Update shaders_deferred_rendering.c

This commit is contained in:
Ray
2026-01-12 13:36:40 +01:00
parent 28b9411e9d
commit 644ff28f87

View File

@ -40,13 +40,13 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// GBuffer data // GBuffer data
typedef struct GBuffer { typedef struct GBuffer {
unsigned int framebuffer; unsigned int framebufferId;
unsigned int positionTexture; unsigned int positionTextureId;
unsigned int normalTexture; unsigned int normalTextureId;
unsigned int albedoSpecTexture; unsigned int albedoSpecTextureId;
unsigned int depthRenderbuffer; unsigned int depthRenderbufferId;
} GBuffer; } GBuffer;
// Deferred mode passes // Deferred mode passes
@ -90,15 +90,10 @@ int main(void)
// Initialize the G-buffer // Initialize the G-buffer
GBuffer gBuffer = { 0 }; GBuffer gBuffer = { 0 };
gBuffer.framebuffer = rlLoadFramebuffer(); gBuffer.framebufferId = rlLoadFramebuffer();
if (gBuffer.framebufferId == 0) TraceLog(LOG_WARNING, "Failed to create framebufferId");
if (!gBuffer.framebuffer) rlEnableFramebuffer(gBuffer.framebufferId);
{
TraceLog(LOG_WARNING, "Failed to create framebuffer");
exit(1);
}
rlEnableFramebuffer(gBuffer.framebuffer);
// NOTE: Vertex positions are stored in a texture for simplicity. A better approach would use a depth texture // NOTE: Vertex positions are stored in a texture for simplicity. A better approach would use a depth texture
// (instead of a detph renderbuffer) to reconstruct world positions in the final render shader via clip-space position, // (instead of a detph renderbuffer) to reconstruct world positions in the final render shader via clip-space position,
@ -107,46 +102,42 @@ int main(void)
// 16-bit precision ensures OpenGL ES 3 compatibility, though it may lack precision for real scenarios // 16-bit precision ensures OpenGL ES 3 compatibility, though it may lack precision for real scenarios
// But as mentioned above, the positions could be reconstructed instead of stored. If not targeting OpenGL ES // But as mentioned above, the positions could be reconstructed instead of stored. If not targeting OpenGL ES
// and you wish to maintain this approach, consider using `RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32` // and you wish to maintain this approach, consider using `RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32`
gBuffer.positionTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1); gBuffer.positionTextureId = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// Similarly, 16-bit precision is used for normals ensures OpenGL ES 3 compatibility // Similarly, 16-bit precision is used for normals ensures OpenGL ES 3 compatibility
// This is generally sufficient, but a 16-bit fixed-point format offer a better uniform precision in all orientations // This is generally sufficient, but a 16-bit fixed-point format offer a better uniform precision in all orientations
gBuffer.normalTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1); gBuffer.normalTextureId = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// Albedo (diffuse color) and specular strength can be combined into one texture // Albedo (diffuse color) and specular strength can be combined into one texture
// The color in RGB, and the specular strength in the alpha channel // The color in RGB, and the specular strength in the alpha channel
gBuffer.albedoSpecTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); gBuffer.albedoSpecTextureId = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
// Activate the draw buffers for our framebuffer // Activate the draw buffers for our framebufferId
rlActiveDrawBuffers(3); rlActiveDrawBuffers(3);
// Now we attach our textures to the framebuffer // Now we attach our textures to the framebufferId
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.positionTexture, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.positionTextureId, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.normalTexture, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.normalTextureId, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.albedoSpecTexture, RL_ATTACHMENT_COLOR_CHANNEL2, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.albedoSpecTextureId, RL_ATTACHMENT_COLOR_CHANNEL2, RL_ATTACHMENT_TEXTURE2D, 0);
// Finally we attach the depth buffer // Finally we attach the depth buffer
gBuffer.depthRenderbuffer = rlLoadTextureDepth(screenWidth, screenHeight, true); gBuffer.depthRenderbufferId = rlLoadTextureDepth(screenWidth, screenHeight, true);
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.depthRenderbuffer, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.depthRenderbufferId, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0);
// Make sure our framebuffer is complete // Make sure our framebufferId is complete
// NOTE: rlFramebufferComplete() automatically unbinds the framebuffer, so we don't have // NOTE: rlFramebufferComplete() automatically unbinds the framebufferId, so we don't have to rlDisableFramebuffer() here
// to rlDisableFramebuffer() here if (!rlFramebufferComplete(gBuffer.framebufferId)) TraceLog(LOG_WARNING, "Framebuffer is not complete");
if (!rlFramebufferComplete(gBuffer.framebuffer))
{
TraceLog(LOG_WARNING, "Framebuffer is not complete");
}
// Now we initialize the sampler2D uniform's in the deferred shader // Now we initialize the sampler2D uniform's in the deferred shader
// We do this by setting the uniform's values to the texture units that // We do this by setting the uniform's values to the texture units that
// we later bind our g-buffer textures to // we later bind our g-buffer textures to
rlEnableShader(deferredShader.id); rlEnableShader(deferredShader.id);
int texUnitPosition = 0; int texUnitPosition = 0;
int texUnitNormal = 1; int texUnitNormal = 1;
int texUnitAlbedoSpec = 2; int texUnitAlbedoSpec = 2;
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gPosition"), &texUnitPosition, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gPosition"), &texUnitPosition, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D);
rlDisableShader(); rlDisableShader();
// Assign out lighting shader to model // Assign out lighting shader to model
@ -176,7 +167,7 @@ int main(void)
cubeRotations[i] = (float)(rand()%360); cubeRotations[i] = (float)(rand()%360);
} }
DeferredMode mode = DEFERRED_SHADING; int mode = DEFERRED_SHADING;
rlEnableDepthTest(); rlEnableDepthTest();
@ -215,17 +206,16 @@ int main(void)
BeginDrawing(); BeginDrawing();
// Draw to the geometry buffer by first activating it // Draw to the geometry buffer by first activating it
rlEnableFramebuffer(gBuffer.framebuffer); rlEnableFramebuffer(gBuffer.framebufferId);
rlClearColor(0, 0, 0, 0); rlClearColor(0, 0, 0, 0);
rlClearScreenBuffers(); // Clear color and depth buffer rlClearScreenBuffers(); // Clear color and depth buffer
rlDisableColorBlend(); rlDisableColorBlend();
BeginMode3D(camera); BeginMode3D(camera);
// NOTE: We have to use rlEnableShader here. `BeginShaderMode` or thus `rlSetShader` // NOTE: We have to use rlEnableShader here. `BeginShaderMode` or thus `rlSetShader`
// will not work, as they won't immediately load the shader program // will not work, as they won't immediately load the shader program
rlEnableShader(gbufferShader.id); rlEnableShader(gbufferShader.id);
// When drawing a model here, make sure that the material's shaders // When drawing a model here, make sure that the material's shaders are set to the gbuffer shader!
// are set to the gbuffer shader!
DrawModel(model, Vector3Zero(), 1.0f, WHITE); DrawModel(model, Vector3Zero(), 1.0f, WHITE);
DrawModel(cube, (Vector3) { 0.0, 1.0f, 0.0 }, 1.0f, WHITE); DrawModel(cube, (Vector3) { 0.0, 1.0f, 0.0 }, 1.0f, WHITE);
@ -234,12 +224,12 @@ int main(void)
Vector3 position = cubePositions[i]; Vector3 position = cubePositions[i];
DrawModelEx(cube, position, (Vector3) { 1, 1, 1 }, cubeRotations[i], (Vector3) { CUBE_SCALE, CUBE_SCALE, CUBE_SCALE }, WHITE); DrawModelEx(cube, position, (Vector3) { 1, 1, 1 }, cubeRotations[i], (Vector3) { CUBE_SCALE, CUBE_SCALE, CUBE_SCALE }, WHITE);
} }
rlDisableShader(); rlDisableShader();
EndMode3D(); EndMode3D();
rlEnableColorBlend(); rlEnableColorBlend();
// Go back to the default framebuffer (0) and draw our deferred shading // Go back to the default framebufferId (0) and draw our deferred shading
rlDisableFramebuffer(); rlDisableFramebuffer();
rlClearScreenBuffers(); // Clear color & depth buffer rlClearScreenBuffers(); // Clear color & depth buffer
@ -254,21 +244,21 @@ int main(void)
// We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`, // We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`,
// and `gAlbedoSpec` // and `gAlbedoSpec`
rlActiveTextureSlot(texUnitPosition); rlActiveTextureSlot(texUnitPosition);
rlEnableTexture(gBuffer.positionTexture); rlEnableTexture(gBuffer.positionTextureId);
rlActiveTextureSlot(texUnitNormal); rlActiveTextureSlot(texUnitNormal);
rlEnableTexture(gBuffer.normalTexture); rlEnableTexture(gBuffer.normalTextureId);
rlActiveTextureSlot(texUnitAlbedoSpec); rlActiveTextureSlot(texUnitAlbedoSpec);
rlEnableTexture(gBuffer.albedoSpecTexture); rlEnableTexture(gBuffer.albedoSpecTextureId);
// Finally, we draw a fullscreen quad to our default framebuffer // Finally, we draw a fullscreen quad to our default framebufferId
// This will now be shaded using our deferred shader // This will now be shaded using our deferred shader
rlLoadDrawQuad(); rlLoadDrawQuad();
rlDisableShader(); rlDisableShader();
rlEnableColorBlend(); rlEnableColorBlend();
EndMode3D(); EndMode3D();
// As a last step, we now copy over the depth buffer from our g-buffer to the default framebuffer // As a last step, we now copy over the depth buffer from our g-buffer to the default framebufferId
rlBindFramebuffer(RL_READ_FRAMEBUFFER, gBuffer.framebuffer); rlBindFramebuffer(RL_READ_FRAMEBUFFER, gBuffer.framebufferId);
rlBindFramebuffer(RL_DRAW_FRAMEBUFFER, 0); rlBindFramebuffer(RL_DRAW_FRAMEBUFFER, 0);
rlBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0x00000100); // GL_DEPTH_BUFFER_BIT rlBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0x00000100); // GL_DEPTH_BUFFER_BIT
rlDisableFramebuffer(); rlDisableFramebuffer();
@ -290,7 +280,7 @@ int main(void)
case DEFERRED_POSITION: case DEFERRED_POSITION:
{ {
DrawTextureRec((Texture2D){ DrawTextureRec((Texture2D){
.id = gBuffer.positionTexture, .id = gBuffer.positionTextureId,
.width = screenWidth, .width = screenWidth,
.height = screenHeight, .height = screenHeight,
}, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE);
@ -300,7 +290,7 @@ int main(void)
case DEFERRED_NORMAL: case DEFERRED_NORMAL:
{ {
DrawTextureRec((Texture2D){ DrawTextureRec((Texture2D){
.id = gBuffer.normalTexture, .id = gBuffer.normalTextureId,
.width = screenWidth, .width = screenWidth,
.height = screenHeight, .height = screenHeight,
}, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE);
@ -310,7 +300,7 @@ int main(void)
case DEFERRED_ALBEDO: case DEFERRED_ALBEDO:
{ {
DrawTextureRec((Texture2D){ DrawTextureRec((Texture2D){
.id = gBuffer.albedoSpecTexture, .id = gBuffer.albedoSpecTextureId,
.width = screenWidth, .width = screenWidth,
.height = screenHeight, .height = screenHeight,
}, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE);
@ -331,18 +321,20 @@ int main(void)
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
UnloadModel(model); // Unload the models // Unload the models
UnloadModel(model);
UnloadModel(cube); UnloadModel(cube);
UnloadShader(deferredShader); // Unload shaders // Unload shaders
UnloadShader(deferredShader);
UnloadShader(gbufferShader); UnloadShader(gbufferShader);
// Unload geometry buffer and all attached textures // Unload geometry buffer and all attached textures
rlUnloadFramebuffer(gBuffer.framebuffer); rlUnloadFramebuffer(gBuffer.framebufferId);
rlUnloadTexture(gBuffer.positionTexture); rlUnloadTexture(gBuffer.positionTextureId);
rlUnloadTexture(gBuffer.normalTexture); rlUnloadTexture(gBuffer.normalTextureId);
rlUnloadTexture(gBuffer.albedoSpecTexture); rlUnloadTexture(gBuffer.albedoSpecTextureId);
rlUnloadTexture(gBuffer.depthRenderbuffer); rlUnloadTexture(gBuffer.depthRenderbufferId);
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------