Implement double frame buffering

This commit is contained in:
Abdelrahman Said 2024-12-27 22:22:32 +00:00
parent 9de54d016d
commit 68cc990650
3 changed files with 124 additions and 4 deletions

18
shaders/pp_frag.glsl Normal file
View File

@ -0,0 +1,18 @@
#version 330 core
struct Material {
sampler2D diffuse1;
sampler2D specular1;
float shininess;
};
in vec2 uv_coords;
uniform Material material;
// uniform sampler2D image_texture;
out vec4 color;
void main() {
color = vec4(vec3(texture(material.diffuse1, uv_coords)), 1.0);
}

12
shaders/pp_vert.glsl Normal file
View File

@ -0,0 +1,12 @@
#version 330 core
layout(location=0) in vec3 position;
layout(location=1) in vec3 normal;
layout(location=2) in vec2 uv;
out vec2 uv_coords;
void main() {
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
uv_coords = uv;
}

View File

@ -54,6 +54,7 @@ enum exit_codes : int {
EXIT_CODE_WINDOW_CREATION_FAILED, EXIT_CODE_WINDOW_CREATION_FAILED,
EXIT_CODE_OPENGL_CONTEXT_FAILED, EXIT_CODE_OPENGL_CONTEXT_FAILED,
EXIT_CODE_GLAD_LOADER_FAILED, EXIT_CODE_GLAD_LOADER_FAILED,
EXIT_CODE_INCOMPLETE_FRAME_BUFFER,
}; };
class Shader { class Shader {
@ -135,6 +136,15 @@ class Model {
std::vector<Texture2D> load_material_textures(aiMaterial *mat, aiTextureType type); std::vector<Texture2D> load_material_textures(aiMaterial *mat, aiTextureType type);
}; };
struct FrameBuffer {
GLuint fbo;
GLuint color;
GLuint depth_stencil;
};
FrameBuffer create_frame_buffer(unsigned int width, unsigned int height);
void delete_frame_buffer(FrameBuffer &buffer);
int main() { int main() {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
return EXIT_CODE_SDL_INIT_FAILED; return EXIT_CODE_SDL_INIT_FAILED;
@ -166,8 +176,7 @@ int main() {
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glEnable(GL_DEPTH_TEST); FrameBuffer offscreen_buffer = create_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT);
glEnable(GL_CULL_FACE);
std::vector<Vertex> vertices = { std::vector<Vertex> vertices = {
// positions // normals // texture coords // positions // normals // texture coords
@ -215,8 +224,23 @@ int main() {
Model backpack = {"models/suzanne/suzanne.obj"}; Model backpack = {"models/suzanne/suzanne.obj"};
Mesh light = {vertices, indices, {}}; Mesh light = {vertices, indices, {}};
std::vector<Vertex> screen_vertices = {
Vertex{glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 0.0f)},
Vertex{glm::vec3( 1.0f, -1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)},
Vertex{glm::vec3(-1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f)},
Vertex{glm::vec3( 1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f)},
};
std::vector<GLuint> screen_indices = {
0, 1, 2,
2, 1, 3,
};
Mesh screen = {screen_vertices, screen_indices, {}};
Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"}; Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"};
Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"}; Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"};
Shader post_processing {"shaders/pp_vert.glsl", "shaders/pp_frag.glsl"};
const float camera_speed = 25.0f; const float camera_speed = 25.0f;
glm::vec3 camera_position = glm::vec3(-2.0f, 0.0f, 6.0f); glm::vec3 camera_position = glm::vec3(-2.0f, 0.0f, 6.0f);
@ -356,6 +380,10 @@ int main() {
SDL_GL_GetDrawableSize(wnd, &w, &h); SDL_GL_GetDrawableSize(wnd, &w, &h);
glViewport(0, 0, w, h); glViewport(0, 0, w, h);
SDL_WarpMouseInWindow(wnd, (int)(w * 0.5f), (int)(h * 0.5f)); SDL_WarpMouseInWindow(wnd, (int)(w * 0.5f), (int)(h * 0.5f));
// Recreate offscreen frame buffer
delete_frame_buffer(offscreen_buffer);
offscreen_buffer = create_frame_buffer(w, h);
} }
break; break;
} }
@ -375,8 +403,13 @@ int main() {
main_shader.set_mat4("view", view); main_shader.set_mat4("view", view);
light_shader.set_mat4("view", view); light_shader.set_mat4("view", view);
// Main render pass
glBindFramebuffer(GL_FRAMEBUFFER, offscreen_buffer.fbo);
glClearColor(0.04f, 0.08f, 0.08f, 1.0f); glClearColor(0.04f, 0.08f, 0.08f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
normal_mat = glm::transpose(glm::inverse(model)); normal_mat = glm::transpose(glm::inverse(model));
@ -395,6 +428,23 @@ int main() {
light.draw(light_shader); light.draw(light_shader);
} }
// wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Post processing pass
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
post_processing.activate();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, offscreen_buffer.color);
post_processing.set_int("image_texture", 0);
screen.draw(post_processing);
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
} }
@ -726,3 +776,43 @@ std::vector<Texture2D> Model::load_material_textures(aiMaterial *material, aiTex
return textures; return textures;
} }
FrameBuffer create_frame_buffer(unsigned int width, unsigned int height) {
FrameBuffer buffer = {};
glGenFramebuffers(1, &buffer.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, buffer.fbo);
// Create color texture
glGenTextures(1, &buffer.color);
glBindTexture(GL_TEXTURE_2D, buffer.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
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, buffer.color, 0);
// Create depth and stencil buffers
glGenRenderbuffers(1, &buffer.depth_stencil);
glBindRenderbuffer(GL_RENDERBUFFER, buffer.depth_stencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer.depth_stencil);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
printf("Incomplete frame buffer\n");
exit(EXIT_CODE_INCOMPLETE_FRAME_BUFFER);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
return buffer;
}
void delete_frame_buffer(FrameBuffer &buffer) {
glDeleteFramebuffers(1, &buffer.fbo);
glDeleteTextures(1, &buffer.color);
glDeleteRenderbuffers(1, &buffer.depth_stencil);
}