mirror of
				https://github.com/raysan5/raylib.git
				synced 2025-10-26 12:27:01 +00:00 
			
		
		
		
	REDESIGN: Move GenTexture*() functions to PBR example #721
Removed functions from rlgl module.
This commit is contained in:
		| @@ -28,6 +28,12 @@ | |||||||
| #define LIGHT_DISTANCE 1000.0f | #define LIGHT_DISTANCE 1000.0f | ||||||
| #define LIGHT_HEIGHT 1.0f | #define LIGHT_HEIGHT 1.0f | ||||||
|  |  | ||||||
|  | // PBR texture maps generation | ||||||
|  | static TextureCubemap GenTextureCubemap(Shader shader, Texture2D panorama, int size, int format); // Generate cubemap (6 faces) from equirectangular (panorama) texture | ||||||
|  | static TextureCubemap GenTextureIrradiance(Shader shader, TextureCubemap cubemap, int size);      // Generate irradiance cubemap using cubemap texture | ||||||
|  | static TextureCubemap GenTexturePrefilter(Shader shader, TextureCubemap cubemap, int size);       // Generate prefilter cubemap using cubemap texture | ||||||
|  | static Texture2D GenTextureBRDF(Shader shader, int size);              // Generate a generic BRDF texture | ||||||
|  |  | ||||||
| // PBR material loading | // PBR material loading | ||||||
| static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); | static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); | ||||||
|  |  | ||||||
| @@ -188,7 +194,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) | |||||||
|     Shader shdrCubemap = LoadShader("resources/shaders/glsl100/cubemap.vs", "resources/shaders/glsl100/cubemap.fs"); |     Shader shdrCubemap = LoadShader("resources/shaders/glsl100/cubemap.vs", "resources/shaders/glsl100/cubemap.fs"); | ||||||
| #endif | #endif | ||||||
|     SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, SHADER_UNIFORM_INT); |     SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, SHADER_UNIFORM_INT); | ||||||
|     TextureCubemap cubemap = rlGenTextureCubemap(shdrCubemap, panorama, CUBEMAP_SIZE, PIXELFORMAT_UNCOMPRESSED_R32G32B32); |     TextureCubemap cubemap = GenTextureCubemap(shdrCubemap, panorama, CUBEMAP_SIZE, PIXELFORMAT_UNCOMPRESSED_R32G32B32); | ||||||
|     UnloadTexture(panorama); |     UnloadTexture(panorama); | ||||||
|     UnloadShader(shdrCubemap); |     UnloadShader(shdrCubemap); | ||||||
|     //-------------------------------------------------------------------------------------------------------- |     //-------------------------------------------------------------------------------------------------------- | ||||||
| @@ -202,7 +208,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) | |||||||
|     Shader shdrIrradiance = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/irradiance.fs"); |     Shader shdrIrradiance = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/irradiance.fs"); | ||||||
| #endif | #endif | ||||||
|     SetShaderValue(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, SHADER_UNIFORM_INT); |     SetShaderValue(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, SHADER_UNIFORM_INT); | ||||||
|     mat.maps[MATERIAL_MAP_IRRADIANCE].texture = rlGenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE); |     mat.maps[MATERIAL_MAP_IRRADIANCE].texture = GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE); | ||||||
|     UnloadShader(shdrIrradiance); |     UnloadShader(shdrIrradiance); | ||||||
|     //-------------------------------------------------------------------------------------------------------- |     //-------------------------------------------------------------------------------------------------------- | ||||||
|      |      | ||||||
| @@ -215,7 +221,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) | |||||||
|     Shader shdrPrefilter = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/prefilter.fs"); |     Shader shdrPrefilter = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/prefilter.fs"); | ||||||
| #endif | #endif | ||||||
|     SetShaderValue(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, SHADER_UNIFORM_INT); |     SetShaderValue(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, SHADER_UNIFORM_INT); | ||||||
|     mat.maps[MATERIAL_MAP_PREFILTER].texture = rlGenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE); |     mat.maps[MATERIAL_MAP_PREFILTER].texture = GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE); | ||||||
|     UnloadTexture(cubemap); |     UnloadTexture(cubemap); | ||||||
|     UnloadShader(shdrPrefilter); |     UnloadShader(shdrPrefilter); | ||||||
|     //-------------------------------------------------------------------------------------------------------- |     //-------------------------------------------------------------------------------------------------------- | ||||||
| @@ -227,9 +233,315 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) | |||||||
| #else | #else | ||||||
|     Shader shdrBRDF = LoadShader("resources/shaders/glsl100/brdf.vs", "resources/shaders/glsl100/brdf.fs"); |     Shader shdrBRDF = LoadShader("resources/shaders/glsl100/brdf.vs", "resources/shaders/glsl100/brdf.fs"); | ||||||
| #endif | #endif | ||||||
|     mat.maps[MATERIAL_MAP_BRDG].texture = rlGenTextureBRDF(shdrBRDF, BRDF_SIZE); |     mat.maps[MATERIAL_MAP_BRDG].texture = GenTextureBRDF(shdrBRDF, BRDF_SIZE); | ||||||
|     UnloadShader(shdrBRDF); |     UnloadShader(shdrBRDF); | ||||||
|     //-------------------------------------------------------------------------------------------------------- |     //-------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|     return mat; |     return mat; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Texture maps generation (PBR) | ||||||
|  | //------------------------------------------------------------------------------------------- | ||||||
|  | // Generate cubemap texture from HDR texture | ||||||
|  | TextureCubemap GenTextureCubemap(Shader shader, Texture2D panorama, int size, int format) | ||||||
|  | { | ||||||
|  |     TextureCubemap cubemap = { 0 }; | ||||||
|  | #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) | ||||||
|  |     rlDisableBackfaceCulling();     // Disable backface culling to render inside the cube | ||||||
|  |  | ||||||
|  |     // STEP 1: Setup framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     unsigned int rbo = rlLoadTextureDepth(size, size, true); | ||||||
|  |     cubemap.id = rlLoadTextureCubemap(NULL, size, format); | ||||||
|  |  | ||||||
|  |     unsigned int fbo = rlLoadFramebuffer(size, size); | ||||||
|  |     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); | ||||||
|  |     rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X, 0); | ||||||
|  |  | ||||||
|  |     // Check if framebuffer is complete with attachments (valid) | ||||||
|  |     if (rlFramebufferComplete(fbo)) TraceLog(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", fbo); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // STEP 2: Draw to framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     // NOTE: Shader is used to convert HDR equirectangular environment map to cubemap equivalent (6 faces) | ||||||
|  |     rlEnableShader(shader.id); | ||||||
|  |  | ||||||
|  |     // Define projection matrix and send it to shader | ||||||
|  |     Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); | ||||||
|  |     rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matFboProjection); | ||||||
|  |  | ||||||
|  |     // Define view matrix for every side of the cubemap | ||||||
|  |     Matrix fboViews[6] = { | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f,  1.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f, -1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f, -1.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f,  1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }) | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | #if !defined(GENTEXTURECUBEMAP_USE_BATCH_SYSTEM) | ||||||
|  |     rlActiveTextureSlot(0); | ||||||
|  |     rlEnableTexture(panorama.id); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |     rlViewport(0, 0, size, size);   // Set viewport to current fbo dimensions | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < 6; i++) | ||||||
|  |     { | ||||||
|  |         rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]); | ||||||
|  |         rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i, 0); | ||||||
|  |  | ||||||
|  |         rlEnableFramebuffer(fbo); | ||||||
|  | #if defined(GENTEXTURECUBEMAP_USE_BATCH_SYSTEM) | ||||||
|  |         rlSetTexture(panorama.id);   // WARNING: It must be called after enabling current framebuffer if using internal batch system! | ||||||
|  | #endif | ||||||
|  |         rlClearScreenBuffers(); | ||||||
|  |         rlLoadDrawCube(); | ||||||
|  |  | ||||||
|  | #if defined(GENTEXTURECUBEMAP_USE_BATCH_SYSTEM) | ||||||
|  |         // Using internal batch system instead of raw OpenGL cube creating+drawing | ||||||
|  |         // NOTE: DrawCubeV() is actually provided by models.c! -> GenTextureCubemap() should be moved to user code! | ||||||
|  |         DrawCubeV(Vector3Zero(), Vector3One(), WHITE); | ||||||
|  |         rlDrawRenderBatch(RLGL.currentBatch); | ||||||
|  | #endif | ||||||
|  |     } | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // STEP 3: Unload framebuffer and reset state | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     rlDisableShader();          // Unbind shader | ||||||
|  |     rlDisableTexture();         // Unbind texture | ||||||
|  |     rlDisableFramebuffer();     // Unbind framebuffer | ||||||
|  |     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) | ||||||
|  |  | ||||||
|  |     // Reset viewport dimensions to default | ||||||
|  |     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); | ||||||
|  |     rlEnableBackfaceCulling(); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     cubemap.width = size; | ||||||
|  |     cubemap.height = size; | ||||||
|  |     cubemap.mipmaps = 1; | ||||||
|  |     cubemap.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; | ||||||
|  | #endif | ||||||
|  |     return cubemap; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Generate irradiance texture using cubemap data | ||||||
|  | TextureCubemap GenTextureIrradiance(Shader shader, TextureCubemap cubemap, int size) | ||||||
|  | { | ||||||
|  |     TextureCubemap irradiance = { 0 }; | ||||||
|  |  | ||||||
|  | #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) | ||||||
|  |     rlDisableBackfaceCulling();     // Disable backface culling to render inside the cube | ||||||
|  |  | ||||||
|  |     // STEP 1: Setup framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     unsigned int rbo = rlLoadTextureDepth(size, size, true); | ||||||
|  |     irradiance.id = rlLoadTextureCubemap(NULL, size, PIXELFORMAT_UNCOMPRESSED_R32G32B32); | ||||||
|  |  | ||||||
|  |     unsigned int fbo = rlLoadFramebuffer(size, size); | ||||||
|  |     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); | ||||||
|  |     rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X, 0); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // STEP 2: Draw to framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     // NOTE: Shader is used to solve diffuse integral by convolution to create an irradiance cubemap | ||||||
|  |     rlEnableShader(shader.id); | ||||||
|  |  | ||||||
|  |     // Define projection matrix and send it to shader | ||||||
|  |     Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); | ||||||
|  |     rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matFboProjection); | ||||||
|  |  | ||||||
|  |     // Define view matrix for every side of the cubemap | ||||||
|  |     Matrix fboViews[6] = { | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f,  1.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f, -1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f, -1.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f,  1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }) | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     rlActiveTextureSlot(0); | ||||||
|  |     rlEnableTextureCubemap(cubemap.id); | ||||||
|  |  | ||||||
|  |     rlViewport(0, 0, size, size);   // Set viewport to current fbo dimensions | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < 6; i++) | ||||||
|  |     { | ||||||
|  |         rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]); | ||||||
|  |         rlFramebufferAttach(fbo, irradiance.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i, 0); | ||||||
|  |  | ||||||
|  |         rlEnableFramebuffer(fbo); | ||||||
|  |         rlClearScreenBuffers(); | ||||||
|  |         rlLoadDrawCube(); | ||||||
|  |     } | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // STEP 3: Unload framebuffer and reset state | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     rlDisableShader();          // Unbind shader | ||||||
|  |     rlDisableTexture();         // Unbind texture | ||||||
|  |     rlDisableFramebuffer();     // Unbind framebuffer | ||||||
|  |     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) | ||||||
|  |  | ||||||
|  |     // Reset viewport dimensions to default | ||||||
|  |     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); | ||||||
|  |     rlEnableBackfaceCulling(); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     irradiance.width = size; | ||||||
|  |     irradiance.height = size; | ||||||
|  |     irradiance.mipmaps = 1; | ||||||
|  |     irradiance.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; | ||||||
|  | #endif | ||||||
|  |     return irradiance; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Generate prefilter texture using cubemap data | ||||||
|  | TextureCubemap GenTexturePrefilter(Shader shader, TextureCubemap cubemap, int size) | ||||||
|  | { | ||||||
|  |     TextureCubemap prefilter = { 0 }; | ||||||
|  |  | ||||||
|  | #if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) | ||||||
|  |     rlDisableBackfaceCulling();     // Disable backface culling to render inside the cube | ||||||
|  |  | ||||||
|  |     // STEP 1: Setup framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     unsigned int rbo = rlLoadTextureDepth(size, size, true); | ||||||
|  |     prefilter.id = rlLoadTextureCubemap(NULL, size, PIXELFORMAT_UNCOMPRESSED_R32G32B32); | ||||||
|  |     rlTextureParameters(prefilter.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_MIP_LINEAR); | ||||||
|  |  | ||||||
|  |     unsigned int fbo = rlLoadFramebuffer(size, size); | ||||||
|  |     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); | ||||||
|  |     rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X, 0); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // Generate mipmaps for the prefiltered HDR texture | ||||||
|  |     //glGenerateMipmap(GL_TEXTURE_CUBE_MAP);    // TODO! | ||||||
|  |  | ||||||
|  |     // STEP 2: Draw to framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     // NOTE: Shader is used to prefilter HDR and store data into mipmap levels | ||||||
|  |  | ||||||
|  |     // Define projection matrix and send it to shader | ||||||
|  |     Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); | ||||||
|  |     rlEnableShader(shader.id); | ||||||
|  |     rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], fboProjection); | ||||||
|  |  | ||||||
|  |     // Define view matrix for every side of the cubemap | ||||||
|  |     Matrix fboViews[6] = { | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f,  1.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f, -1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f, -1.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f,  1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), | ||||||
|  |         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }) | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     rlActiveTextureSlot(0); | ||||||
|  |     rlEnableTextureCubemap(cubemap.id); | ||||||
|  |  | ||||||
|  |     // TODO: Locations should be taken out of this function... too shader dependant... | ||||||
|  |     int roughnessLoc = rlGetLocationUniform(shader.id, "roughness"); | ||||||
|  |  | ||||||
|  |     rlEnableFramebuffer(fbo); | ||||||
|  |  | ||||||
|  |     #define MAX_MIPMAP_LEVELS   5   // Max number of prefilter texture mipmaps | ||||||
|  |  | ||||||
|  |     for (int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) | ||||||
|  |     { | ||||||
|  |         // Resize framebuffer according to mip-level size. | ||||||
|  |         unsigned int mipWidth  = size*(int)powf(0.5f, (float)mip); | ||||||
|  |         unsigned int mipHeight = size*(int)powf(0.5f, (float)mip); | ||||||
|  |  | ||||||
|  |         rlViewport(0, 0, mipWidth, mipHeight); | ||||||
|  |  | ||||||
|  |         //glBindRenderbuffer(GL_RENDERBUFFER, rbo); | ||||||
|  |         //glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); | ||||||
|  |  | ||||||
|  |         float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); | ||||||
|  |         rlSetUniform(roughnessLoc, &roughness, SHADER_UNIFORM_FLOAT, 1); | ||||||
|  |  | ||||||
|  |         for (int i = 0; i < 6; i++) | ||||||
|  |         { | ||||||
|  |             rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]); | ||||||
|  |             rlFramebufferAttach(fbo, prefilter.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i, mip); | ||||||
|  |              | ||||||
|  |             rlClearScreenBuffers(); | ||||||
|  |             rlLoadDrawCube(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // STEP 3: Unload framebuffer and reset state | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     rlDisableShader();          // Unbind shader | ||||||
|  |     rlDisableTexture();         // Unbind texture | ||||||
|  |     rlDisableFramebuffer();     // Unbind framebuffer | ||||||
|  |     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) | ||||||
|  |  | ||||||
|  |     // Reset viewport dimensions to default | ||||||
|  |     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); | ||||||
|  |     rlEnableBackfaceCulling(); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     prefilter.width = size; | ||||||
|  |     prefilter.height = size; | ||||||
|  |     prefilter.mipmaps = MAX_MIPMAP_LEVELS; | ||||||
|  |     prefilter.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; | ||||||
|  | #endif | ||||||
|  |     return prefilter; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Generate BRDF texture using cubemap data | ||||||
|  | // TODO: Review implementation: https://github.com/HectorMF/BRDFGenerator | ||||||
|  | Texture2D GenTextureBRDF(Shader shader, int size) | ||||||
|  | { | ||||||
|  |     Texture2D brdf = { 0 }; | ||||||
|  | #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) | ||||||
|  |     // STEP 1: Setup framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     unsigned int rbo = rlLoadTextureDepth(size, size, true); | ||||||
|  |     brdf.id = rlLoadTexture(NULL, size, size, PIXELFORMAT_UNCOMPRESSED_R32G32B32, 1); | ||||||
|  |  | ||||||
|  |     unsigned int fbo = rlLoadFramebuffer(size, size); | ||||||
|  |     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); | ||||||
|  |     rlFramebufferAttach(fbo, brdf.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // STEP 2: Draw to framebuffer | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     // NOTE: Render BRDF LUT into a quad using FBO | ||||||
|  |     rlEnableShader(shader.id); | ||||||
|  |  | ||||||
|  |     rlViewport(0, 0, size, size); | ||||||
|  |  | ||||||
|  |     rlEnableFramebuffer(fbo); | ||||||
|  |     rlClearScreenBuffers(); | ||||||
|  |  | ||||||
|  |     rlLoadDrawQuad(); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     // STEP 3: Unload framebuffer and reset state | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |     rlDisableShader();          // Unbind shader | ||||||
|  |     rlDisableTexture();         // Unbind texture | ||||||
|  |     rlDisableFramebuffer();     // Unbind framebuffer | ||||||
|  |     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) | ||||||
|  |  | ||||||
|  |     // Reset viewport dimensions to default | ||||||
|  |     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); | ||||||
|  |     //------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
|  |     brdf.width = size; | ||||||
|  |     brdf.height = size; | ||||||
|  |     brdf.mipmaps = 1; | ||||||
|  |     brdf.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; | ||||||
|  | #endif | ||||||
|  |     return brdf; | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										523
									
								
								src/rlgl.h
									
									
									
									
									
								
							
							
						
						
									
										523
									
								
								src/rlgl.h
									
									
									
									
									
								
							| @@ -624,7 +624,7 @@ RLAPI unsigned char *rlReadScreenPixels(int width, int height);           // Rea | |||||||
|  |  | ||||||
| // Framebuffer management (fbo) | // Framebuffer management (fbo) | ||||||
| RLAPI unsigned int rlLoadFramebuffer(int width, int height);              // Load an empty framebuffer | RLAPI unsigned int rlLoadFramebuffer(int width, int height);              // Load an empty framebuffer | ||||||
| RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType);  // Attach texture/renderbuffer to a framebuffer | RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel);  // Attach texture/renderbuffer to a framebuffer | ||||||
| RLAPI bool rlFramebufferComplete(unsigned int id);                        // Verify framebuffer is complete | RLAPI bool rlFramebufferComplete(unsigned int id);                        // Verify framebuffer is complete | ||||||
| RLAPI void rlUnloadFramebuffer(unsigned int id);                          // Delete framebuffer from GPU | RLAPI void rlUnloadFramebuffer(unsigned int id);                          // Delete framebuffer from GPU | ||||||
|  |  | ||||||
| @@ -651,13 +651,9 @@ RLAPI void rlSetMatrixModelview(Matrix view);                             // Set | |||||||
| RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left);        // Set eyes projection matrices for stereo rendering | RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left);        // Set eyes projection matrices for stereo rendering | ||||||
| RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left);        // Set eyes view offsets matrices for stereo rendering | RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left);        // Set eyes view offsets matrices for stereo rendering | ||||||
|  |  | ||||||
| // Texture maps generation (PBR) | // Quick and dirty cube/quad buffers load->draw->unload | ||||||
| // TODO: Redesign or remove to avoid requiring external shaders | RLAPI void rlLoadDrawCube(void);     // Load and draw a cube | ||||||
| RLAPI TextureCubemap rlGenTextureCubemap(Shader shader, Texture2D panorama, int size, int format); // Generate cubemap (6 faces) from equirectangular (panorama) texture | RLAPI void rlLoadDrawQuad(void);     // Load and draw a quad | ||||||
| RLAPI TextureCubemap rlGenTextureIrradiance(Shader shader, TextureCubemap cubemap, int size);      // Generate irradiance cubemap using cubemap texture |  | ||||||
| RLAPI TextureCubemap rlGenTexturePrefilter(Shader shader, TextureCubemap cubemap, int size);       // Generate prefilter cubemap using cubemap texture |  | ||||||
| RLAPI Texture2D rlGenTextureBRDF(Shader shader, int size);              // Generate a generic BRDF texture |  | ||||||
|  |  | ||||||
| #if defined(__cplusplus) | #if defined(__cplusplus) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -912,9 +908,6 @@ static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL; | |||||||
| #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) | #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) | ||||||
| static Shader rlLoadShaderDefault(void);    // Load default shader (just vertex positioning and texture coloring) | static Shader rlLoadShaderDefault(void);    // Load default shader (just vertex positioning and texture coloring) | ||||||
| static void rlUnloadShaderDefault(void);    // Unload default shader | static void rlUnloadShaderDefault(void);    // Unload default shader | ||||||
|  |  | ||||||
| static void rlGenDrawCube(void);            // Generate and draw cube |  | ||||||
| static void rlGenDrawQuad(void);            // Generate and draw quad |  | ||||||
| #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 | #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 | ||||||
| #if defined(GRAPHICS_API_OPENGL_11) | #if defined(GRAPHICS_API_OPENGL_11) | ||||||
| static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight);   // Generate mipmaps data on CPU side | static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight);   // Generate mipmaps data on CPU side | ||||||
| @@ -2966,7 +2959,7 @@ unsigned int rlLoadFramebuffer(int width, int height) | |||||||
|  |  | ||||||
| // Attach color buffer texture to an fbo (unloads previous attachment) | // Attach color buffer texture to an fbo (unloads previous attachment) | ||||||
| // NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture | // NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture | ||||||
| void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType) | void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel) | ||||||
| { | { | ||||||
| #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT) | #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT) | ||||||
|     glBindFramebuffer(GL_FRAMEBUFFER, fboId); |     glBindFramebuffer(GL_FRAMEBUFFER, fboId); | ||||||
| @@ -2982,20 +2975,20 @@ void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, | |||||||
|         case RL_ATTACHMENT_COLOR_CHANNEL6: |         case RL_ATTACHMENT_COLOR_CHANNEL6: | ||||||
|         case RL_ATTACHMENT_COLOR_CHANNEL7: |         case RL_ATTACHMENT_COLOR_CHANNEL7: | ||||||
|         { |         { | ||||||
|             if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, 0); |             if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel); | ||||||
|             else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId); |             else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId); | ||||||
|             else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, 0); |             else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel); | ||||||
|  |  | ||||||
|         } break; |         } break; | ||||||
|         case RL_ATTACHMENT_DEPTH: |         case RL_ATTACHMENT_DEPTH: | ||||||
|         { |         { | ||||||
|             if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, 0); |             if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel); | ||||||
|             else if (texType == RL_ATTACHMENT_RENDERBUFFER)  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId); |             else if (texType == RL_ATTACHMENT_RENDERBUFFER)  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId); | ||||||
|  |  | ||||||
|         } break; |         } break; | ||||||
|         case RL_ATTACHMENT_STENCIL: |         case RL_ATTACHMENT_STENCIL: | ||||||
|         { |         { | ||||||
|             if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, 0); |             if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel); | ||||||
|             else if (texType == RL_ATTACHMENT_RENDERBUFFER)  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId); |             else if (texType == RL_ATTACHMENT_RENDERBUFFER)  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId); | ||||||
|  |  | ||||||
|         } break; |         } break; | ||||||
| @@ -3623,312 +3616,119 @@ void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| // Texture maps generation (PBR) | // Load and draw a 1x1 XY quad in NDC | ||||||
| //------------------------------------------------------------------------------------------- | void rlLoadDrawQuad(void) | ||||||
| // Generate cubemap texture from HDR texture |  | ||||||
| TextureCubemap rlGenTextureCubemap(Shader shader, Texture2D panorama, int size, int format) |  | ||||||
| { | { | ||||||
|     TextureCubemap cubemap = { 0 }; |     unsigned int quadVAO = 0; | ||||||
| #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |     unsigned int quadVBO = 0; | ||||||
|     rlDisableBackfaceCulling();     // Disable backface culling to render inside the cube |  | ||||||
|  |  | ||||||
|     // STEP 1: Setup framebuffer |     float vertices[] = { | ||||||
|     //------------------------------------------------------------------------------------------ |          // Positions         Texcoords | ||||||
|     unsigned int rbo = rlLoadTextureDepth(size, size, true); |         -1.0f,  1.0f, 0.0f,   0.0f, 1.0f, | ||||||
|     cubemap.id = rlLoadTextureCubemap(NULL, size, format); |         -1.0f, -1.0f, 0.0f,   0.0f, 0.0f, | ||||||
|  |          1.0f,  1.0f, 0.0f,   1.0f, 1.0f, | ||||||
|     unsigned int fbo = rlLoadFramebuffer(size, size); |          1.0f, -1.0f, 0.0f,   1.0f, 0.0f, | ||||||
|     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER); |  | ||||||
|     rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X); |  | ||||||
|  |  | ||||||
|     // Check if framebuffer is complete with attachments (valid) |  | ||||||
|     if (rlFramebufferComplete(fbo)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", fbo); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     // STEP 2: Draw to framebuffer |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     // NOTE: Shader is used to convert HDR equirectangular environment map to cubemap equivalent (6 faces) |  | ||||||
|     rlEnableShader(shader.id); |  | ||||||
|  |  | ||||||
|     // Define projection matrix and send it to shader |  | ||||||
|     Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); |  | ||||||
|     rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matFboProjection); |  | ||||||
|  |  | ||||||
|     // Define view matrix for every side of the cubemap |  | ||||||
|     Matrix fboViews[6] = { |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f,  1.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f, -1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f, -1.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f,  1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }) |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| #if !defined(GENTEXTURECUBEMAP_USE_BATCH_SYSTEM) |     // Gen VAO to contain VBO | ||||||
|     rlActiveTextureSlot(0); |     glGenVertexArrays(1, &quadVAO); | ||||||
|     rlEnableTexture(panorama.id); |     glBindVertexArray(quadVAO); | ||||||
| #endif |  | ||||||
|  |  | ||||||
|     rlViewport(0, 0, size, size);   // Set viewport to current fbo dimensions |     // Gen and fill vertex buffer (VBO) | ||||||
|  |     glGenBuffers(1, &quadVBO); | ||||||
|  |     glBindBuffer(GL_ARRAY_BUFFER, quadVBO); | ||||||
|  |     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); | ||||||
|  |  | ||||||
|     for (int i = 0; i < 6; i++) |     // Bind vertex attributes (position, texcoords) | ||||||
|     { |     glEnableVertexAttribArray(0); | ||||||
|         rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]); |     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); // Positions | ||||||
|         rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i); |     glEnableVertexAttribArray(1); | ||||||
|  |     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Texcoords | ||||||
|  |  | ||||||
|         rlEnableFramebuffer(fbo); |     // Draw quad | ||||||
| #if defined(GENTEXTURECUBEMAP_USE_BATCH_SYSTEM) |     glBindVertexArray(quadVAO); | ||||||
|         rlSetTexture(panorama.id);   // WARNING: It must be called after enabling current framebuffer if using internal batch system! |     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||||||
| #endif |     glBindVertexArray(0); | ||||||
|         rlClearScreenBuffers(); |  | ||||||
|         rlGenDrawCube(); |  | ||||||
|  |  | ||||||
| #if defined(GENTEXTURECUBEMAP_USE_BATCH_SYSTEM) |     // Delete buffers (VBO and VAO) | ||||||
|         // Using internal batch system instead of raw OpenGL cube creating+drawing |     glDeleteBuffers(1, &quadVBO); | ||||||
|         // NOTE: DrawCubeV() is actually provided by models.c! -> rlGenTextureCubemap() should be moved to user code! |     glDeleteVertexArrays(1, &quadVAO); | ||||||
|         DrawCubeV(Vector3Zero(), Vector3One(), WHITE); |  | ||||||
|         rlDrawRenderBatch(RLGL.currentBatch); |  | ||||||
| #endif |  | ||||||
|     } |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     // STEP 3: Unload framebuffer and reset state |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     rlDisableShader();          // Unbind shader |  | ||||||
|     rlDisableTexture();         // Unbind texture |  | ||||||
|     rlDisableFramebuffer();     // Unbind framebuffer |  | ||||||
|     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) |  | ||||||
|  |  | ||||||
|     // Reset viewport dimensions to default |  | ||||||
|     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); |  | ||||||
|     rlEnableBackfaceCulling(); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     cubemap.width = size; |  | ||||||
|     cubemap.height = size; |  | ||||||
|     cubemap.mipmaps = 1; |  | ||||||
|     cubemap.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; |  | ||||||
| #endif |  | ||||||
|     return cubemap; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Generate irradiance texture using cubemap data | // Load and draw a 1x1 3D cube in NDC | ||||||
| TextureCubemap rlGenTextureIrradiance(Shader shader, TextureCubemap cubemap, int size) | void rlLoadDrawCube(void) | ||||||
| { | { | ||||||
|     TextureCubemap irradiance = { 0 }; |     unsigned int cubeVAO = 0; | ||||||
|  |     unsigned int cubeVBO = 0; | ||||||
|  |  | ||||||
| #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |     float vertices[] = { | ||||||
|     rlDisableBackfaceCulling();     // Disable backface culling to render inside the cube |          // Positions          Normals               Texcoords | ||||||
|  |         -1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f, | ||||||
|     // STEP 1: Setup framebuffer |          1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f, | ||||||
|     //------------------------------------------------------------------------------------------ |          1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 0.0f, | ||||||
|     unsigned int rbo = rlLoadTextureDepth(size, size, true); |          1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f, | ||||||
|     irradiance.id = rlLoadTextureCubemap(NULL, size, PIXELFORMAT_UNCOMPRESSED_R32G32B32); |         -1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f, | ||||||
|  |         -1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 1.0f, | ||||||
|     unsigned int fbo = rlLoadFramebuffer(size, size); |         -1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f, | ||||||
|     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER); |          1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 0.0f, | ||||||
|     rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X); |          1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f, | ||||||
|     //------------------------------------------------------------------------------------------ |          1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f, | ||||||
|  |         -1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 1.0f, | ||||||
|     // STEP 2: Draw to framebuffer |         -1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f, | ||||||
|     //------------------------------------------------------------------------------------------ |         -1.0f,  1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 0.0f, | ||||||
|     // NOTE: Shader is used to solve diffuse integral by convolution to create an irradiance cubemap |         -1.0f,  1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 1.0f, | ||||||
|     rlEnableShader(shader.id); |         -1.0f, -1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 1.0f, | ||||||
|  |         -1.0f, -1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 1.0f, | ||||||
|     // Define projection matrix and send it to shader |         -1.0f, -1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 0.0f, | ||||||
|     Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); |         -1.0f,  1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 0.0f, | ||||||
|     rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matFboProjection); |          1.0f,  1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 0.0f, | ||||||
|  |          1.0f, -1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 1.0f, | ||||||
|     // Define view matrix for every side of the cubemap |          1.0f,  1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 1.0f, | ||||||
|     Matrix fboViews[6] = { |          1.0f, -1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 1.0f, | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |          1.0f,  1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 0.0f, | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |          1.0f, -1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 0.0f, | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f,  1.0f }), |         -1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 1.0f, | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f, -1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f, -1.0f }), |          1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 1.0f, | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f,  1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |          1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 0.0f, | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }) |          1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 0.0f, | ||||||
|  |         -1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 0.0f, | ||||||
|  |         -1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 1.0f, | ||||||
|  |         -1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 1.0f, | ||||||
|  |          1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 0.0f, | ||||||
|  |          1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 1.0f, | ||||||
|  |          1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 0.0f, | ||||||
|  |         -1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 1.0f, | ||||||
|  |         -1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 0.0f | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     rlActiveTextureSlot(0); |     // Gen VAO to contain VBO | ||||||
|     rlEnableTextureCubemap(cubemap.id); |     glGenVertexArrays(1, &cubeVAO); | ||||||
|  |     glBindVertexArray(cubeVAO); | ||||||
|  |  | ||||||
|     rlViewport(0, 0, size, size);   // Set viewport to current fbo dimensions |     // Gen and fill vertex buffer (VBO) | ||||||
|  |     glGenBuffers(1, &cubeVBO); | ||||||
|  |     glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); | ||||||
|  |     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | ||||||
|  |  | ||||||
|     for (int i = 0; i < 6; i++) |     // Bind vertex attributes (position, normals, texcoords) | ||||||
|     { |     glBindVertexArray(cubeVAO); | ||||||
|         rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]); |     glEnableVertexAttribArray(0); | ||||||
|         rlFramebufferAttach(fbo, irradiance.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i); |     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); // Positions | ||||||
|  |     glEnableVertexAttribArray(1); | ||||||
|  |     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); // Normals | ||||||
|  |     glEnableVertexAttribArray(2); | ||||||
|  |     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); // Texcoords | ||||||
|  |     glBindBuffer(GL_ARRAY_BUFFER, 0); | ||||||
|  |     glBindVertexArray(0); | ||||||
|  |  | ||||||
|         rlEnableFramebuffer(fbo); |     // Draw cube | ||||||
|         rlClearScreenBuffers(); |     glBindVertexArray(cubeVAO); | ||||||
|         rlGenDrawCube(); |     glDrawArrays(GL_TRIANGLES, 0, 36); | ||||||
|     } |     glBindVertexArray(0); | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     // STEP 3: Unload framebuffer and reset state |     // Delete VBO and VAO | ||||||
|     //------------------------------------------------------------------------------------------ |     glDeleteBuffers(1, &cubeVBO); | ||||||
|     rlDisableShader();          // Unbind shader |     glDeleteVertexArrays(1, &cubeVAO); | ||||||
|     rlDisableTexture();         // Unbind texture |  | ||||||
|     rlDisableFramebuffer();     // Unbind framebuffer |  | ||||||
|     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) |  | ||||||
|  |  | ||||||
|     // Reset viewport dimensions to default |  | ||||||
|     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); |  | ||||||
|     rlEnableBackfaceCulling(); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     irradiance.width = size; |  | ||||||
|     irradiance.height = size; |  | ||||||
|     irradiance.mipmaps = 1; |  | ||||||
|     irradiance.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; |  | ||||||
| #endif |  | ||||||
|     return irradiance; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Generate prefilter texture using cubemap data |  | ||||||
| TextureCubemap rlGenTexturePrefilter(Shader shader, TextureCubemap cubemap, int size) |  | ||||||
| { |  | ||||||
|     TextureCubemap prefilter = { 0 }; |  | ||||||
|  |  | ||||||
| #if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) |  | ||||||
|     rlDisableBackfaceCulling();     // Disable backface culling to render inside the cube |  | ||||||
|  |  | ||||||
|     // STEP 1: Setup framebuffer |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     unsigned int rbo = rlLoadTextureDepth(size, size, true); |  | ||||||
|     prefilter.id = rlLoadTextureCubemap(NULL, size, PIXELFORMAT_UNCOMPRESSED_R32G32B32); |  | ||||||
|     rlTextureParameters(prefilter.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_MIP_LINEAR); |  | ||||||
|  |  | ||||||
|     unsigned int fbo = rlLoadFramebuffer(size, size); |  | ||||||
|     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER); |  | ||||||
|     rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     // Generate mipmaps for the prefiltered HDR texture |  | ||||||
|     glGenerateMipmap(GL_TEXTURE_CUBE_MAP); |  | ||||||
|  |  | ||||||
|     // STEP 2: Draw to framebuffer |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     // NOTE: Shader is used to prefilter HDR and store data into mipmap levels |  | ||||||
|  |  | ||||||
|     // Define projection matrix and send it to shader |  | ||||||
|     Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); |  | ||||||
|     rlEnableShader(shader.id); |  | ||||||
|     rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], fboProjection); |  | ||||||
|  |  | ||||||
|     // Define view matrix for every side of the cubemap |  | ||||||
|     Matrix fboViews[6] = { |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f,  0.0f,  0.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f,  1.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f, -1.0f,  0.0f }, (Vector3){ 0.0f,  0.0f, -1.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f,  1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }), |  | ||||||
|         MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){  0.0f,  0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f,  0.0f }) |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     rlActiveTextureSlot(0); |  | ||||||
|     rlEnableTextureCubemap(cubemap.id); |  | ||||||
|  |  | ||||||
|     // TODO: Locations should be taken out of this function... too shader dependant... |  | ||||||
|     int roughnessLoc = rlGetLocationUniform(shader.id, "roughness"); |  | ||||||
|  |  | ||||||
|     rlEnableFramebuffer(fbo); |  | ||||||
|  |  | ||||||
|     #define MAX_MIPMAP_LEVELS   5   // Max number of prefilter texture mipmaps |  | ||||||
|  |  | ||||||
|     for (int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) |  | ||||||
|     { |  | ||||||
|         // Resize framebuffer according to mip-level size. |  | ||||||
|         unsigned int mipWidth  = size*(int)powf(0.5f, (float)mip); |  | ||||||
|         unsigned int mipHeight = size*(int)powf(0.5f, (float)mip); |  | ||||||
|  |  | ||||||
|         rlViewport(0, 0, mipWidth, mipHeight); |  | ||||||
|  |  | ||||||
|         glBindRenderbuffer(GL_RENDERBUFFER, rbo); |  | ||||||
|         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); |  | ||||||
|  |  | ||||||
|         float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); |  | ||||||
|         rlSetUniform(roughnessLoc, &roughness, SHADER_UNIFORM_FLOAT); |  | ||||||
|  |  | ||||||
|         for (int i = 0; i < 6; i++) |  | ||||||
|         { |  | ||||||
|             //rlEnableShader(shader.id); |  | ||||||
|             rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]); |  | ||||||
|             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); |  | ||||||
|             //rlFramebufferAttach(fbo, irradiance.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i);  // TODO: Support mip levels? |  | ||||||
|  |  | ||||||
|             rlEnableFramebuffer(fbo); |  | ||||||
|             rlClearScreenBuffers(); |  | ||||||
|             rlGenDrawCube(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     // STEP 3: Unload framebuffer and reset state |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     rlDisableShader();          // Unbind shader |  | ||||||
|     rlDisableTexture();         // Unbind texture |  | ||||||
|     rlDisableFramebuffer();     // Unbind framebuffer |  | ||||||
|     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) |  | ||||||
|  |  | ||||||
|     // Reset viewport dimensions to default |  | ||||||
|     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); |  | ||||||
|     rlEnableBackfaceCulling(); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     prefilter.width = size; |  | ||||||
|     prefilter.height = size; |  | ||||||
|     //prefilter.mipmaps = 1 + (int)floor(log(size)/log(2)); // MAX_MIPMAP_LEVELS |  | ||||||
|     //prefilter.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; |  | ||||||
| #endif |  | ||||||
|     return prefilter; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Generate BRDF texture using cubemap data |  | ||||||
| // TODO: Review implementation: https://github.com/HectorMF/BRDFGenerator |  | ||||||
| Texture2D rlGenTextureBRDF(Shader shader, int size) |  | ||||||
| { |  | ||||||
|     Texture2D brdf = { 0 }; |  | ||||||
| #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |  | ||||||
|     // STEP 1: Setup framebuffer |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     unsigned int rbo = rlLoadTextureDepth(size, size, true); |  | ||||||
|     brdf.id = rlLoadTexture(NULL, size, size, PIXELFORMAT_UNCOMPRESSED_R32G32B32, 1); |  | ||||||
|  |  | ||||||
|     unsigned int fbo = rlLoadFramebuffer(size, size); |  | ||||||
|     rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER); |  | ||||||
|     rlFramebufferAttach(fbo, brdf.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     // STEP 2: Draw to framebuffer |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     // NOTE: Render BRDF LUT into a quad using FBO |  | ||||||
|     rlEnableShader(shader.id); |  | ||||||
|  |  | ||||||
|     rlViewport(0, 0, size, size); |  | ||||||
|  |  | ||||||
|     rlEnableFramebuffer(fbo); |  | ||||||
|     rlClearScreenBuffers(); |  | ||||||
|     rlGenDrawQuad(); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     // STEP 3: Unload framebuffer and reset state |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|     rlDisableShader();          // Unbind shader |  | ||||||
|     rlDisableTexture();         // Unbind texture |  | ||||||
|     rlDisableFramebuffer();     // Unbind framebuffer |  | ||||||
|     rlUnloadFramebuffer(fbo);   // Unload framebuffer (and automatically attached depth texture/renderbuffer) |  | ||||||
|  |  | ||||||
|     // Reset viewport dimensions to default |  | ||||||
|     rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); |  | ||||||
|     //------------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
|     brdf.width = size; |  | ||||||
|     brdf.height = size; |  | ||||||
|     brdf.mipmaps = 1; |  | ||||||
|     brdf.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; |  | ||||||
| #endif |  | ||||||
|     return brdf; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- | //---------------------------------------------------------------------------------- | ||||||
| @@ -4048,121 +3848,6 @@ static void rlUnloadShaderDefault(void) | |||||||
|  |  | ||||||
|     RL_FREE(RLGL.State.defaultShader.locs); |     RL_FREE(RLGL.State.defaultShader.locs); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Renders a 1x1 XY quad in NDC |  | ||||||
| static void rlGenDrawQuad(void) |  | ||||||
| { |  | ||||||
|     unsigned int quadVAO = 0; |  | ||||||
|     unsigned int quadVBO = 0; |  | ||||||
|  |  | ||||||
|     float vertices[] = { |  | ||||||
|          // Positions         Texcoords |  | ||||||
|         -1.0f,  1.0f, 0.0f,   0.0f, 1.0f, |  | ||||||
|         -1.0f, -1.0f, 0.0f,   0.0f, 0.0f, |  | ||||||
|          1.0f,  1.0f, 0.0f,   1.0f, 1.0f, |  | ||||||
|          1.0f, -1.0f, 0.0f,   1.0f, 0.0f, |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // Gen VAO to contain VBO |  | ||||||
|     glGenVertexArrays(1, &quadVAO); |  | ||||||
|     glBindVertexArray(quadVAO); |  | ||||||
|  |  | ||||||
|     // Gen and fill vertex buffer (VBO) |  | ||||||
|     glGenBuffers(1, &quadVBO); |  | ||||||
|     glBindBuffer(GL_ARRAY_BUFFER, quadVBO); |  | ||||||
|     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); |  | ||||||
|  |  | ||||||
|     // Bind vertex attributes (position, texcoords) |  | ||||||
|     glEnableVertexAttribArray(0); |  | ||||||
|     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); // Positions |  | ||||||
|     glEnableVertexAttribArray(1); |  | ||||||
|     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Texcoords |  | ||||||
|  |  | ||||||
|     // Draw quad |  | ||||||
|     glBindVertexArray(quadVAO); |  | ||||||
|     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |  | ||||||
|     glBindVertexArray(0); |  | ||||||
|  |  | ||||||
|     // Delete buffers (VBO and VAO) |  | ||||||
|     glDeleteBuffers(1, &quadVBO); |  | ||||||
|     glDeleteVertexArrays(1, &quadVAO); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Renders a 1x1 3D cube in NDC |  | ||||||
| static void rlGenDrawCube(void) |  | ||||||
| { |  | ||||||
|     unsigned int cubeVAO = 0; |  | ||||||
|     unsigned int cubeVBO = 0; |  | ||||||
|  |  | ||||||
|     float vertices[] = { |  | ||||||
|          // Positions          Normals               Texcoords |  | ||||||
|         -1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f, |  | ||||||
|          1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f, |  | ||||||
|          1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 0.0f, |  | ||||||
|          1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f, |  | ||||||
|         -1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f, |  | ||||||
|         -1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 1.0f, |  | ||||||
|         -1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f, |  | ||||||
|          1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 0.0f, |  | ||||||
|          1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f, |  | ||||||
|          1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f, |  | ||||||
|         -1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 1.0f, |  | ||||||
|         -1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f, |  | ||||||
|         -1.0f,  1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|         -1.0f,  1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 1.0f, |  | ||||||
|         -1.0f, -1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|         -1.0f, -1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|         -1.0f, -1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 0.0f, |  | ||||||
|         -1.0f,  1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|          1.0f,  1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|          1.0f, -1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|          1.0f,  1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 1.0f, |  | ||||||
|          1.0f, -1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|          1.0f,  1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|          1.0f, -1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 0.0f, |  | ||||||
|         -1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|          1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 1.0f, |  | ||||||
|          1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|          1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|         -1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 0.0f, |  | ||||||
|         -1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|         -1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|          1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|          1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 1.0f, |  | ||||||
|          1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 0.0f, |  | ||||||
|         -1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 1.0f, |  | ||||||
|         -1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 0.0f |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // Gen VAO to contain VBO |  | ||||||
|     glGenVertexArrays(1, &cubeVAO); |  | ||||||
|     glBindVertexArray(cubeVAO); |  | ||||||
|  |  | ||||||
|     // Gen and fill vertex buffer (VBO) |  | ||||||
|     glGenBuffers(1, &cubeVBO); |  | ||||||
|     glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); |  | ||||||
|     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); |  | ||||||
|  |  | ||||||
|     // Bind vertex attributes (position, normals, texcoords) |  | ||||||
|     glBindVertexArray(cubeVAO); |  | ||||||
|     glEnableVertexAttribArray(0); |  | ||||||
|     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); // Positions |  | ||||||
|     glEnableVertexAttribArray(1); |  | ||||||
|     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); // Normals |  | ||||||
|     glEnableVertexAttribArray(2); |  | ||||||
|     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); // Texcoords |  | ||||||
|     glBindBuffer(GL_ARRAY_BUFFER, 0); |  | ||||||
|     glBindVertexArray(0); |  | ||||||
|  |  | ||||||
|     // Draw cube |  | ||||||
|     glBindVertexArray(cubeVAO); |  | ||||||
|     glDrawArrays(GL_TRIANGLES, 0, 36); |  | ||||||
|     glBindVertexArray(0); |  | ||||||
|  |  | ||||||
|     // Delete VBO and VAO |  | ||||||
|     glDeleteBuffers(1, &cubeVBO); |  | ||||||
|     glDeleteVertexArrays(1, &cubeVAO); |  | ||||||
| } |  | ||||||
| #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 | #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 | ||||||
|  |  | ||||||
| #if defined(GRAPHICS_API_OPENGL_11) | #if defined(GRAPHICS_API_OPENGL_11) | ||||||
|   | |||||||
| @@ -2852,8 +2852,8 @@ RenderTexture2D LoadRenderTexture(int width, int height) | |||||||
|         target.depth.mipmaps = 1; |         target.depth.mipmaps = 1; | ||||||
|  |  | ||||||
|         // Attach color texture and depth renderbuffer/texture to FBO |         // Attach color texture and depth renderbuffer/texture to FBO | ||||||
|         rlFramebufferAttach(target.id, target.texture.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D); |         rlFramebufferAttach(target.id, target.texture.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0); | ||||||
|         rlFramebufferAttach(target.id, target.depth.id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER); |         rlFramebufferAttach(target.id, target.depth.id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); | ||||||
|  |  | ||||||
|         // Check if fbo is complete with attachments (valid) |         // Check if fbo is complete with attachments (valid) | ||||||
|         if (rlFramebufferComplete(target.id)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", target.id); |         if (rlFramebufferComplete(target.id)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", target.id); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 raysan5
					raysan5