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