Implement double frame buffering
This commit is contained in:
		
							
								
								
									
										18
									
								
								shaders/pp_frag.glsl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								shaders/pp_frag.glsl
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										12
									
								
								shaders/pp_vert.glsl
									
									
									
									
									
										Normal 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; | ||||
| } | ||||
							
								
								
									
										94
									
								
								src/main.cc
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								src/main.cc
									
									
									
									
									
								
							| @@ -54,6 +54,7 @@ enum exit_codes : int { | ||||
|   EXIT_CODE_WINDOW_CREATION_FAILED, | ||||
|   EXIT_CODE_OPENGL_CONTEXT_FAILED, | ||||
|   EXIT_CODE_GLAD_LOADER_FAILED, | ||||
|   EXIT_CODE_INCOMPLETE_FRAME_BUFFER, | ||||
| }; | ||||
|  | ||||
| class Shader { | ||||
| @@ -135,6 +136,15 @@ class Model { | ||||
|     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() { | ||||
|   if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { | ||||
|     return EXIT_CODE_SDL_INIT_FAILED; | ||||
| @@ -166,8 +176,7 @@ int main() { | ||||
|  | ||||
|   glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); | ||||
|  | ||||
|   glEnable(GL_DEPTH_TEST); | ||||
|   glEnable(GL_CULL_FACE); | ||||
|   FrameBuffer offscreen_buffer = create_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT); | ||||
|  | ||||
|   std::vector<Vertex> vertices = { | ||||
|     // positions                           // normals                      // texture coords | ||||
| @@ -215,8 +224,23 @@ int main() { | ||||
|   Model backpack = {"models/suzanne/suzanne.obj"}; | ||||
|   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 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; | ||||
|   glm::vec3 camera_position  = glm::vec3(-2.0f, 0.0f, 6.0f); | ||||
| @@ -356,6 +380,10 @@ int main() { | ||||
|             SDL_GL_GetDrawableSize(wnd, &w, &h); | ||||
|             glViewport(0, 0, w, h); | ||||
|             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; | ||||
|       } | ||||
| @@ -375,8 +403,13 @@ int main() { | ||||
|     main_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); | ||||
|     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)); | ||||
|     normal_mat = glm::transpose(glm::inverse(model)); | ||||
| @@ -395,6 +428,23 @@ int main() { | ||||
|       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); | ||||
|   } | ||||
|  | ||||
| @@ -726,3 +776,43 @@ std::vector<Texture2D> Model::load_material_textures(aiMaterial *material, aiTex | ||||
|  | ||||
|   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); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user