Skip to content
Snippets Groups Projects
Commit 93c4576b authored by Adam Nyberg's avatar Adam Nyberg
Browse files

WIP: Depth buffer now working

parent 6a5f4cda
No related branches found
No related tags found
No related merge requests found
// Fragment Shader
#version 330 core
in vec3 vEyeSpacePos;
uniform mat4 projectionMatrix;
uniform float sphereRadius;
uniform vec3 lightDir; // If you decide to pass it from your application
uniform float zNear;
uniform float zFar;
out vec4 FragColor;
out vec4 FragColor; // Color output for depth visualization
/*
void main()
{
// Convert gl_PointCoord from [0,1] to [-1,1]
vec2 texCoord = gl_PointCoord * 2.0 - 1.0;
float r2 = dot(texCoord, texCoord);
if (r2 > 1.0) discard;
float z = sqrt(1.0 - r2);
vec3 N = vec3(texCoord, z);
vec3 pixelPos = vEyeSpacePos + N * sphereRadius;
vec4 clipSpacePos = projectionMatrix * vec4(pixelPos, 1.0);
float depth = clipSpacePos.z / clipSpacePos.w;
gl_FragDepth = depth;
// Map depth to grayscale color
// Depth values are in [0, 1], but due to non-linearity, you might need to adjust
FragColor = vec4(vec3(depth), 1.0);
}
*/
void main()
{
vec2 texCoord = gl_PointCoord * 2.0 - 1.0;
float r2 = dot(texCoord, texCoord);
if (r2 > 1.0) discard;
// Discard fragments outside the circle to form a sphere silhouette
if (r2 > 1.0)
discard;
// Calculate the sphere's surface normal offset in eye-space
float z = sqrt(1.0 - r2);
vec3 N = vec3(texCoord, z);
// Compute the fragment's actual position on the sphere surface in eye space
vec3 pixelPos = vEyeSpacePos + N * sphereRadius;
vec4 clipSpacePos = projectionMatrix * vec4(pixelPos, 1.0);
gl_FragDepth = clipSpacePos.z / clipSpacePos.w;
float diffuse = max(dot(normalize(N), normalize(lightDir)), 0.0);
// Compute linear depth (distance from camera)
float linearDepth = length(pixelPos); // Distance from camera in eye-space
vec3 baseColor = vec3(0.29, 0.573, 1.0);
vec3 depthColor = vec3(1.0, 1.0, 1.0)/gl_FragDepth;
vec3 shadedColor = baseColor * diffuse;
// Normalize linear depth to [0, 1]
float normalizedDepth = (linearDepth - zNear) / (zFar - zNear);
normalizedDepth = clamp(normalizedDepth, 0.0, 1.0);
FragColor = vec4(shadedColor, 1.0);
// Output the linear depth as grayscale
FragColor = vec4(vec3(normalizedDepth), 1.0);
}
\ No newline at end of file
// Vertex Shader
#version 330 core
layout(location = 0) in vec3 aPosition;
......
// FluidRenderer.cpp
#include "include/FluidRenderer.h"
#include "GL_utilities.h" // For loadShaders
#include <iostream>
......@@ -8,182 +9,480 @@
namespace FluidSimulation {
FluidRenderer::FluidRenderer(int width, int height, Camera* camera)
: m_fbWidth(width), m_fbHeight(height), m_camera(camera) {
// Constructor
FluidRenderer::FluidRenderer(int width, int height, Camera* camera)
: m_fbWidth(width), m_fbHeight(height), m_camera(camera),
m_particleVBO(0), m_boundaryVBO(0) {
init();
}
init();
// Destructor
FluidRenderer::~FluidRenderer() {
// Cleanup Normal Render Program
if (m_normalRenderProgram.fboTexture != 0) {
glDeleteTextures(1, &m_normalRenderProgram.fboTexture);
}
FluidRenderer::~FluidRenderer() {
glDeleteTextures(1, &m_fboTexture);
glDeleteRenderbuffers(1, &m_depthRBO);
glDeleteFramebuffers(1, &m_fbo);
std::cout << "FluidRenderer destroyed." << std::endl;
if (m_normalRenderProgram.depthRBO != 0) {
glDeleteRenderbuffers(1, &m_normalRenderProgram.depthRBO);
}
if (m_normalRenderProgram.fbo != 0) {
glDeleteFramebuffers(1, &m_normalRenderProgram.fbo);
}
void FluidRenderer::init() {
initGLEW();
initOpenGLSettings();
initShaders();
initShaderUniforms();
initFBOs();
// Cleanup Depth Render Program
if (m_depthRenderProgram.fboTexture != 0) {
glDeleteTextures(1, &m_depthRenderProgram.fboTexture);
}
if (m_depthRenderProgram.depthRBO != 0) {
glDeleteRenderbuffers(1, &m_depthRenderProgram.depthRBO);
}
if (m_depthRenderProgram.fbo != 0) {
glDeleteFramebuffers(1, &m_depthRenderProgram.fbo);
}
std::cout << "FluidRenderer destroyed." << std::endl;
}
// Initialization
void FluidRenderer::init() {
initGLEW();
initOpenGLSettings();
initShaders();
initShaderUniforms();
initFBOs();
}
void FluidRenderer::initGLEW() {
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (err != GLEW_OK) {
fprintf(stderr, "Error initializing GLEW: %s\n", glewGetErrorString(err));
exit(1);
}
std::cout << "GLEW initialized successfully." << std::endl;
// Initialize GLEW
void FluidRenderer::initGLEW() {
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (err != GLEW_OK) {
fprintf(stderr, "Error initializing GLEW: %s\n", glewGetErrorString(err));
exit(1);
}
std::cout << "GLEW initialized successfully." << std::endl;
}
// Initialize OpenGL Settings
void FluidRenderer::initOpenGLSettings() {
glEnable(GL_PROGRAM_POINT_SIZE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
// Enable OpenGL Debug Output
//glEnable(GL_DEBUG_OUTPUT);
//glDebugMessageCallback(MessageCallback, 0);
void FluidRenderer::initOpenGLSettings() {
glEnable(GL_PROGRAM_POINT_SIZE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
// Create and bind a Vertex Array Object (VAO) - mandatory for OpenGL 3.3+
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and bind a VAO - mandatory for opeeeenGl 3.3+ ??
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
std::cout << "OpenGL settings initialized." << std::endl;
}
// Debug callback function
void GLAPIENTRY MessageCallback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam)
{
std::cerr << "GL CALLBACK: " << (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "")
<< " type = " << type
<< ", severity = " << severity
<< ", message = " << message << std::endl;
}
std::cout << "OpenGL settings initialized." << std::endl;
// Initialize Shaders
void FluidRenderer::initShaders() {
// Normal Render Shader
m_normalRenderProgram.programID = loadShaders("../shaders/particle.vert", "../shaders/particle.frag");
if (m_normalRenderProgram.programID == 0) {
std::cerr << "Failed to load Normal Render Shaders." << std::endl;
exit(1);
}
glUseProgram(m_normalRenderProgram.programID);
std::cout << "Normal Render Shaders initialized successfully." << std::endl;
// Depth Render Shader
m_depthRenderProgram.programID = loadShaders("../shaders/depth.vert", "../shaders/depth.frag");
if (m_depthRenderProgram.programID == 0) {
std::cerr << "Failed to load Depth Render Shaders." << std::endl;
exit(1);
}
glUseProgram(m_depthRenderProgram.programID);
std::cout << "Depth Render Shaders initialized successfully." << std::endl;
}
// Initialize Shader Uniforms
void FluidRenderer::initShaderUniforms() {
// Normal Render Shader Uniforms
glUseProgram(m_normalRenderProgram.programID);
void FluidRenderer::initShaders() {
m_shaderProgram = loadShaders("../shaders/particle.vert", "../shaders/particle.frag");
glUseProgram(m_shaderProgram);
std::cout << "Shaders initialized successfully." << std::endl;
m_normalRenderProgram.positionAttribLoc = glGetAttribLocation(m_normalRenderProgram.programID, "aPosition");
if (m_normalRenderProgram.positionAttribLoc == -1) {
fprintf(stderr, "Normal Render Shader: Could not find attribute 'aPosition'\n");
} else {
printf("Normal Render Shader: Attribute 'aPosition' location: %d\n", m_normalRenderProgram.positionAttribLoc);
}
void FluidRenderer::initShaderUniforms() {
m_positionAttribLoc = glGetAttribLocation(m_shaderProgram, "aPosition");
if (m_positionAttribLoc == -1) {
fprintf(stderr, "Could not find attribute 'aPosition'\n");
} else {
printf("Attribute 'aPosition' location: %d\n", m_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");
m_modelMatrixLoc = glGetUniformLocation(m_shaderProgram, "modelMatrix");
m_viewMatrixLoc = glGetUniformLocation(m_shaderProgram, "viewMatrix");
m_projectionMatrixLoc = glGetUniformLocation(m_shaderProgram, "projectionMatrix");
m_pointRadiusLoc = glGetUniformLocation(m_shaderProgram, "pointRadius");
m_pointScaleLoc = glGetUniformLocation(m_shaderProgram, "pointScale");
m_uColorLoc = glGetUniformLocation(m_shaderProgram, "uColor");
if (m_normalRenderProgram.pointRadiusLoc != -1)
glUniform1f(m_normalRenderProgram.pointRadiusLoc, 20.0f);
if (m_normalRenderProgram.pointScaleLoc != -1)
glUniform1f(m_normalRenderProgram.pointScaleLoc, 10.0f);
// Should be moved to a setting and be controllable with GUI
if (m_pointRadiusLoc != -1) glUniform1f(m_pointRadiusLoc, 20.0f); // Example radius
if (m_pointScaleLoc != -1) glUniform1f(m_pointScaleLoc, 10.0f); // Example scale
mat4 modelMatrix = IdentityMatrix();
glUniformMatrix4fv(m_normalRenderProgram.modelMatrixLoc, 1, GL_TRUE, modelMatrix.m);
mat4 modelMatrix = IdentityMatrix();
glUniformMatrix4fv(m_modelMatrixLoc, 1, GL_TRUE, modelMatrix.m);
std::cout << "Normal Render Shader uniforms initialized." << std::endl;
std::cout << "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);
}
void FluidRenderer::initFBOs() {
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
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 (m_depthRenderProgram.farPlaneLoc != -1) {
glUniform1f(m_depthRenderProgram.farPlaneLoc, cameraFarPlane);
}
// Create texture for FBO
glGenTextures(1, &m_fboTexture);
glBindTexture(GL_TEXTURE_2D, m_fboTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_fbWidth, m_fbHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fboTexture, 0);
glUniformMatrix4fv(m_depthRenderProgram.modelMatrixLoc, 1, GL_TRUE, modelMatrix.m);
// Create depth renderbuffer
glGenRenderbuffers(1, &m_depthRBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRBO);
std::cout << "Depth Render Shader uniforms initialized." << std::endl;
}
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "FBO not complete: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
// Initialize Framebuffers
void FluidRenderer::initFBOs() {
// Initialize Normal Render Shader FBO
glGenFramebuffers(1, &m_normalRenderProgram.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_normalRenderProgram.fbo);
glGenTextures(1, &m_normalRenderProgram.fboTexture);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_normalRenderProgram.fboTexture, 0);
glGenRenderbuffers(1, &m_normalRenderProgram.depthRBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_normalRenderProgram.depthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_normalRenderProgram.depthRBO);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Normal Render Shader FBO not complete: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind FBO
std::cout << "FBO initialized successfully." << std::endl;
// Initialize Depth Render Shader FBO
/*
glGenFramebuffers(1, &m_depthRenderProgram.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_depthRenderProgram.fbo);
glGenTextures(1, &m_depthRenderProgram.fboTexture);
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
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Ensure magnification filtering is set
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_depthRenderProgram.fboTexture, 0);
glGenRenderbuffers(1, &m_depthRenderProgram.depthRBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderProgram.depthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderProgram.depthRBO);
// Specify which color attachments will be used for rendering
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, drawBuffers);
// Check if the Depth Render Shader FBO is complete
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Depth Render Shader FBO not complete: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
void FluidRenderer::resizeFBO(int newWidth, int newHeight) {
if (newWidth <= 0 || newHeight <= 0) return;
// Unbind the framebuffer to return to default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
*/
// Initialize Depth Render Shader FBO with RGB format
glGenFramebuffers(1, &m_depthRenderProgram.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_depthRenderProgram.fbo);
glGenTextures(1, &m_depthRenderProgram.fboTexture);
glBindTexture(GL_TEXTURE_2D, m_depthRenderProgram.fboTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_fbWidth, m_fbHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // RGB format
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_depthRenderProgram.fboTexture, 0);
glGenRenderbuffers(1, &m_depthRenderProgram.depthRBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderProgram.depthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderProgram.depthRBO);
// Specify which color attachments will be used for rendering
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, drawBuffers);
// Check if the Depth Render Shader FBO is complete
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Depth Render Shader FBO not complete: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
m_fbWidth = newWidth;
m_fbHeight = newHeight;
// Unbind the framebuffer to return to default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Bind the existing FBO
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// Resize the color attachment texture
glBindTexture(GL_TEXTURE_2D, m_fboTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_fbWidth, m_fbHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
std::cout << "Framebuffers for both shaders initialized successfully." << std::endl;
}
// Resize the depth renderbuffer
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight);
// Resize Framebuffers
void FluidRenderer::resizeFBO(int newWidth, int newHeight) {
if (newWidth <= 0 || newHeight <= 0) return;
// Check framebuffer completeness
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "FBO not complete after resize: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
m_fbWidth = newWidth;
m_fbHeight = newHeight;
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind FBO
//std::cout << "FBO resized to " << newWidth << "x" << newHeight << "." << std::endl;
}
// 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);
void FluidRenderer::setVBOs(GLuint particleVBO, GLuint boundaryVBO) {
m_particleVBO = particleVBO;
m_boundaryVBO = boundaryVBO;
}
glBindRenderbuffer(GL_RENDERBUFFER, m_normalRenderProgram.depthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_fbWidth, m_fbHeight);
void FluidRenderer::renderParticles(size_t particleCount) {
glUniform3f(m_uColorLoc, 0.29f, 0.573f, 1.0f);
glBindBuffer(GL_ARRAY_BUFFER, m_particleVBO);
glEnableVertexAttribArray(m_positionAttribLoc);
glVertexAttribPointer(m_positionAttribLoc, 3, GL_FLOAT, GL_FALSE, sizeof(float3), (void*)0);
glDrawArrays(GL_POINTS, 0, particleCount); // Use actual particle count
glDisableVertexAttribArray(m_positionAttribLoc);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Normal Render Shader FBO not complete after resize: 0x%X\n", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
void FluidRenderer::renderBoundaries(size_t boundaryCount) {
glUniform3f(m_uColorLoc, 0.29f, 1.0f, 0.57f);
glBindBuffer(GL_ARRAY_BUFFER, m_boundaryVBO);
glEnableVertexAttribArray(m_positionAttribLoc);
glVertexAttribPointer(m_positionAttribLoc, 3, GL_FLOAT, GL_FALSE, sizeof(float3), (void*)0);
glDrawArrays(GL_POINTS, 0, boundaryCount); // Use actual boundary particle count
glDisableVertexAttribArray(m_positionAttribLoc);
// Resize Depth Render Shader FBO
glBindFramebuffer(GL_FRAMEBUFFER, m_depthRenderProgram.fbo);
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));
}
void FluidRenderer::renderFrame(size_t particleCount, size_t boundaryCount) {
glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
// Unbind framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glViewport(0, 0, m_fbWidth, m_fbHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
std::cout << "Framebuffers resized to " << newWidth << "x" << newHeight << "." << std::endl;
}
glUseProgram(m_shaderProgram);
// Set VBOs
void FluidRenderer::setVBOs(GLuint particleVBO, GLuint boundaryVBO) {
m_particleVBO = particleVBO;
m_boundaryVBO = boundaryVBO;
}
// Update shader with camera matrices
mat4 projectionMatrix = m_camera->getProjectionMatrix();
glUniformMatrix4fv(m_projectionMatrixLoc, 1, GL_TRUE, projectionMatrix.m);
// 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
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 particles as points
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(particleCount));
// Disable the 'aPosition' attribute
glDisableVertexAttribArray(shader.positionAttribLoc);
}
mat4 viewMatrix = m_camera->getViewMatrix();
glUniformMatrix4fv(m_viewMatrixLoc, 1, GL_TRUE, viewMatrix.m);
// 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);
}
// Render particles
renderParticles(particleCount);
// Render Normal Frame
void FluidRenderer::renderNormalFrame(size_t particleCount, size_t boundaryCount) {
// Bind the Normal Render Shader framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_normalRenderProgram.fbo);
// 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);
// Enable depth writing
glDepthMask(GL_TRUE);
// Use the Normal Render Shader program
glUseProgram(m_normalRenderProgram.programID);
// 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
if (m_camera->shouldDisplayBorder()) {
renderBoundaries(boundaryCount, m_normalRenderProgram);
}
// Render boundaries if enabled
if (m_camera->shouldDisplayBorder()) {
renderBoundaries(boundaryCount);
}
// Unbind the framebuffer to return to default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Render Depth Frame
void FluidRenderer::renderDepthFrame(size_t particleCount, size_t boundaryCount) {
// Bind the Depth Render Shader framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthRenderProgram.fbo);
// 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
// Clear color and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Enable depth writing
glDepthMask(GL_TRUE);
// Use the Depth Render Shader program
glUseProgram(m_depthRenderProgram.programID);
// 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
}
// 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 (m_depthRenderProgram.farPlaneLoc != -1) {
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);
}
// 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
}
}
} // namespace FluidSimulation
\ No newline at end of file
......@@ -18,7 +18,7 @@ namespace FluidSimulation {
45.0f,
appSettings->width / (float)appSettings->height,
0.1f,
500.0f
30.0f
);
m_fluidRenderer = new FluidRenderer(appSettings->width, appSettings->height, m_camera);
......@@ -154,7 +154,20 @@ namespace FluidSimulation {
{
m_fluidSimulation->setSimulationMode(static_cast<SimulationMode>(selectedOption));
}
const char* stageOptions[] = {
"Normal",
"Depth Buffer",
"Thickness Buffer",
"Filtered Depth",
"Depth Normals",
"Filtered Thickness"
};
if (ImGui::Combo("Rendering Stage", reinterpret_cast<int*>(&selectedStage), stageOptions, IM_ARRAYSIZE(stageOptions)))
{
std::cout << "Selected Rendering Stage: " << static_cast<int>(selectedStage) << std::endl;
}
ImGui::Separator();
......@@ -183,12 +196,23 @@ namespace FluidSimulation {
if (m_updatePhysics)
{
m_fluidSimulation->updateSimulation();
m_fluidRenderer->renderFrame(
m_fluidSimulation->getParticleCount(),
m_fluidSimulation->getBoundaryParticleCount()
);
if (selectedStage == RenderStage::FinalOutput)
{
m_fluidRenderer->renderNormalFrame(
m_fluidSimulation->getParticleCount(),
m_fluidSimulation->getBoundaryParticleCount()
);
}
else
{
m_fluidRenderer->renderDepthFrame(
m_fluidSimulation->getParticleCount(),
m_fluidSimulation->getBoundaryParticleCount()
);
}
}
/*
// Display FBO texture in ImGui window
ImGui::Begin("Simulation");
......@@ -198,6 +222,22 @@ namespace FluidSimulation {
ImGui::Image((ImTextureID)(uintptr_t)m_fluidRenderer->getFBOTexture(), availableSize, ImVec2(0, 1), ImVec2(1, 0)); // Flip Y-axis
ImGui::End();
*/
ImGui::Begin("Simulation");
ImVec2 availableSize = ImGui::GetContentRegionAvail();
GLuint textureID = m_fluidRenderer->getTexture(selectedStage);
if (textureID != 0)
{
ImGui::Image((ImTextureID)(uintptr_t)textureID, availableSize, ImVec2(0, 1), ImVec2(1, 0));
}
else
{
ImGui::Text("No texture available for the selected stage.");
}
ImGui::End();
}
......
......@@ -28,6 +28,8 @@ namespace FluidSimulation {
bool shouldDisplayBorder() const { return displayBorder; }
void toggleDisplayBorder() { displayBorder = !displayBorder; }
void setAspectRatio(float aspect) { aspectRatio = aspect; }
float getNearPlane() { return zNear; };
float getFarPlane() { return zFar; };
};
void initCamera(Camera& camera);
......
// FluidRenderer.h
#pragma once
#include <GL/glew.h>
......@@ -7,48 +8,105 @@
namespace FluidSimulation {
class FluidRenderer {
private:
GLuint m_shaderProgram;
GLuint m_positionAttribLoc;
GLuint m_modelMatrixLoc;
GLuint m_viewMatrixLoc;
GLuint m_projectionMatrixLoc;
GLuint m_pointRadiusLoc;
GLuint m_pointScaleLoc;
GLuint m_uColorLoc;
GLuint m_particleVBO;
GLuint m_boundaryVBO;
GLuint m_fbo;
GLuint m_fboTexture;
GLuint m_depthRBO;
int m_fbWidth;
int m_fbHeight;
Camera* m_camera;
void initGLEW(); // Initialize GLEW
void initOpenGLSettings(); // Set up OpenGL state
void initShaders(); // Load and configure shaders
void initFBOs(); // Set up framebuffers
void initShaderUniforms(); // Configure shader uniforms
void renderParticles(size_t particleCount);
void renderBoundaries(size_t boundaryCount);
public:
FluidRenderer(int width, int height, Camera* camera);
~FluidRenderer();
void init(); // Consolidated initialization function
void resizeFBO(int newWidth, int newHeight);
void setVBOs(GLuint particleVBO, GLuint boundaryVBO);
void renderFrame(size_t particleCount, size_t boundaryCount);
GLuint getFBOTexture() const { return m_fboTexture; }
};
}
// Enumeration for different rendering stages
enum class RenderStage {
FinalOutput,
DepthBuffer,
ThicknessBuffer,
FilteredDepth,
DepthNormals,
FilteredThickness
};
// Structure to encapsulate shader program details
struct ShaderProgram {
// Shader program ID
GLuint programID;
// Attribute locations
GLuint positionAttribLoc;
// Uniform locations
GLuint modelMatrixLoc;
GLuint viewMatrixLoc;
GLuint projectionMatrixLoc;
GLuint pointRadiusLoc;
GLuint pointScaleLoc;
GLuint uColorLoc;
GLuint sphereRadiusLoc; // For depth shader
// New Uniform Locations for Depth Normalization
GLuint nearPlaneLoc;
GLuint farPlaneLoc;
// Framebuffer Object and its attachments
GLuint fbo;
GLuint fboTexture;
GLuint depthRBO;
// Constructor to initialize members
ShaderProgram()
: programID(0),
positionAttribLoc(0),
modelMatrixLoc(0),
viewMatrixLoc(0),
projectionMatrixLoc(0),
pointRadiusLoc(0),
pointScaleLoc(0),
uColorLoc(0),
sphereRadiusLoc(0),
nearPlaneLoc(0),
farPlaneLoc(0),
fbo(0),
fboTexture(0),
depthRBO(0) {}
};
class FluidRenderer {
private:
// Shader programs
ShaderProgram m_normalRenderProgram; // For particle shaders
ShaderProgram m_depthRenderProgram; // For depth shaders
// VBOs for particles and boundaries
GLuint m_particleVBO;
GLuint m_boundaryVBO;
// Framebuffer dimensions
int m_fbWidth;
int m_fbHeight;
// Pointer to the Camera object
Camera* m_camera;
// Initialization helper methods
void initGLEW(); // Initialize GLEW
void initOpenGLSettings(); // Set up OpenGL state
void initShaders(); // Load and configure shaders
void initShaderUniforms(); // Configure shader uniforms
void initFBOs(); // Set up framebuffers for each shader program
// Rendering helper methods
void renderParticles(size_t particleCount, const ShaderProgram& shader);
void renderBoundaries(size_t boundaryCount, const ShaderProgram& shader);
public:
// Constructor and Destructor
FluidRenderer(int width, int height, Camera* camera);
~FluidRenderer();
// Public methods
void init(); // Consolidated initialization function
void resizeFBO(int newWidth, int newHeight); // Resize framebuffers
void setVBOs(GLuint particleVBO, GLuint boundaryVBO); // Set VBOs
// 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
// Method to retrieve textures based on RenderStage
GLuint getTexture(RenderStage stage) const;
};
} // namespace FluidSimulation
......@@ -23,6 +23,7 @@ namespace FluidSimulation
FluidSimulation* m_fluidSimulation;
bool m_updatePhysics;
RenderStage selectedStage = RenderStage::FinalOutput;
void RenderControlPannel();
void RenderFluidView();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment