diff --git a/shaders/depth_normals.frag b/shaders/depth_normals.frag index 5a59e0860fbec2a1077d5d5cd8621b0cd9e8adc7..d550e44760e2ae51adddbed9162f306633f36c7f 100644 --- a/shaders/depth_normals.frag +++ b/shaders/depth_normals.frag @@ -3,104 +3,97 @@ in vec2 TexCoords; out vec4 FragColor; -// The linear depth texture (0..1 -> zNear..zFar) uniform sampler2D uDepthTex; -// The inverse of the projection matrix (pass from CPU) +// We need these to convert linear [0..1] to actual distance +uniform float zNear; +uniform float zFar; + +// The inverse of the same projection matrix used when rendering depth uniform mat4 invProjectionMatrix; -// Optional max depth clamp -uniform float maxDepth; // e.g., 1.0 if 1 means zFar +// We can discard if depth is bigger than some clamp +uniform float maxDepth; -// Offset in texture coordinates for neighbor sampling -// Usually (1.0 / screenWidth, 1.0 / screenHeight) +// Pixel-size step for neighbor sampling uniform vec2 uTexelSize; +////////////////////////////////////////////////////////// +// Helper: Reconstruct eye-space position from linear depth +////////////////////////////////////////////////////////// +vec3 reconstructEyePos(vec2 uv, float depthLin) +{ + // 1) Convert [0..1] -> actual eye-space distance + float dEye = depthLin * (zFar - zNear) + zNear; + + // 2) Compute direction from camera through this UV. + // We'll treat the clip-space z = -1 (the near plane), + // so that we get a direction vector after inverse-projection. + float xNDC = uv.x * 2.0 - 1.0; + float yNDC = uv.y * 2.0 - 1.0; + + vec4 clipPos = vec4(xNDC, yNDC, -1.0, 1.0); + vec4 eyePos4 = invProjectionMatrix * clipPos; + // perspective divide + vec3 dir = eyePos4.xyz / eyePos4.w; + dir = normalize(dir); + + // 3) Actual position = direction * distance + return dir * dEye; +} + void main() { + ////////////////////////////////// // 1) Sample center depth + ////////////////////////////////// float depthLin = texture(uDepthTex, TexCoords).r; - // Validate - if (depthLin < 0.0 || depthLin > 1.0 || depthLin > maxDepth) - { + if (depthLin < 0.0 || depthLin > 1.0 || depthLin > maxDepth) { discard; } - // 2) Convert to clip space - // OpenGL clip space: X, Y in [-1,1], Z in [-1,1]. - // Our linear depth is [0..1], we map it to clip Z by (depthLin * 2 - 1). - vec4 clipPos = vec4( - TexCoords.x * 2.0 - 1.0, - TexCoords.y * 2.0 - 1.0, - depthLin * 2.0 - 1.0, - 1.0 - ); - - // 3) Inverse-project to eye space - vec4 eyePos4 = invProjectionMatrix * clipPos; - // perspective divide - eyePos4.xyz /= eyePos4.w; - vec3 centerEye = eyePos4.xyz; // The actual eye-space position + // Reconstruct center pixel in eye space + vec3 centerEye = reconstructEyePos(TexCoords, depthLin); - // 4) Sample neighbors and reconstruct their eye-space positions - // We'll do left-right in x direction + ////////////////////////////////// + // 2) Sample neighbors (x direction) + ////////////////////////////////// vec2 uvLeft = TexCoords + vec2(-uTexelSize.x, 0.0); vec2 uvRight = TexCoords + vec2( uTexelSize.x, 0.0); float depthL = texture(uDepthTex, uvLeft).r; float depthR = texture(uDepthTex, uvRight).r; - vec3 leftEye = vec3(0.0); - vec3 rightEye = vec3(0.0); - - if (depthL >= 0.0 && depthL <= maxDepth) { - vec4 clipL = vec4(uvLeft.x * 2.0 - 1.0, uvLeft.y * 2.0 - 1.0, depthL * 2.0 - 1.0, 1.0); - vec4 epL = invProjectionMatrix * clipL; - leftEye = epL.xyz / epL.w; - } else { - discard; // or skip partial if invalid - } + // If invalid neighbors, optionally discard + if (depthL < 0.0 || depthL > 1.0 || depthL > maxDepth) discard; + if (depthR < 0.0 || depthR > 1.0 || depthR > maxDepth) discard; - if (depthR >= 0.0 && depthR <= maxDepth) { - vec4 clipR = vec4(uvRight.x * 2.0 - 1.0, uvRight.y * 2.0 - 1.0, depthR * 2.0 - 1.0, 1.0); - vec4 epR = invProjectionMatrix * clipR; - rightEye = epR.xyz / epR.w; - } else { - discard; - } + vec3 leftEye = reconstructEyePos(uvLeft, depthL); + vec3 rightEye = reconstructEyePos(uvRight, depthR); // partial derivative in x vec3 ddx = rightEye - centerEye; vec3 ddx2 = centerEye - leftEye; + + // Optionally pick whichever has smaller Z difference if (abs(ddx2.z) < abs(ddx.z)) { ddx = ddx2; } - // 5) same approach for up-down + ////////////////////////////////// + // 3) Sample neighbors (y direction) + ////////////////////////////////// vec2 uvUp = TexCoords + vec2(0.0, uTexelSize.y); vec2 uvDn = TexCoords + vec2(0.0, -uTexelSize.y); float depthU = texture(uDepthTex, uvUp).r; float depthD = texture(uDepthTex, uvDn).r; - vec3 upEye = vec3(0.0); - vec3 dnEye = vec3(0.0); - - if (depthU >= 0.0 && depthU <= maxDepth) { - vec4 clipU = vec4(uvUp.x * 2.0 - 1.0, uvUp.y * 2.0 - 1.0, depthU * 2.0 - 1.0, 1.0); - vec4 epU = invProjectionMatrix * clipU; - upEye = epU.xyz / epU.w; - } else { - discard; - } + if (depthU < 0.0 || depthU > 1.0 || depthU > maxDepth) discard; + if (depthD < 0.0 || depthD > 1.0 || depthD > maxDepth) discard; - if (depthD >= 0.0 && depthD <= maxDepth) { - vec4 clipD = vec4(uvDn.x * 2.0 - 1.0, uvDn.y * 2.0 - 1.0, depthD * 2.0 - 1.0, 1.0); - vec4 epD = invProjectionMatrix * clipD; - dnEye = epD.xyz / epD.w; - } else { - discard; - } + vec3 upEye = reconstructEyePos(uvUp, depthU); + vec3 dnEye = reconstructEyePos(uvDn, depthD); vec3 ddy = upEye - centerEye; vec3 ddy2 = centerEye - dnEye; @@ -108,15 +101,17 @@ void main() ddy = ddy2; } - // 6) Cross partial derivatives to get normal + ////////////////////////////////// + // 4) Cross partials => normal + ////////////////////////////////// vec3 N = normalize(cross(ddx, ddy)); - // Optionally flip if needed - if (N.z > 0.0) { - N = -N; - } + // Some folks invert if N.z > 0 + //if (N.z > 0.0) { + // N = -N; + //} - // Shift from [-1..1] to [0..1] + // Map [-1..1] -> [0..1] for display vec3 normalColor = 0.5 * (N + vec3(1.0)); FragColor = vec4(normalColor, 1.0); } diff --git a/shaders/final_combine.frag b/shaders/final_combine.frag index 28f4880a32bd4af84356e5411461bc9a242d3ec3..0bf72657801b64b736df7c59f2f4b32dc224a770 100644 --- a/shaders/final_combine.frag +++ b/shaders/final_combine.frag @@ -51,7 +51,7 @@ void main() } // Expand [0..1] -> [-1..1], then normalize - normal = normalize(normal * 2.0 - 1.0); + //normal = normalize(normal * 2.0 - 1.0); //--------------------------------------------------------- // 3) Reconstruct eye-space position from depth @@ -94,8 +94,8 @@ void main() //--------------------------------------------------------- // 6) Multiply by attenuation //--------------------------------------------------------- - lighting *= attenuation; - + //lighting *= attenuation; + float alpha = 1 - attenuation; //--------------------------------------------------------- // 7) Fresnel effect //--------------------------------------------------------- @@ -112,5 +112,6 @@ void main() finalColor += fluidColor * fresnel; // tinted Fresnel // Done - FragColor = vec4(finalColor, 1.0); + //FragColor = vec4(finalColor, 0.5); + FragColor = vec4(normal, 1.0); //vec4(finalColor, 0.5); } diff --git a/shaders/thickness.frag b/shaders/thickness.frag index d4e13cf0fb6b0514a806a38cbb30913425193093..c97ea00327df46a75fbef7b877c438a98fb5dab7 100644 --- a/shaders/thickness.frag +++ b/shaders/thickness.frag @@ -19,7 +19,7 @@ void main() discard; // For thickness: each particle in this pixel adds some amount. - float thicknessIncrement = 0.01; + float thicknessIncrement = 0.04; // Output that in the red channel. Using GL32F only reed chanele sotred FragColor = vec4(thicknessIncrement, 0.0, 0.0, 1.0); diff --git a/src/FluidRenderer.cpp b/src/FluidRenderer.cpp index edc478bac7c549b43df6523a0defd89b67ed4e16..5ad8d3932963652b702600c15e270a41601455b8 100644 --- a/src/FluidRenderer.cpp +++ b/src/FluidRenderer.cpp @@ -816,7 +816,7 @@ void FluidRenderer::renderDepthNormalsFrame() // 3) Bind the *filtered depth* texture as input glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_depthFilterProgram.fboTexture); + glBindTexture(GL_TEXTURE_2D, m_depthRenderProgram.fboTexture); // temporary to se normals for spheres glUniform1i(glGetUniformLocation(m_depthNormalsProgram.programID, "uDepthTex"), 0); // 4) Set uniforms: zNear, zFar, uTexelSize, maxDepth, etc. @@ -898,7 +898,7 @@ void FluidRenderer::renderThicknessFrame(size_t particleCount, size_t boundaryCo void FluidRenderer::renderThicknessFilterFrame() { - int radius = 5; // or something + int radius = 24; // or something std::vector<float> weights; computeGaussianWeights(radius, weights); @@ -989,7 +989,7 @@ void FluidRenderer::renderThicknessAttenFrame() glUniform1i(glGetUniformLocation(m_thicknessAttenProgram.programID, "uThicknessTex"), 0); // 3) Set uniform: absorption, fluidColor, etc. - float absorption = 0.2f; // tweak to taste + float absorption = 0.8f; // tweak to taste GLuint absorpLoc = glGetUniformLocation(m_thicknessAttenProgram.programID, "absorption"); glUniform1f(absorpLoc, absorption); @@ -1016,11 +1016,14 @@ void FluidRenderer::renderFinalCombineFrame() glBindFramebuffer(GL_FRAMEBUFFER, m_finalCombineProgram.fbo); // Or 0 for screen glViewport(0, 0, m_fbWidth, m_fbHeight); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear to black + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Clear to black glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); // Disable depth testing for fullscreen quad + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glUseProgram(m_finalCombineProgram.programID); // Bind the required textures diff --git a/src/include/FluidSimulationApp.h b/src/include/FluidSimulationApp.h index e9614d36f3c6dc793dfda4f43a82c5728f1d446f..0211cbf52d1ab6a9ac385e83103359a4679bc041 100644 --- a/src/include/FluidSimulationApp.h +++ b/src/include/FluidSimulationApp.h @@ -23,7 +23,7 @@ namespace FluidSimulation FluidSimulation* m_fluidSimulation; bool m_updatePhysics; - RenderStage selectedStage = RenderStage::ParticleView; + RenderStage selectedStage = RenderStage::ScreenSpacedRender; void RenderControlPannel(); void RenderFluidView();