From ed1edf44ceeeab82d0b172680ac9872cb1c23d4c Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Wed, 23 Dec 2015 18:47:00 +0500 Subject: [PATCH] Implemented resolution independent rendering and RTT --- src/camera.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++- src/camera.h | 8 +++- src/game.c | 7 +++- src/renderer.c | 35 +++++++++++------ 4 files changed, 136 insertions(+), 14 deletions(-) diff --git a/src/camera.c b/src/camera.c index ced6fe1..21cecd7 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,13 +1,21 @@ +#include "GLFW/glfw3.h" #include "camera.h" #include "entity.h" #include "transform.h" #include "array.h" +#include "framebuffer.h" +#include "texture.h" #include "utils.h" #include "log.h" +#include +#include +#include + static struct Camera* camera_list; static int* empty_indices; +static int primary_camera_index; struct Camera* camera_get(int index) { @@ -22,6 +30,7 @@ void camera_init(void) { camera_list = array_new(struct Camera); empty_indices = array_new(int); + primary_camera_index = -1; } void camera_remove(int index) @@ -54,7 +63,9 @@ int camera_create(int node, int width, int height) new_camera = array_grow(camera_list, struct Camera); index = array_len(camera_list) - 1; } - + new_camera->fbo = -1; + new_camera->render_tex = -1; + new_camera->depth_tex = -1; new_camera->node = node; new_camera->farz = 1000.f; new_camera->nearz = 0.1f; @@ -106,3 +117,90 @@ void camera_update_proj(struct Camera* camera) } camera_update_view_proj(camera); } + +void camera_attach_fbo(struct Camera* camera, int width, int height, int has_depth, int has_color) +{ + assert(width > 0 && height > 0 && camera); + if(camera->fbo != -1) + { + log_error("camera:attach_fbo", "Camera already has fbo attached!"); + return; + } + camera->fbo = framebuffer_create(width, height, has_depth, has_color); + if(camera->fbo > -1) + { + char tex_name[128]; + snprintf(tex_name, 128, "cam_render_tex_%d", camera->node); + camera->render_tex = texture_create(tex_name, + TU_DIFFUSE, + width, height, + GL_RGBA, + GL_RGBA8, + GL_UNSIGNED_BYTE, + NULL); + texture_set_param(camera->render_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + texture_set_param(camera->render_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_set_param(camera->render_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture_set_param(camera->render_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + memset(tex_name, '\0', 128); + snprintf(tex_name, 128, "cam_depth_tex_%d", camera->node); + camera->depth_tex = texture_create(tex_name, + TU_SHADOWMAP1, + width, height, + GL_DEPTH_COMPONENT, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_BYTE, + NULL); + texture_set_param(camera->depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + texture_set_param(camera->depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_set_param(camera->depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture_set_param(camera->depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + texture_set_param(camera->depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + texture_set_param(camera->depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + + camera->fbo = framebuffer_create(width, height, 0, 1); + framebuffer_set_texture(camera->fbo, camera->render_tex, GL_COLOR_ATTACHMENT0); + framebuffer_set_texture(camera->fbo, camera->depth_tex, GL_DEPTH_ATTACHMENT); + } + else + { + log_error("camera:attach_fbo", "Framebuffer not attached to camera!"); + } +} + +struct Camera* camera_get_all(void) +{ + return camera_list; +} + +void camera_set_primary_viewer(struct Camera* camera) +{ + assert(camera); + if(camera->node == -1) + { + log_error("camera:set_primary_viewer", "Invalid camera!"); + } + else + { + /* locate the index of this camera */ + for(int i = 0; i < array_len(camera_list); i++) + { + if(camera_list[i].node == camera->node) + { + primary_camera_index = i; + log_message("Camera at index %d set as primary viewer", primary_camera_index); + break; + } + + } + } +} + +struct Camera* camera_get_primary(void) +{ + struct Camera* primary_camera = NULL; + if(primary_camera_index != -1) + primary_camera = &camera_list[primary_camera_index]; + return primary_camera; +} diff --git a/src/camera.h b/src/camera.h index 72d56a5..4920d4a 100644 --- a/src/camera.h +++ b/src/camera.h @@ -14,9 +14,14 @@ struct Camera float nearz; float farz; int ortho; + int fbo; + int render_tex; + int depth_tex; }; struct Camera* camera_get(int index); +struct Camera* camera_get_all(void); +struct Camera* camera_get_primary(void); void camera_init(void); void camera_cleanup(void); void camera_remove(int index); @@ -24,6 +29,7 @@ int camera_create(int node, int width, int height); void camera_update_view_proj(struct Camera* camera); void camera_update_view(struct Camera* camera); void camera_update_proj(struct Camera* camera); - +void camera_attach_fbo(struct Camera* camera, int width, int height, int has_depth, int has_color); +void camera_set_primary_viewer(struct Camera* camera); #endif diff --git a/src/game.c b/src/game.c index 6cab2a5..c7f6509 100644 --- a/src/game.c +++ b/src/game.c @@ -84,7 +84,12 @@ void scene_setup(void) vec3 viewer_pos = {0, 0, 10}; struct Transform* viewer_tran = entity_component_get(player, C_TRANSFORM); transform_set_position(viewer_tran, &viewer_pos); - entity_component_add(player, C_CAMERA, 800, 600); + int render_width, render_height; + render_width = 800; + render_height = 600; + struct Camera* camera = entity_component_add(player, C_CAMERA, render_width, render_height); + camera_attach_fbo(camera, render_width, render_height, 1, 1); + camera_set_primary_viewer(camera); struct Entity* new_ent = scene_add_new("Model_Entity", NULL); struct Transform* tran = entity_component_get(new_ent, C_TRANSFORM); diff --git a/src/renderer.c b/src/renderer.c index f487095..43efce0 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -95,24 +95,37 @@ void renderer_init(GLFWwindow* window) void renderer_draw(void) { - framebuffer_bind(def_fbo); + struct Camera* camera_list = camera_get_all(); + for(int i = 0; i < array_len(camera_list); i++) { - glDrawBuffer(GL_COLOR_ATTACHMENT0); - glDepthFunc(GL_LEQUAL); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - struct Camera* camera = camera_get(0); - model_render_all(camera); - glDisable(GL_BLEND); + struct Camera* camera = &camera_list[i]; + if(camera->node < 0) + continue; + + int fbo = camera->fbo == -1 ? def_fbo : camera->fbo; + framebuffer_bind(fbo); + { + glViewport(0, 0, framebuffer_get_width(fbo), framebuffer_get_height(fbo)); + glDrawBuffer(GL_COLOR_ATTACHMENT0); + glDepthFunc(GL_LEQUAL); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + model_render_all(camera); + glDisable(GL_BLEND); + } + framebuffer_unbind(); } - framebuffer_unbind(); + int width, height; + window_get_size(&width, &height); + glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); shader_bind(fbo_shader); - texture_bind(def_render_tex); + struct Camera* primary_camera = camera_get_primary(); + texture_bind(primary_camera->render_tex); geom_render(quad_geo); texture_unbind(def_render_tex); shader_unbind();