diff --git a/src/FluidRenderer.cpp b/src/FluidRenderer.cpp index c3fa0bbf085a5e1b16ab9555a331e71bf6ba1784..685393cd3fb1d4a58b868124d01a699afced736e 100644 --- a/src/FluidRenderer.cpp +++ b/src/FluidRenderer.cpp @@ -142,88 +142,85 @@ void FluidRenderer::initShaders() { std::cout << "Visualization Shaders initialized successfully." << std::endl; } -// Initialize Shader Uniforms -void FluidRenderer::initShaderUniforms() { - // Normal Render Shader Uniforms - glUseProgram(m_normalRenderProgram.programID); - - m_normalRenderProgram.positionAttribLoc = glGetAttribLocation(m_normalRenderProgram.programID, "aPosition"); - if (m_normalRenderProgram.positionAttribLoc == -1) { - fprintf(stderr, "Normal Render Shader: Could not find attribute 'aPosition'\n"); +void FluidRenderer::setupShaderProgram(ShaderProgram& shaderProgram) +{ + glUseProgram(shaderProgram.programID); + + // 1. Try fetching the attribute for position + // Note: Some shaders use "aPosition", some use "aPos". + shaderProgram.positionAttribLoc = glGetAttribLocation(shaderProgram.programID, "aPosition"); + if (shaderProgram.positionAttribLoc == -1) { + // If "aPosition" is not found, try "aPos" (used by visualization) + shaderProgram.positionAttribLoc = glGetAttribLocation(shaderProgram.programID, "aPos"); + if (shaderProgram.positionAttribLoc == -1) { + fprintf(stderr, "Shader (ID %d): Could not find attribute 'aPosition' or 'aPos'\n", + shaderProgram.programID); + } else { + printf("Shader (ID %d): Found attribute 'aPos' at location %d\n", + shaderProgram.programID, shaderProgram.positionAttribLoc); + } } else { - printf("Normal Render Shader: Attribute 'aPosition' location: %d\n", m_normalRenderProgram.positionAttribLoc); + printf("Shader (ID %d): Found attribute 'aPosition' at location %d\n", + shaderProgram.programID, shaderProgram.positionAttribLoc); } - m_normalRenderProgram.modelMatrixLoc = glGetUniformLocation(m_normalRenderProgram.programID, "modelMatrix"); - m_normalRenderProgram.viewMatrixLoc = glGetUniformLocation(m_normalRenderProgram.programID, "viewMatrix"); - m_normalRenderProgram.projectionMatrixLoc = glGetUniformLocation(m_normalRenderProgram.programID, "projectionMatrix"); - m_normalRenderProgram.pointRadiusLoc = glGetUniformLocation(m_normalRenderProgram.programID, "pointRadius"); - m_normalRenderProgram.pointScaleLoc = glGetUniformLocation(m_normalRenderProgram.programID, "pointScale"); - m_normalRenderProgram.uColorLoc = glGetUniformLocation(m_normalRenderProgram.programID, "uColor"); - - if (m_normalRenderProgram.pointRadiusLoc != -1) - glUniform1f(m_normalRenderProgram.pointRadiusLoc, 20.0f); - if (m_normalRenderProgram.pointScaleLoc != -1) - glUniform1f(m_normalRenderProgram.pointScaleLoc, 10.0f); - - mat4 modelMatrix = IdentityMatrix(); - glUniformMatrix4fv(m_normalRenderProgram.modelMatrixLoc, 1, GL_TRUE, modelMatrix.m); + // Fetch uniforms that may or may not exist in this shader. + // If the location is -1, that uniform is absent; just skip it. + shaderProgram.modelMatrixLoc = glGetUniformLocation(shaderProgram.programID, "modelMatrix"); + shaderProgram.viewMatrixLoc = glGetUniformLocation(shaderProgram.programID, "viewMatrix"); + shaderProgram.projectionMatrixLoc = glGetUniformLocation(shaderProgram.programID, "projectionMatrix"); + shaderProgram.pointRadiusLoc = glGetUniformLocation(shaderProgram.programID, "pointRadius"); + shaderProgram.pointScaleLoc = glGetUniformLocation(shaderProgram.programID, "pointScale"); + shaderProgram.uColorLoc = glGetUniformLocation(shaderProgram.programID, "uColor"); + shaderProgram.sphereRadiusLoc = glGetUniformLocation(shaderProgram.programID, "sphereRadius"); + shaderProgram.nearPlaneLoc = glGetUniformLocation(shaderProgram.programID, "zNear"); + shaderProgram.farPlaneLoc = glGetUniformLocation(shaderProgram.programID, "zFar"); - std::cout << "Normal Render Shader uniforms initialized." << std::endl; - - // Depth Render Shader Uniforms - glUseProgram(m_depthRenderProgram.programID); - - m_depthRenderProgram.positionAttribLoc = glGetAttribLocation(m_depthRenderProgram.programID, "aPosition"); - if (m_depthRenderProgram.positionAttribLoc == -1) { - fprintf(stderr, "Depth Render Shader: Could not find attribute 'aPosition'\n"); - } else { - printf("Depth Render Shader: Attribute 'aPosition' location: %d\n", m_depthRenderProgram.positionAttribLoc); + + // Set default values if the uniform is present + + // For point rendering (as in particle shaders): + if (shaderProgram.pointRadiusLoc != -1) { + glUniform1f(shaderProgram.pointRadiusLoc, 20.0f); } - - m_depthRenderProgram.modelMatrixLoc = glGetUniformLocation(m_depthRenderProgram.programID, "modelMatrix"); - m_depthRenderProgram.viewMatrixLoc = glGetUniformLocation(m_depthRenderProgram.programID, "viewMatrix"); - m_depthRenderProgram.projectionMatrixLoc = glGetUniformLocation(m_depthRenderProgram.programID, "projectionMatrix"); - m_depthRenderProgram.pointRadiusLoc = glGetUniformLocation(m_depthRenderProgram.programID, "pointRadius"); - m_depthRenderProgram.pointScaleLoc = glGetUniformLocation(m_depthRenderProgram.programID, "pointScale"); - m_depthRenderProgram.uColorLoc = glGetUniformLocation(m_depthRenderProgram.programID, "uColor"); - m_depthRenderProgram.sphereRadiusLoc = glGetUniformLocation(m_depthRenderProgram.programID, "sphereRadius"); // For depth shader - m_depthRenderProgram.nearPlaneLoc = glGetUniformLocation(m_depthRenderProgram.programID, "zNear"); // Corrected uniform name - m_depthRenderProgram.farPlaneLoc = glGetUniformLocation(m_depthRenderProgram.programID, "zFar"); // Corrected uniform name - - if (m_depthRenderProgram.pointRadiusLoc != -1) - glUniform1f(m_depthRenderProgram.pointRadiusLoc, 20.0f); - if (m_depthRenderProgram.pointScaleLoc != -1) - glUniform1f(m_depthRenderProgram.pointScaleLoc, 10.0f); - if (m_depthRenderProgram.sphereRadiusLoc != -1) - glUniform1f(m_depthRenderProgram.sphereRadiusLoc, 1.0f); // Set to desired sphere radius - - // Set near and far planes - float cameraNearPlane = m_camera->getNearPlane(); // Replace with actual method - float cameraFarPlane = m_camera->getFarPlane(); // Replace with actual method - - if (m_depthRenderProgram.nearPlaneLoc != -1) { - glUniform1f(m_depthRenderProgram.nearPlaneLoc, cameraNearPlane); + if (shaderProgram.pointScaleLoc != -1) { + glUniform1f(shaderProgram.pointScaleLoc, 10.0f); } - if (m_depthRenderProgram.farPlaneLoc != -1) { - glUniform1f(m_depthRenderProgram.farPlaneLoc, cameraFarPlane); + // For model matrix, set to Identity by default + if (shaderProgram.modelMatrixLoc != -1) { + mat4 modelMatrix = IdentityMatrix(); + glUniformMatrix4fv(shaderProgram.modelMatrixLoc, 1, GL_TRUE, modelMatrix.m); + } + // For near/far planes, if present + if (shaderProgram.nearPlaneLoc != -1 || shaderProgram.farPlaneLoc != -1) { + float cameraNearPlane = m_camera->getNearPlane(); + float cameraFarPlane = m_camera->getFarPlane(); + + if (shaderProgram.nearPlaneLoc != -1) { + glUniform1f(shaderProgram.nearPlaneLoc, cameraNearPlane); + } + if (shaderProgram.farPlaneLoc != -1) { + glUniform1f(shaderProgram.farPlaneLoc, cameraFarPlane); + } } - glUniformMatrix4fv(m_depthRenderProgram.modelMatrixLoc, 1, GL_TRUE, modelMatrix.m); + std::cout << "Shader (ID " << shaderProgram.programID + << ") uniform/attribute locations have been fetched and set where applicable.\n"; +} - std::cout << "Depth Render Shader uniforms initialized." << std::endl; +// Initialize Shader Uniforms +void FluidRenderer::initShaderUniforms() +{ + // Normal render program: + setupShaderProgram(m_normalRenderProgram); - // Visualization Shader Uniforms - glUseProgram(m_visualizationProgram.programID); + // Depth render program: + setupShaderProgram(m_depthRenderProgram); - m_visualizationProgram.positionAttribLoc = glGetAttribLocation(m_visualizationProgram.programID, "aPos"); - if (m_visualizationProgram.positionAttribLoc == -1) { - fprintf(stderr, "Visualization Shader: Could not find attribute 'aPos'\n"); - } else { - printf("Visualization Shader: Attribute 'aPos' location: %d\n", m_visualizationProgram.positionAttribLoc); - } + // Visualization program: + setupShaderProgram(m_visualizationProgram); - std::cout << "Visualization Shader uniforms initialized." << std::endl; + std::cout << "All shader programs' uniforms initialized via setupShaderProgram()." << std::endl; } void FluidRenderer::initializeFramebuffer(ShaderProgram& shaderProgram, GLenum textureInternalFormat, GLenum textureFormat, GLenum textureType) { @@ -304,6 +301,38 @@ void FluidRenderer::initFullscreenQuad() { std::cout << "Fullscreen quad initialized." << std::endl; } +void FluidRenderer::resizeFramebuffer( + ShaderProgram& shaderProgram, + GLenum textureInternalFormat, + GLenum textureFormat, + GLenum textureType, + int newWidth, + int newHeight) +{ + // Bind the FBO + glBindFramebuffer(GL_FRAMEBUFFER, shaderProgram.fbo); + + // Resize the texture + glBindTexture(GL_TEXTURE_2D, shaderProgram.fboTexture); + glTexImage2D(GL_TEXTURE_2D, 0, textureInternalFormat, + newWidth, newHeight, 0, + textureFormat, textureType, nullptr); + + // Resize the renderbuffer + glBindRenderbuffer(GL_RENDERBUFFER, shaderProgram.depthRBO); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, newWidth, newHeight); + + // Check completeness + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "FBO (ID %d) not complete after resize: 0x%X\n", + shaderProgram.programID, glCheckFramebufferStatus(GL_FRAMEBUFFER)); + } + + // Unbind + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + + // Resize Framebuffers void FluidRenderer::resizeFBO(int newWidth, int newHeight) { if (newWidth <= 0 || newHeight <= 0) return; @@ -312,33 +341,19 @@ void FluidRenderer::resizeFBO(int newWidth, int newHeight) { m_fbHeight = newHeight; // Resize Normal Render Shader FBO - glBindFramebuffer(GL_FRAMEBUFFER, m_normalRenderProgram.fbo); - - glBindTexture(GL_TEXTURE_2D, m_normalRenderProgram.fboTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_fbWidth, m_fbHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glBindRenderbuffer(GL_RENDERBUFFER, m_normalRenderProgram.depthRBO); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - fprintf(stderr, "Normal Render Shader FBO not complete after resize: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER)); - } + resizeFramebuffer(m_normalRenderProgram, + GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, + newWidth, newHeight); // Resize Depth Render Shader FBO - glBindFramebuffer(GL_FRAMEBUFFER, m_depthRenderProgram.fbo); + resizeFramebuffer(m_depthRenderProgram, + GL_R32F, GL_RED, GL_FLOAT, + newWidth, newHeight); - glBindTexture(GL_TEXTURE_2D, m_depthRenderProgram.fboTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, m_fbWidth, m_fbHeight, 0, GL_RED, GL_FLOAT, NULL); // Use GL_R32F for depth storage - - glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderProgram.depthRBO); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - fprintf(stderr, "Depth Render Shader FBO not complete after resize: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER)); - } - - // Unbind framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, 0); + // Resize Visualization Render Shader FBO + resizeFramebuffer(m_visualizationProgram, + GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, + newWidth, newHeight); std::cout << "Framebuffers resized to " << newWidth << "x" << newHeight << "." << std::endl; } @@ -349,62 +364,48 @@ void FluidRenderer::setVBOs(GLuint particleVBO, GLuint boundaryVBO) { m_boundaryVBO = boundaryVBO; } -// Render Particles -void FluidRenderer::renderParticles(size_t particleCount, const ShaderProgram& shader) { - // Set particle color - glUseProgram(shader.programID); - glUniform3f(shader.uColorLoc, 0.29f, 0.573f, 1.0f); - - // Bind the particle VBO - glBindBuffer(GL_ARRAY_BUFFER, m_particleVBO); - - // Enable the 'aPosition' attribute - glEnableVertexAttribArray(shader.positionAttribLoc); - - // Define the layout of the 'aPosition' attribute +void FluidRenderer::renderPoints(GLuint vbo, + size_t count, + const ShaderProgram& shaderProgram, + const vec3& color) +{ + glUseProgram(shaderProgram.programID); + glUniform3f(shaderProgram.uColorLoc, color.x, color.y, color.z); + + // Bind the VBO + glBindBuffer(GL_ARRAY_BUFFER, vbo); + + // Enable position attribute + glEnableVertexAttribArray(shaderProgram.positionAttribLoc); glVertexAttribPointer( - shader.positionAttribLoc, // Attribute location - 3, // Number of components (x, y, z) - GL_FLOAT, // Data type - GL_FALSE, // Normalized - sizeof(float3), // Stride - (void*)0 // Offset + shaderProgram.positionAttribLoc, // location + 3, // number of components + GL_FLOAT, // type + GL_FALSE, // normalized? + sizeof(float3), // stride + (void*)0 // offset ); - - // Draw the particles as points - glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(particleCount)); - - // Disable the 'aPosition' attribute - glDisableVertexAttribArray(shader.positionAttribLoc); + + // Draw + glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(count)); + + // Disable + glDisableVertexAttribArray(shaderProgram.positionAttribLoc); +} + + +// Render Particles +void FluidRenderer::renderParticles(size_t particleCount, + const ShaderProgram& shaderProgram) +{ + renderPoints(m_particleVBO, particleCount, shaderProgram, vec3(0.29f, 0.573f, 1.0f)); } // Render Boundaries -void FluidRenderer::renderBoundaries(size_t boundaryCount, const ShaderProgram& shader) { - // Set boundary color - glUseProgram(shader.programID); - glUniform3f(shader.uColorLoc, 0.29f, 1.0f, 0.57f); - - // Bind the boundary VBO - glBindBuffer(GL_ARRAY_BUFFER, m_boundaryVBO); - - // Enable the 'aPosition' attribute - glEnableVertexAttribArray(shader.positionAttribLoc); - - // Define the layout of the 'aPosition' attribute - glVertexAttribPointer( - shader.positionAttribLoc, // Attribute location - 3, // Number of components (x, y, z) - GL_FLOAT, // Data type - GL_FALSE, // Normalized - sizeof(float3), // Stride - (void*)0 // Offset - ); - - // Draw the boundary particles as points - glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(boundaryCount)); - - // Disable the 'aPosition' attribute - glDisableVertexAttribArray(shader.positionAttribLoc); +void FluidRenderer::renderBoundaries(size_t boundaryCount, + const ShaderProgram& shaderProgram) +{ + renderPoints(m_boundaryVBO, boundaryCount, shaderProgram, vec3(0.29f, 1.0f, 0.57f)); } // Render Normal Frame @@ -416,29 +417,23 @@ void FluidRenderer::renderNormalFrame(size_t particleCount, size_t boundaryCount // Set the viewport to match the framebuffer size glViewport(0, 0, m_fbWidth, m_fbHeight); - // Set clear color (background) glClearColor(0.9f, 0.9f, 0.9f, 1.0f); // Clear color and depth buffers - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - // Enable depth writing glDepthMask(GL_TRUE); - // Use the Normal Render Shader program glUseProgram(m_normalRenderProgram.programID); glBindVertexArray(particles_vao); - // Update shader with camera projection matrix mat4 projectionMatrix = m_camera->getProjectionMatrix(); glUniformMatrix4fv(m_normalRenderProgram.projectionMatrixLoc, 1, GL_TRUE, projectionMatrix.m); - // Update shader with camera view matrix mat4 viewMatrix = m_camera->getViewMatrix(); glUniformMatrix4fv(m_normalRenderProgram.viewMatrixLoc, 1, GL_TRUE, viewMatrix.m); - // Render particles renderParticles(particleCount, m_normalRenderProgram); // Render boundaries if enabled @@ -459,35 +454,28 @@ void FluidRenderer::renderDepthFrame(size_t particleCount, size_t boundaryCount) // Set the viewport to match the framebuffer size glViewport(0, 0, m_fbWidth, m_fbHeight); - // Set clear color (background) - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Typically black for depth + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Typically black for depth? // Clear color and depth buffers - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - // Enable depth writing glDepthMask(GL_TRUE); - // Use the Depth Render Shader program glUseProgram(m_depthRenderProgram.programID); glBindVertexArray(particles_vao); - // Update shader with camera projection matrix mat4 projectionMatrix = m_camera->getProjectionMatrix(); glUniformMatrix4fv(m_depthRenderProgram.projectionMatrixLoc, 1, GL_TRUE, projectionMatrix.m); - // Update shader with camera view matrix mat4 viewMatrix = m_camera->getViewMatrix(); glUniformMatrix4fv(m_depthRenderProgram.viewMatrixLoc, 1, GL_TRUE, viewMatrix.m); - // Set sphereRadius uniform if (m_depthRenderProgram.sphereRadiusLoc != -1) { - glUniform1f(m_depthRenderProgram.sphereRadiusLoc, 1.0f); // Adjust based on your simulation + glUniform1f(m_depthRenderProgram.sphereRadiusLoc, 1.0f); } - // Set near and far planes - float cameraNearPlane = m_camera->getNearPlane(); // Replace with actual method - float cameraFarPlane = m_camera->getFarPlane(); // Replace with actual method + float cameraNearPlane = m_camera->getNearPlane(); + float cameraFarPlane = m_camera->getFarPlane(); if (m_depthRenderProgram.nearPlaneLoc != -1) { glUniform1f(m_depthRenderProgram.nearPlaneLoc, cameraNearPlane); @@ -496,14 +484,8 @@ void FluidRenderer::renderDepthFrame(size_t particleCount, size_t boundaryCount) glUniform1f(m_depthRenderProgram.farPlaneLoc, cameraFarPlane); } - // Render particles renderParticles(particleCount, m_depthRenderProgram); - // Render boundaries if enabled - if (m_camera->shouldDisplayBorder()) { - renderBoundaries(boundaryCount, m_depthRenderProgram); - } - // Unbind the framebuffer to return to default framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -517,10 +499,8 @@ void FluidRenderer::visualizeBuffer(RenderStage stage) glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // White background for visualization glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Disable depth testing for visualization glDisable(GL_DEPTH_TEST); - // Use the Visualization Shader Program glUseProgram(m_visualizationProgram.programID); // Retrieve the appropriate texture based on RenderStage @@ -549,20 +529,17 @@ void FluidRenderer::visualizeBuffer(RenderStage stage) glBindFramebuffer(GL_FRAMEBUFFER, 0); } -// Retrieve Texture Based on RenderStage GLuint FluidRenderer::getTexture(RenderStage stage) const { switch (stage) { case RenderStage::FinalOutput: return m_normalRenderProgram.fboTexture; case RenderStage::DepthBuffer: return m_depthRenderProgram.fboTexture; - // Add more cases here if additional RenderStages are implemented default: return 0; // Return 0 if no valid stage was selected } } -// Getter for Visualization Texture GLuint FluidRenderer::getVisualizationTexture() const { return m_visualizationProgram.fboTexture; } diff --git a/src/include/FluidRenderer.h b/src/include/FluidRenderer.h index 40d20c2646aa855c51701e8042642d7d777656cf..bebb5c8efd79254f08f6f0f09b7f82939b69e8ad 100644 --- a/src/include/FluidRenderer.h +++ b/src/include/FluidRenderer.h @@ -92,9 +92,22 @@ private: void initializeFramebuffer(ShaderProgram& shaderProgram, GLenum textureInternalFormat, GLenum textureFormat, GLenum textureType); void initFBOs(); // Set up framebuffers for each shader program void initFullscreenQuad(); // Set up fullscreen quad for visualization + void setupShaderProgram(ShaderProgram& shaderProgram); void deleteFramebufferResources(ShaderProgram& shaderProgram); - + void resizeFramebuffer( + ShaderProgram& shaderProgram, + GLenum textureInternalFormat, + GLenum textureFormat, + GLenum textureType, + int newWidth, + int newHeight); + + void renderPoints( + GLuint vbo, + size_t count, + const ShaderProgram& shaderProgram, + const vec3& color); // Rendering helper methods void renderParticles(size_t particleCount, const ShaderProgram& shader); void renderBoundaries(size_t boundaryCount, const ShaderProgram& shader);