From 4960cc74e09dada8837745e5f14d4571c15836c8 Mon Sep 17 00:00:00 2001 From: luis605 Date: Fri, 4 Apr 2025 22:41:34 +0100 Subject: [PATCH] [examples] Reviewed shader view depth --- .../resources/shaders/glsl100/depth.fs | 37 ++++++++++++------ .../resources/shaders/glsl330/depth.fs | 36 ++++++++++++----- examples/shaders/shaders_view_depth.c | 2 + examples/shaders/shaders_view_depth.png | Bin 7745 -> 11335 bytes 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl100/depth.fs b/examples/shaders/resources/shaders/glsl100/depth.fs index cdd45f17f..0ea7c46e7 100644 --- a/examples/shaders/resources/shaders/glsl100/depth.fs +++ b/examples/shaders/resources/shaders/glsl100/depth.fs @@ -1,19 +1,34 @@ #version 100 -in vec2 fragTexCoord; -out vec4 finalColor; -uniform sampler2D depthTexture; +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +// Input uniform values +uniform sampler2D depthTexture; +uniform bool flipY; + +float nearPlane = 0.1; +float farPlane = 100.0; + +// Function to linearize depth from non-linear depth buffer float linearizeDepth(float depth) { - float n = 0.1; // near plane - float f = 100.0; // far plane - return (2.0 * n) / (f + n - depth * (f - n)); + return (2.0 * nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane)); } -void main() { - vec2 flippedTexCoord = vec2(fragTexCoord.x, 1.0 - fragTexCoord.y); - float depth = texture(depthTexture, flippedTexCoord).r; +void main() +{ + // Handle potential Y-flipping + vec2 texCoord = fragTexCoord; + if (flipY) + texCoord.y = 1.0 - texCoord.y; + + // Sample depth texture + float depth = texture2D(depthTexture, texCoord).r; + + // Linearize depth float linearDepth = linearizeDepth(depth); - finalColor = vec4(vec3(linearDepth), 1.0); -} + + // Output final color + gl_FragColor = vec4(vec3(linearDepth), 1.0); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/depth.fs b/examples/shaders/resources/shaders/glsl330/depth.fs index ccda3111b..cbcb6da67 100644 --- a/examples/shaders/resources/shaders/glsl330/depth.fs +++ b/examples/shaders/resources/shaders/glsl330/depth.fs @@ -1,19 +1,37 @@ #version 330 +// Input vertex attributes (from vertex shader) in vec2 fragTexCoord; -out vec4 finalColor; -uniform sampler2D depthTexture; +// Input uniform values +uniform sampler2D depthTexture; +uniform bool flipY; + +const float nearPlane = 0.1; +const float farPlane = 100.0; + +// Output fragment color +out vec4 finalColor; + +// Linearizes the depth buffer value float linearizeDepth(float depth) { - float n = 0.1; // near plane - float f = 100.0; // far plane - return (2.0 * n) / (f + n - depth * (f - n)); + return (2.0 * nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane)); } -void main() { - vec2 flippedTexCoord = vec2(fragTexCoord.x, 1.0 - fragTexCoord.y); - float depth = texture(depthTexture, flippedTexCoord).r; +void main() +{ + // Handle potential Y-flipping + vec2 texCoord = fragTexCoord; + if (flipY) + texCoord.y = 1.0 - texCoord.y; + + // Sample depth + float depth = texture(depthTexture, texCoord).r; + + // Linearize depth value float linearDepth = linearizeDepth(depth); + + // Output final color finalColor = vec4(vec3(linearDepth), 1.0); -} +} \ No newline at end of file diff --git a/examples/shaders/shaders_view_depth.c b/examples/shaders/shaders_view_depth.c index fa5393280..5da0c1ca4 100644 --- a/examples/shaders/shaders_view_depth.c +++ b/examples/shaders/shaders_view_depth.c @@ -52,6 +52,8 @@ int main(void) // Load depth shader and get depth texture shader location Shader depthShader = LoadShader(0, TextFormat("resources/shaders/glsl%i/depth.fs", GLSL_VERSION)); int depthLoc = GetShaderLocation(depthShader, "depthTexture"); + int flipTextureLoc = GetShaderLocation(depthShader, "flipY"); + SetShaderValue(depthShader, flipTextureLoc, (int[]){ 1 }, SHADER_UNIFORM_INT); // Flip Y texture // Load models Model cube = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f)); diff --git a/examples/shaders/shaders_view_depth.png b/examples/shaders/shaders_view_depth.png index bcce1fd61497f5884d045a9b1bafab3b34dcaa0b..b68de9644cab86bc0ff3422f147bdee0a59a2494 100644 GIT binary patch literal 11335 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 MT~{?<#U|wc0o}j6-~a#s literal 7745 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