diff --git a/shaders/final_combine.frag b/shaders/final_combine.frag index 64fa77e5190be51e1a36e4258e14f31afbce58da..e46ced1c277cf4bc90913606842e0d058c35f7b9 100644 --- a/shaders/final_combine.frag +++ b/shaders/final_combine.frag @@ -5,21 +5,17 @@ out vec4 FragColor; // Samplers uniform sampler2D uNormalsTex; -uniform sampler2D uLightAttenTex;// not used in the example +uniform sampler2D uLightAttenTex; uniform sampler2D uDepthTex; // Camera/eye parameters uniform mat4 invProjectionMatrix; uniform float zNear; uniform float zFar; - -// If your camera is at the origin in eye space, -// then viewPos = (0,0,0). -// If for some reason it's not, you can pass that in. uniform vec3 viewPos; -// Light in eye space -uniform vec3 lightPos; +// Light +uniform vec3 lightPos; uniform vec3 lightColor; // Material @@ -31,86 +27,72 @@ uniform float fresnelPower; uniform float fresnelScale; uniform float fresnelBias; -/////////////////////////////////////////// -// Helper: Reconstruct eye position -/////////////////////////////////////////// vec3 reconstructEyePos(vec2 uv, float depthLin) { float dEye = depthLin * (zFar - zNear) + zNear; - - vec2 ndc = uv * 2.0 - 1.0; - vec4 clip = vec4(ndc, -1.0, 1.0); - vec4 eye4 = invProjectionMatrix * clip; - vec3 dir = eye4.xyz / eye4.w; - dir = normalize(dir); + vec2 ndc = uv * 2.0 - 1.0; + vec4 clip = vec4(ndc, -1.0, 1.0); + vec4 eye4 = invProjectionMatrix * clip; + vec3 dir = normalize(eye4.xyz / eye4.w); return dEye * dir; } void main() { - //--------------------------------------- - // 1) Depth => Position - //--------------------------------------- - float depthLin = texture(uDepthTex, TexCoords).r; + // Depth => position + float depthLin = texture(uDepthTex, TexCoords).r; if (depthLin >= 0.9999) { - // probably background + // background => skip FragColor = vec4(1.0); return; } vec3 position = reconstructEyePos(TexCoords, depthLin); - //--------------------------------------- - // 2) Normal - //--------------------------------------- + // Normal vec3 packedNormal = texture(uNormalsTex, TexCoords).rgb; if (length(packedNormal) < 0.001) { - // background => skip FragColor = vec4(1.0); return; } - // Unpack from [0..1] => [-1..1] vec3 normal = normalize(packedNormal * 2.0 - 1.0); - //--------------------------------------- - // 3) Basic Blinn-Phong - //--------------------------------------- - // Eye space camera position might be (0,0,0) + // Blinn-Phong shading vec3 viewDir = normalize(viewPos - position); vec3 lightDir = normalize(lightPos - position); vec3 halfDir = normalize(lightDir + viewDir); - // ambient + diffuse + spec vec3 ambient = 0.1 * lightColor; float ndl = max(dot(normal, lightDir), 0.0); vec3 diffuse = ndl * lightColor; + float ndh = max(dot(normal, halfDir), 0.0); float spec = pow(ndh, shininess); vec3 specular = spec * lightColor; + // Combine vec3 lighting = ambient + diffuse + specular; - //--------------------------------------- - // 4) Fresnel (optional) - //--------------------------------------- + // Fresnel float cosTheta = max(dot(viewDir, normal), 0.0); - float fresnel = fresnelBias + fresnelScale * pow((1.0 - cosTheta), fresnelPower); - - // fluid color tinted by fresnel - vec3 finalColor = fluidColor * lighting; - finalColor += fluidColor * fresnel; - - //--------------------------------------- - // Attenuation - //--------------------------------------- - float attenuation = texture(uLightAttenTex, TexCoords).r; - finalColor *= attenuation; + float fresnelTerm = fresnelBias + + fresnelScale * pow((1.0 - cosTheta), fresnelPower); + fresnelTerm = clamp(fresnelTerm, 0.0, 1.0); + + // Base shading + vec3 transmissionColor = fluidColor * lighting; + + // Reflection color (approx) + vec3 reflectionColor = lightColor * 2.0; // or pick a sky color, etc. + + vec3 colorFresnel = mix(transmissionColor, reflectionColor, fresnelTerm); + + // Volumetric attenuation from attennuation pass + vec3 attenuationRGB = texture(uLightAttenTex, TexCoords).rgb; + colorFresnel *= attenuationRGB; + // Alpha from attenuation pass float alpha = texture(uLightAttenTex, TexCoords).a; - // float alpha = clamp(1.0 - attenuation, 0.0, 1.0); - //--------------------------------------- - // 5) Output - //--------------------------------------- - FragColor = vec4(finalColor, alpha); + FragColor = vec4(colorFresnel, alpha); } diff --git a/shaders/thickness.frag b/shaders/thickness.frag index 226d6b193e9ccd36a19d6258f0be27a1ab64483f..a614cbcb8652687c633bd50bc2970c4db217bfde 100644 --- a/shaders/thickness.frag +++ b/shaders/thickness.frag @@ -2,8 +2,8 @@ in vec3 vEyeSpacePos; -uniform float sphereRadius; // If you need it for logic; sometimes optional. - +uniform float sphereRadius; +uniform float thicknessMass; // We only need one color channel, // but OpenGL still expects a vec4 out of the fragment shader. out vec4 FragColor; @@ -19,7 +19,7 @@ void main() discard; // For thickness: each particle in this pixel adds some amount. - float thicknessIncrement = 0.015; + float thicknessIncrement = thicknessMass; // Output that in the red channel. Using GL32F only reed chanele sotred FragColor = vec4(thicknessIncrement, 0.0, 0.0, 1.0); diff --git a/shaders/thickness_attenuation.frag b/shaders/thickness_attenuation.frag index 82475789a2a621d6a9d01d1908452760e09f4a9b..4f7c9cfa80b667caf770f2827d9155fcb185f247 100644 --- a/shaders/thickness_attenuation.frag +++ b/shaders/thickness_attenuation.frag @@ -7,18 +7,19 @@ out vec4 FragColor; uniform sampler2D uThicknessTex; // Absorption coefficient -uniform float absorption; // e.g. 3.0 -> the higher, the more quickly light fades +uniform float alphaScale; // e.g. 3.0 -> the higher, the more quickly light fades // The color of the fluid (if you want tinted absorption) -uniform vec3 fluidColor; // e.g. vec3(0.3, 0.7, 1.0) +uniform vec3 absorptionRGB; // e.g. vec3(0.3, 0.7, 1.0) void main() { float thicknessVal = texture(uThicknessTex, TexCoords).r; // Beer–Lambert law - float attenuation = exp(-absorption * thicknessVal); + //float attenuation = exp(-absorption * thicknessVal); + vec3 attenuationRGB = exp(-absorptionRGB * thicknessVal); // The fluid color modulated by that attenuation // (This is a simplistic approach: if you want the fluid // to be fully absorbing, you do: finalColor = fluidColor * (1 - attenuation), etc.) @@ -31,8 +32,9 @@ void main() alpha = 0; } else { - alpha = clamp((1.0 - attenuation)*4, 0.0, 1.0); + float avgAttenuation = (attenuationRGB.x + attenuationRGB.y + attenuationRGB.z) / 3.0; + alpha = clamp((1.0 - avgAttenuation )*alphaScale, 0.0, 1.0); } - FragColor = vec4(attenuation, 0.0, 0.0, alpha); + FragColor = vec4(attenuationRGB, alpha); } diff --git a/src/FluidRenderer.cpp b/src/FluidRenderer.cpp index 7f0764433b953827e5bf76791b6a4ea18b8a7b39..3fbea490b916b1dfb0ddf1cab50986f55caec3fb 100644 --- a/src/FluidRenderer.cpp +++ b/src/FluidRenderer.cpp @@ -886,6 +886,8 @@ void FluidRenderer::renderThicknessFrame(size_t particleCount, size_t boundaryCo if (m_thicknessRenderProgram.pointScaleLoc != -1) { glUniform1f(m_thicknessRenderProgram.pointScaleLoc, m_pointScale); } + + glUniform1f(glGetUniformLocation(m_thicknessRenderProgram.programID, "thicknessMass"), m_thicknessMass); renderParticles(particleCount, m_thicknessRenderProgram); @@ -990,13 +992,13 @@ void FluidRenderer::renderThicknessAttenFrame() // 3) Set uniform: absorption, fluidColor, etc. float absorption = 0.2f; // tweak to taste - GLuint absorpLoc = glGetUniformLocation(m_thicknessAttenProgram.programID, "absorption"); - glUniform1f(absorpLoc, m_absorbtion); + GLuint absorpLoc = glGetUniformLocation(m_thicknessAttenProgram.programID, "alphaScale"); + glUniform1f(absorpLoc, m_alphaScale); // color - float fluidR = 0.2f, fluidG = 0.7f, fluidB = 1.0f; - glUniform3f(glGetUniformLocation(m_thicknessAttenProgram.programID, "fluidColor"), - fluidR, fluidG, fluidB); + float fluidR = 0.3f, fluidG = 0.3f, fluidB = 0.4f; + glUniform3f(glGetUniformLocation(m_thicknessAttenProgram.programID, "absorptionRGB"), + m_absorbtionR, m_absorbtionG, m_absorbtionB); // 4) Render a fullscreen quad glBindVertexArray(quadVAO); diff --git a/src/FluidSimulationApp.cpp b/src/FluidSimulationApp.cpp index afcfe12b792f3ab1eb2cc1d16017100e068e5612..51eae01e9b05d46bf657d967d05573e7d79386b4 100644 --- a/src/FluidSimulationApp.cpp +++ b/src/FluidSimulationApp.cpp @@ -144,8 +144,12 @@ namespace FluidSimulation { static float blurStrength = m_fluidRenderer->getBlurStrength(); static float depthThreshold = m_fluidRenderer->getDepthThreshold(); + static float thicknessMass = m_fluidRenderer->getThicknessMass(); static int thicknessBlurRadius = m_fluidRenderer->getThicknessBlurRadius(); - static float absorption = m_fluidRenderer->getAbsorption(); + static float absorptionR = m_fluidRenderer->getAbsorptionR(); + static float absorptionG = m_fluidRenderer->getAbsorptionG(); + static float absorptionB = m_fluidRenderer->getAbsorptionB(); + static float alphaScale = m_fluidRenderer->getAlphaScale(); static float shininess = m_fluidRenderer->getShininess(); static float fresnelPower = m_fluidRenderer->getFresnelPower(); @@ -229,6 +233,12 @@ namespace FluidSimulation { { m_fluidRenderer->setDepthThreshold(depthThreshold); } + + ImGui::Text("Thickness Mass"); + if (ImGui::SliderFloat("##ThicknessMass", &thicknessMass, 0.0f, 0.4f, "%.4f")) + { + m_fluidRenderer->setThicknessMass(thicknessMass); + } // -- Thickness Blur Radius (int) ImGui::Text("Thickness Blur Radius"); @@ -239,9 +249,24 @@ namespace FluidSimulation { // -- Absorption ImGui::Text("Absorption"); - if (ImGui::SliderFloat("##Absorption", &absorption, 0.0f, 2.0f, "%.2f")) + if (ImGui::SliderFloat("##AbsorptionR", &absorptionR, 0.0f, 1.0f, "%.2f")) + { + m_fluidRenderer->setAbsorptionR(absorptionR); + } + if (ImGui::SliderFloat("##AbsorptionG", &absorptionG, 0.0f, 1.0f, "%.2f")) + { + m_fluidRenderer->setAbsorptionG(absorptionG); + } + if (ImGui::SliderFloat("##AbsorptionB", &absorptionB, 0.0f, 1.0f, "%.2f")) + { + m_fluidRenderer->setAbsorptionB(absorptionB); + } + + // -- Alpha scale + ImGui::Text("Alpha Scale"); + if (ImGui::SliderFloat("##AlphaScale", &alphaScale, 0.0f, 8.0f, "%.1f")) { - m_fluidRenderer->setAbsorption(absorption); + m_fluidRenderer->setAlphaScale(alphaScale); } // -- Shininess @@ -300,12 +325,22 @@ namespace FluidSimulation { m_fluidRenderer->setDepthThreshold(h_depthThresh); depthThreshold = m_fluidRenderer->getDepthThreshold(); + + m_fluidRenderer->setThicknessMass(h_thicknessMass); + thicknessMass = m_fluidRenderer->getThicknessMass(); m_fluidRenderer->setThicknessBlurRadius(h_thickBlurrRadius); thicknessBlurRadius = m_fluidRenderer->getThicknessBlurRadius(); - m_fluidRenderer->setAbsorption(h_absorbtion); - absorption = m_fluidRenderer->getAbsorption(); + m_fluidRenderer->setAbsorptionR(h_absorbtionR); + absorptionR = m_fluidRenderer->getAbsorptionR(); + m_fluidRenderer->setAbsorptionG(h_absorbtionG); + absorptionG = m_fluidRenderer->getAbsorptionG(); + m_fluidRenderer->setAbsorptionB(h_absorbtionB); + absorptionB = m_fluidRenderer->getAbsorptionB(); + + m_fluidRenderer->setAlphaScale(h_alphaScale); + absorptionB = m_fluidRenderer->getAlphaScale(); m_fluidRenderer->setShininess(h_shininess); shininess = m_fluidRenderer->getShininess(); diff --git a/src/include/FluidRenderer.h b/src/include/FluidRenderer.h index eb1bed756c941bcfa74de06fa31f29456ce7de2f..10b58c0220decfc187765d373a0329215a401fe1 100644 --- a/src/include/FluidRenderer.h +++ b/src/include/FluidRenderer.h @@ -113,8 +113,12 @@ private: float m_blurrStrength = h_sigmaR; float m_deptThreshold = h_depthThresh; + float m_thicknessMass = h_thicknessMass; int thicknesBlurrRadius = h_thickBlurrRadius; - float m_absorbtion = h_absorbtion; + float m_absorbtionR = h_absorbtionR; + float m_absorbtionG = h_absorbtionG; + float m_absorbtionB = h_absorbtionB; + float m_alphaScale = h_alphaScale; float3 m_fluidColor = h_fluidColor; float m_shininess = h_shininess; @@ -198,6 +202,9 @@ public: float getSpatialFactor() const { return m_spatialFactor; } void setSpatialFactor(float spatialFactor) { m_spatialFactor = spatialFactor; } + float getThicknessMass() const { return m_thicknessMass; } + void setThicknessMass(float thicknessMass) { m_thicknessMass = thicknessMass; } + float getBlurStrength() const { return m_blurrStrength; } void setBlurStrength(float blurStrength) { m_blurrStrength = blurStrength; } @@ -207,9 +214,18 @@ public: int getThicknessBlurRadius() const { return thicknesBlurrRadius; } void setThicknessBlurRadius(int blurRadius) { thicknesBlurrRadius = blurRadius; } - float getAbsorption() const { return m_absorbtion; } - void setAbsorption(float absorption) { m_absorbtion = absorption; } + float getAbsorptionR() const { return m_absorbtionR; } + void setAbsorptionR(float absorptionR) { m_absorbtionR = absorptionR; } + float getAbsorptionG() const { return m_absorbtionG; } + void setAbsorptionG(float absorptionG) { m_absorbtionG = absorptionG; } + + float getAbsorptionB() const { return m_absorbtionB; } + void setAbsorptionB(float absorptionB) { m_absorbtionB = absorptionB; } + + float getAlphaScale() const { return m_alphaScale; } + void setAlphaScale(float alphaScale) { m_alphaScale = alphaScale; } + float getShininess() const { return m_shininess; } void setShininess(float shininess) { m_shininess = shininess; } diff --git a/src/settings/constants.h b/src/settings/constants.h index b8ad4fb20a07aee9f10c60b52f6cb411623fba25..8e45e2296db85a8c5b758bac8967ce5e4496b84b 100644 --- a/src/settings/constants.h +++ b/src/settings/constants.h @@ -24,18 +24,22 @@ const int NUM_PARTICLES = 200000; // Rendner parameters const float h_POINT_SCALE = 14.0f; -const float h_POINT_RADIUS = 25.0f; +const float h_POINT_RADIUS = 22.0f; const float h_SPHERE_RADIUS = 0.05f; -const float h_worldRadiusMeters = 0.2f; // e.g. 2 cm smoothing in real space +const float h_worldRadiusMeters = 0.4f; // e.g. 2 cm smoothing in real space const float h_maxPixelRadius = 60.0f; // clamp for performance const float h_sigmaSpatialFactor = 10.0f; // controls the spatial falloff in the blur loop const float h_sigmaR = 4.0f; // range weight exponent const float h_depthThresh = 0.2f; // bilateral threshold for ignoring big depth jumps +const float h_thicknessMass = 0.15f; const int h_thickBlurrRadius = 24; -const float h_absorbtion = 0.2f; +const float h_absorbtionR = 0.08f; +const float h_absorbtionG = 0.03f; +const float h_absorbtionB = 0.02f; +const float h_alphaScale = 3.4f; const float h_shininess = 82.0f;