diff --git a/shaders/thickness.frag b/shaders/thickness.frag new file mode 100644 index 0000000000000000000000000000000000000000..bfaafa22eb8717af0ce5c9fa56cf365793a845d0 --- /dev/null +++ b/shaders/thickness.frag @@ -0,0 +1,26 @@ +#version 330 core + +in vec3 vEyeSpacePos; + +uniform float sphereRadius; // If you need it for logic; sometimes optional. + +// We only need one color channel, +// but OpenGL still expects a vec4 out of the fragment shader. +out vec4 FragColor; + +void main() +{ + // Convert gl_PointCoord from [0,1] to [-1,1] + vec2 texCoord = gl_PointCoord * 2.0 - 1.0; + float r2 = dot(texCoord, texCoord); + + // Discard fragments outside the circle + if (r2 > 1.0) + discard; + + // For thickness: each particle in this pixel adds some amount. + float thicknessIncrement = 0.05; + + // 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.vert b/shaders/thickness.vert new file mode 100644 index 0000000000000000000000000000000000000000..f9e0c1e14290de954a3060650d9e966ee7125179 --- /dev/null +++ b/shaders/thickness.vert @@ -0,0 +1,29 @@ +#version 330 core + +layout(location = 0) in vec3 aPosition; // or "aPos" if that matches your code + +// Same transforms as depth +uniform mat4 modelMatrix; +uniform mat4 viewMatrix; +uniform mat4 projectionMatrix; + +// The same pointSize logic +uniform float pointRadius; +uniform float pointScale; + +out vec3 vEyeSpacePos; + +void main() +{ + // Transform the particle's position from model to eye space + vec4 worldPos = modelMatrix * vec4(aPosition, 1.0); + vec4 eyePos = viewMatrix * worldPos; + vEyeSpacePos = eyePos.xyz; + + // Scale point size based on distance, like your depth pass + float dist = length(eyePos.xyz); + gl_PointSize = pointRadius * (pointScale / dist); + + // Standard projection + gl_Position = projectionMatrix * eyePos; +} diff --git a/src/FluidRenderer.cpp b/src/FluidRenderer.cpp index 685393cd3fb1d4a58b868124d01a699afced736e..d16736089c259bb8d5b5f0eac4f1174899579f1b 100644 --- a/src/FluidRenderer.cpp +++ b/src/FluidRenderer.cpp @@ -132,6 +132,19 @@ void FluidRenderer::initShaders() { glUseProgram(m_depthRenderProgram.programID); std::cout << "Depth Render Shaders initialized successfully." << std::endl; + // Thickness Render Shader + m_thicknessRenderProgram.programID = loadShaders( + "../shaders/thickness.vert", + "../shaders/thickness.frag" + ); + if (m_thicknessRenderProgram.programID == 0) { + std::cerr << "Failed to load Thickness Render Shaders." << std::endl; + exit(1); + } + glUseProgram(m_thicknessRenderProgram.programID); + std::cout << "Thickness Render Shaders initialized successfully." << std::endl; + + // Visualization Shader m_visualizationProgram.programID = loadShaders("../shaders/visualize_grayscale.vert", "../shaders/visualize_grayscale.frag"); if (m_visualizationProgram.programID == 0) { @@ -217,6 +230,9 @@ void FluidRenderer::initShaderUniforms() // Depth render program: setupShaderProgram(m_depthRenderProgram); + // Thickness buffer program: + setupShaderProgram(m_thicknessRenderProgram); + // Visualization program: setupShaderProgram(m_visualizationProgram); @@ -265,6 +281,12 @@ void FluidRenderer::initFBOs() { // Initialize Depth Render Shader FBO with GL_R32F initializeFramebuffer(m_depthRenderProgram, GL_R32F, GL_RED, GL_FLOAT); + // Initialize Thickness Render Shader FBO with GL_R32F + initializeFramebuffer(m_thicknessRenderProgram, + GL_R32F, // internal format + GL_RED, // texture format + GL_FLOAT); // data type + // Initialize Visualization Render Shader FBO with GL_RGBA8 initializeFramebuffer(m_visualizationProgram, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); @@ -350,6 +372,10 @@ void FluidRenderer::resizeFBO(int newWidth, int newHeight) { GL_R32F, GL_RED, GL_FLOAT, newWidth, newHeight); + resizeFramebuffer(m_thicknessRenderProgram, + GL_R32F, GL_RED, GL_FLOAT, + newWidth, newHeight); + // Resize Visualization Render Shader FBO resizeFramebuffer(m_visualizationProgram, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, @@ -454,7 +480,7 @@ void FluidRenderer::renderDepthFrame(size_t particleCount, size_t boundaryCount) // Set the viewport to match the framebuffer size glViewport(0, 0, m_fbWidth, m_fbHeight); - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Typically black for depth? + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Clear color and depth buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -490,6 +516,47 @@ void FluidRenderer::renderDepthFrame(size_t particleCount, size_t boundaryCount) glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void FluidRenderer::renderThicknessFrame(size_t particleCount, size_t boundaryCount) +{ + glBindFramebuffer(GL_FRAMEBUFFER, m_thicknessRenderProgram.fbo); + glViewport(0, 0, m_fbWidth, m_fbHeight); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Disable depth test so *all* fragments draw + glDisable(GL_DEPTH_TEST); + + // Enable additive blending + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + + glUseProgram(m_thicknessRenderProgram.programID); + glBindVertexArray(particles_vao); + + // Update standard uniforms + if (m_thicknessRenderProgram.projectionMatrixLoc != -1) { + mat4 projectionMatrix = m_camera->getProjectionMatrix(); + glUniformMatrix4fv(m_thicknessRenderProgram.projectionMatrixLoc, 1, GL_TRUE, projectionMatrix.m); + } + if (m_thicknessRenderProgram.viewMatrixLoc != -1) { + mat4 viewMatrix = m_camera->getViewMatrix(); + glUniformMatrix4fv(m_thicknessRenderProgram.viewMatrixLoc, 1, GL_TRUE, viewMatrix.m); + } + if (m_thicknessRenderProgram.pointRadiusLoc != -1) { + glUniform1f(m_thicknessRenderProgram.pointRadiusLoc, 20.0f); + } + + renderParticles(particleCount, m_thicknessRenderProgram); + + // Restore states + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + + // Visualize Buffer void FluidRenderer::visualizeBuffer(RenderStage stage) { @@ -535,6 +602,8 @@ GLuint FluidRenderer::getTexture(RenderStage stage) const { return m_normalRenderProgram.fboTexture; case RenderStage::DepthBuffer: return m_depthRenderProgram.fboTexture; + case RenderStage::ThicknessBuffer: + return m_thicknessRenderProgram.fboTexture; default: return 0; // Return 0 if no valid stage was selected } diff --git a/src/FluidSimulationApp.cpp b/src/FluidSimulationApp.cpp index 11d82f9826e3dca2db41081c52b9c6e5254f02a6..d4b564ec327eaaabe910f583af45da23c3fc7e6d 100644 --- a/src/FluidSimulationApp.cpp +++ b/src/FluidSimulationApp.cpp @@ -202,13 +202,28 @@ namespace FluidSimulation { m_fluidSimulation->getBoundaryParticleCount() ); } - else + else if (selectedStage == RenderStage::DepthBuffer) { m_fluidRenderer->renderDepthFrame( m_fluidSimulation->getParticleCount(), m_fluidSimulation->getBoundaryParticleCount() ); + // After rendering the depth frame, perform visualization + m_fluidRenderer->visualizeBuffer(selectedStage); + } + else //if (selectedStage == RenderStage::ThicknessBuffer) + { + printf("Render Thicnness \n"); + if (selectedStage == RenderStage::ThicknessBuffer) + { + printf("Thicnes stagee active \n"); + } + m_fluidRenderer->renderThicknessFrame( + m_fluidSimulation->getParticleCount(), + m_fluidSimulation->getBoundaryParticleCount() + ); + // After rendering the depth frame, perform visualization m_fluidRenderer->visualizeBuffer(selectedStage); } @@ -224,7 +239,7 @@ namespace FluidSimulation { { textureID = m_fluidRenderer->getTexture(selectedStage); // RGBA8 } - else if (selectedStage == RenderStage::DepthBuffer /* || other grayscale stages */) + else if (selectedStage == RenderStage::DepthBuffer || selectedStage == RenderStage::ThicknessBuffer) { // Use the visualization texture textureID = m_fluidRenderer->getVisualizationTexture(); diff --git a/src/include/FluidRenderer.h b/src/include/FluidRenderer.h index bebb5c8efd79254f08f6f0f09b7f82939b69e8ad..0f20fac7dc5687c56a20a8795432c7d05ec2a563 100644 --- a/src/include/FluidRenderer.h +++ b/src/include/FluidRenderer.h @@ -66,6 +66,7 @@ private: // Shader programs ShaderProgram m_normalRenderProgram; // For particle shaders ShaderProgram m_depthRenderProgram; // For depth shaders + ShaderProgram m_thicknessRenderProgram; // For thickness shaders ShaderProgram m_visualizationProgram; // For visualization shaders // VBOs for particles and boundaries @@ -125,6 +126,7 @@ public: // Separate rendering functions void renderNormalFrame(size_t particleCount, size_t boundaryCount); // Render using Normal Shaders void renderDepthFrame(size_t particleCount, size_t boundaryCount); // Render using Depth Shaders + void renderThicknessFrame(size_t particleCount, size_t boundaryCount); void visualizeBuffer(RenderStage stage); // Visualize selected render stage // Methods to retrieve textures based on RenderStage