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; | ||||||
|  | } | ||||||
							
								
								
									
										98
									
								
								src/main.cc
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								src/main.cc
									
									
									
									
									
								
							| @@ -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, {}}; | ||||||
|  |  | ||||||
|   Shader main_shader  {"shaders/vert.glsl", "shaders/frag.glsl"}; |   std::vector<Vertex> screen_vertices = { | ||||||
|   Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"}; |     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; |   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); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user