From 568d03f1552a746bcbeac7af2dd88cd19476540f Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Fri, 30 Oct 2015 12:35:57 +0500 Subject: [PATCH] Added render to texture support --- src/array.c | 35 +++++++++++---- src/array.h | 3 ++ src/framebuffer.c | 16 +++---- src/game.c | 4 +- src/geometry.c | 87 ++++++++++++++++++++++++++--------- src/geometry.h | 6 ++- src/model.c | 2 +- src/renderer.c | 107 +++++++++++++++++++++++++++++++++++++++++--- src/texture.c | 12 ++--- src/texture.h | 2 +- src/window_system.c | 5 +++ src/window_system.h | 1 + 12 files changed, 226 insertions(+), 54 deletions(-) diff --git a/src/array.c b/src/array.c index 4706602..6bc9a74 100644 --- a/src/array.c +++ b/src/array.c @@ -17,7 +17,6 @@ struct Array static struct Array* array_get_ptr(void* array_data); static struct Array* array_reallocate(struct Array* array); static void* array_top(struct Array* array); -static void* array_get(struct Array* array, unsigned int index); static struct Array* array_get_ptr(void* array_data) { @@ -26,7 +25,7 @@ static struct Array* array_get_ptr(void* array_data) void* array_new_(size_t object_size, int capacity) { - capacity = capacity == 0 ? ARRAY_MIN_CAPACITY : capacity; + if(capacity == 0) capacity = ARRAY_MIN_CAPACITY; struct Array* new_array = malloc(sizeof(*new_array) + (object_size * capacity)); new_array->object_size = object_size; new_array->length = 0; @@ -41,11 +40,6 @@ void array_free(void* array) free(array_ptr); } -void* array_get(struct Array* array, unsigned int index) -{ - return array->data + (array->object_size * index); -} - void* array_top(struct Array* array) { return array->data + (array->object_size * (array->length - 1)); @@ -81,6 +75,7 @@ int array_reset_(void** array, int length) size_t object_size = array_ptr->object_size; int new_capacity = length < ARRAY_MIN_CAPACITY ? ARRAY_MIN_CAPACITY : length; int new_length = new_capacity; + array_free(*array); array_ptr = calloc(1, sizeof(*array_ptr) + (new_capacity * object_size)); if(array_ptr) { @@ -187,7 +182,8 @@ void array_inc_cap_by_(void** array, int cap) if(cap > 0) { array_ptr->capacity += cap; - char* new_data = realloc(array_ptr, sizeof(*array_ptr) + (array_ptr->object_size * array_ptr->capacity)); + char* new_data = realloc(array_ptr, + sizeof(*array_ptr) + (array_ptr->object_size * array_ptr->capacity)); if(new_data) { array_ptr = (struct Array*)new_data; @@ -195,8 +191,29 @@ void array_inc_cap_by_(void** array, int cap) } else { - array_ptr->capacity = array_ptr->capacity -= cap; + array_ptr->capacity -= cap; /* TODO: Error handling here! */ } } } + +int array_copy_(void* array_src, void** array_dest) +{ + int success = 0; + struct Array* src = array_get_ptr(array_src); + struct Array* dest = array_get_ptr(*array_dest); + + /* determine if copy is possible */ + if(src->object_size != dest->object_size) + return success; + + if((src->length > dest->length) && (dest->capacity < src->length)) + { + array_free(*array_dest); + *array_dest = array_new_(src->object_size, src->capacity); + dest = *array_dest; + } + memcpy(dest->data, src->data, src->object_size * src->length); + dest->length = src->length; + return success; +} diff --git a/src/array.h b/src/array.h index 6263a60..10011c0 100644 --- a/src/array.h +++ b/src/array.h @@ -11,6 +11,7 @@ int array_pop_(void** array); // Remove object with highest index int array_remove_at_(void** array, int index); void array_match_len_cap_(void** array); void array_inc_cap_by_(void** array, int cap); +int array_copy_(void* arr_src, void** arr_dest); /* Public Api */ #define array_new(type) (type*) array_new_(sizeof(type), 0); // Use this for array creation @@ -27,9 +28,11 @@ void array_inc_cap_by_(void** array, int cap); #define array_reset(array, length) array_reset_((void**)&array, length); #define array_match_len_cap(array) array_match_len_cap_((void**)&array); #define array_inc_cap_by(array, cap) array_inc_cap_by_((void**)&array, cap); +#define array_copy(src, dest) array_copy_(src, (void**)&dest); int array_len(void* array); int array_capacity(void* array); void array_free(void* array); + /* TODO function to increase capacity of array by certain number similar to reserve in stl vector? */ #endif diff --git a/src/framebuffer.c b/src/framebuffer.c index 1babd74..504c1c1 100644 --- a/src/framebuffer.c +++ b/src/framebuffer.c @@ -144,15 +144,15 @@ void framebuffer_set_texture(int index, int texture, int attachment) GL_TEXTURE_2D, texture_get_texture_handle(texture), 0); - if(!renderer_check_glerror("framebuffer:set_texture:glFramebuffertexture")) - { - int current_fbo_tex = fbo_list[index].texture; - if(current_fbo_tex > -1) - texture_remove(current_fbo_tex); + /* if(!renderer_check_glerror("framebuffer:set_texture:glFramebuffertexture")) */ + /* { */ + /* int current_fbo_tex = fbo_list[index].texture; */ + /* if(current_fbo_tex > -1) */ + /* texture_remove(current_fbo_tex); */ - fbo_list[index].texture = texture; - texture_inc_refcount(texture); - } + /* fbo_list[index].texture = texture; */ + /* texture_inc_refcount(texture); */ + /* } */ glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); } diff --git a/src/game.c b/src/game.c index 1bc0e91..6cab2a5 100644 --- a/src/game.c +++ b/src/game.c @@ -37,14 +37,14 @@ void game_init(void) GLFWwindow* window = window_get_active(); /* Init systems */ input_init(window); - renderer_init(window); io_file_init("/mnt/Dev/Projects/Symmetry/assets/");/* TODO: Implement proper way of getting binary directory */ shader_init(); texture_init(); framebuffer_init(); + geom_init(); + renderer_init(window); transform_init(); camera_init(); - geom_init(); material_init(); model_init(); entity_init(); diff --git a/src/geometry.c b/src/geometry.c index 8b3b505..ee52b4d 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -1,7 +1,5 @@ #include "geometry.h" #include "array.h" -#include "num_types.h" -#include "linmath.h" #include "string_utils.h" #include "file_io.h" #include "log.h" @@ -40,9 +38,9 @@ struct Geometry static struct Geometry* geometry_list; static int* empty_indices; -/* Function definitions */ -int load_from_file(struct Geometry* geometry, const char* filename); -void create_vao(struct Geometry* geometry); +static int load_from_file(struct Geometry* geometry, const char* filename); +static void create_vao(struct Geometry* geometry); +static struct Geometry* generate_new_index(int* out_new_index); void geom_init(void) { @@ -65,26 +63,35 @@ int geom_find(const char* filename) return index; } -int geom_create(const char* name) +static struct Geometry* generate_new_index(int* out_new_index) { + assert(out_new_index); + int empty_len = array_len(empty_indices); + struct Geometry* new_geo = NULL; + if(empty_len > 0) + { + *out_new_index = empty_indices[empty_len - 1]; + array_pop(empty_indices); + new_geo = &geometry_list[*out_new_index]; + } + else + { + new_geo = array_grow(geometry_list, struct Geometry); + *out_new_index = array_len(geometry_list) - 1; + } + return new_geo; +} + +int geom_create_from_file(const char* name) +{ + assert(name); // check if exists int index = geom_find(name); if(index == -1) { /* add new geometry object or overwrite existing one */ struct Geometry* new_geo = NULL; - int empty_len = array_len(empty_indices); - if(empty_len > 0) - { - index = empty_indices[empty_len - 1]; - array_pop(empty_indices); - new_geo = &geometry_list[index]; - } - else - { - new_geo = array_grow(geometry_list, struct Geometry); - index = array_len(geometry_list) - 1; - } + new_geo = generate_new_index(&index); assert(new_geo); if(load_from_file(new_geo, name)) @@ -106,6 +113,38 @@ int geom_create(const char* name) return index; } +int geom_create(const char* name, vec3* vertices, vec2* uvs, vec3* normals, uint* indices, vec3* vertex_colors) +{ + assert(name && vertices && uvs && normals && indices); + int index = -1; + /* add new geometry object or overwrite existing one */ + struct Geometry* new_geo = NULL; + new_geo = generate_new_index(&index); + assert(new_geo); + new_geo->filename = str_new(name); + new_geo->vertices = array_new_cap(vec3, array_len(vertices)); + array_copy(vertices, new_geo->vertices); + new_geo->normals = array_new_cap(vec3, array_len(normals)); + array_copy(normals, new_geo->normals); + new_geo->uvs = array_new_cap(vec2, array_len(uvs)); + array_copy(uvs, new_geo->uvs); + new_geo->indices = array_new_cap(uint, array_len(indices)); + array_copy(indices, new_geo->indices); + if(vertex_colors) + { + new_geo->vertex_colors = array_new_cap(vec3, array_len(vertex_colors)); + array_copy(vertex_colors, new_geo->vertex_colors); + } + else + { + new_geo->vertex_colors = array_new(vec3); + } + create_vao(new_geo); + //generateBoundingBox(index); + return index; +} + + void geom_remove(int index) { if(index >= 0 && index < array_len(geometry_list)) @@ -122,6 +161,12 @@ void geom_remove(int index) if(geometry->normals) array_free(geometry->normals); if(geometry->vertex_colors) array_free(geometry->vertex_colors); if(geometry->filename) free(geometry->filename); + geometry->indices = NULL; + geometry->vertices = NULL; + geometry->uvs = NULL; + geometry->normals = NULL; + geometry->vertex_colors = NULL; + geometry->filename = NULL; array_push(empty_indices, index, int); } } @@ -137,7 +182,7 @@ void geom_cleanup(void) array_free(empty_indices); } -int load_from_file(struct Geometry* geometry, const char* filename) +static int load_from_file(struct Geometry* geometry, const char* filename) { assert(filename); int success = 1; @@ -195,9 +240,9 @@ int load_from_file(struct Geometry* geometry, const char* filename) return success; } -void create_vao(struct Geometry* geometry) +static void create_vao(struct Geometry* geometry) { - // TODO : Add support for different model formats and interleaving VBO + // TODO: Add support for different model formats and interleaving VBO assert(geometry); glGenVertexArrays(1, &geometry->vao); glBindVertexArray(geometry->vao); diff --git a/src/geometry.h b/src/geometry.h index 4256c1b..204c62d 100644 --- a/src/geometry.h +++ b/src/geometry.h @@ -1,8 +1,12 @@ #ifndef geometry_H #define geometry_H +#include "num_types.h" +#include "linmath.h" + void geom_init(void); -int geom_create(const char* name); +int geom_create_from_file(const char* name); +int geom_create(const char* name, vec3* vertices, vec2* uvs, vec3* normals, uint* indices, vec3* vertex_colors); int geom_find(const char* filename); void geom_remove(int index); void geom_cleanup(void); diff --git a/src/model.c b/src/model.c index 32fef96..78c2045 100644 --- a/src/model.c +++ b/src/model.c @@ -38,7 +38,7 @@ void model_init(void) int model_create(int node, const char* geo_name) { assert(geo_name); - int geo_index = geom_create(geo_name); + int geo_index = geom_create_from_file(geo_name); int index = -1; struct Model* new_model = NULL; if(geo_index > -1) diff --git a/src/renderer.c b/src/renderer.c index 292325d..6dd40c3 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -4,8 +4,19 @@ #include "log.h" #include "camera.h" #include "model.h" +#include "texture.h" +#include "framebuffer.h" +#include "array.h" +#include "geometry.h" +#include "shader.h" +#include "num_types.h" +#include "window_system.h" -static int default_fbo = -1; +static int def_fbo = -1; +static int def_render_tex = -1; +static int def_depth_tex = -1; +static int quad_geo = -1; +static int fbo_shader = -1; void on_framebuffer_size_change(GLFWwindow* window, int width, int height); @@ -15,19 +26,105 @@ void renderer_init(GLFWwindow* window) glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glfwSetFramebufferSizeCallback(window, on_framebuffer_size_change); + + /* Quad geometry for final render */ + vec3* vertices = array_new(vec3); + vec2* uvs = array_new(vec2); + vec3* normals = array_new(vec3); + uint* indices = array_new(uint); + vec3 temp_v3; + vec2 temp_v2; + /* Vertices */ + temp_v3.x = -1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); + temp_v3.x = 1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); + temp_v3.x = 1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); + temp_v3.x = -1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); + /* Normals */ + temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3); + temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3); + /* Uvs */ + temp_v2.x = 0; temp_v2.y = 0; array_push(uvs, temp_v2, vec2); + temp_v2.x = 1; temp_v2.y = 0; array_push(uvs, temp_v2, vec2); + temp_v2.x = 1; temp_v2.y = 1; array_push(uvs, temp_v2, vec2); + temp_v2.x = 0; temp_v2.y = 1; array_push(uvs, temp_v2, vec2); + /* Indices */ + array_push(indices, 0, uint); array_push(indices, 1, uint); array_push(indices, 2, uint); + array_push(indices, 2, uint); array_push(indices, 3, uint); array_push(indices, 0, uint); + + quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL); + array_free(vertices); + array_free(uvs); + array_free(normals); + array_free(indices); + +/* Textues for default fbo */ + int width = -1, height = -1; + window_get_size(&width, &height); + def_render_tex = texture_create("def_render_texture", + TU_DIFFUSE, + width, height, + GL_RGBA, + GL_RGBA8, + GL_UNSIGNED_BYTE, + NULL); + texture_set_param(def_render_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + texture_set_param(def_render_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_set_param(def_render_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture_set_param(def_render_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + def_depth_tex = texture_create("def_depth_texture", + TU_SHADOWMAP1, + width, height, + GL_DEPTH_COMPONENT, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_BYTE, + NULL); + texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_set_param(def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture_set_param(def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + + def_fbo = framebuffer_create(width, height, 0, 1); + framebuffer_set_texture(def_fbo, def_render_tex, GL_COLOR_ATTACHMENT0); + framebuffer_set_texture(def_fbo, def_depth_tex, GL_DEPTH_ATTACHMENT); + + fbo_shader = shader_create("fbo.vert", "fbo.frag"); } void renderer_draw(void) { + framebuffer_bind(def_fbo); + { + 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); + } + framebuffer_unbind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - /* Hard coded version */ - struct Camera* camera = camera_get(0); - model_render_all(camera); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + shader_bind(fbo_shader); + texture_bind(def_render_tex); + geom_render(quad_geo); + texture_unbind(def_render_tex); + shader_unbind(); } void renderer_cleanup(void) { - + shader_remove(fbo_shader); + geom_remove(quad_geo); + framebuffer_remove(def_fbo); + texture_remove(def_render_tex); + texture_remove(def_depth_tex); } void on_framebuffer_size_change(GLFWwindow* window, int width, int height) diff --git a/src/texture.c b/src/texture.c index c5f5e6d..e625a33 100644 --- a/src/texture.c +++ b/src/texture.c @@ -81,10 +81,10 @@ int texture_create_from_file(const char* filename, int texture_unit) index = texture_create(filename, texture_unit, width, height, fmt, int_fmt, GL_UNSIGNED_BYTE, img_data); if(index > -1) { - texture_param_set(index, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - texture_param_set(index, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - texture_param_set(index,GL_TEXTURE_WRAP_S,GL_REPEAT); - texture_param_set(index,GL_TEXTURE_WRAP_T,GL_REPEAT); + texture_set_param(index, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture_set_param(index, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + texture_set_param(index,GL_TEXTURE_WRAP_S,GL_REPEAT); + texture_set_param(index,GL_TEXTURE_WRAP_T,GL_REPEAT); } else { @@ -291,7 +291,7 @@ int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt return success; } -void texture_param_set(int index, int parameter, int value) +void texture_set_param(int index, int parameter, int value) { struct Texture* texture = NULL; if(index > -1 && index < array_len(texture_list)) @@ -303,7 +303,7 @@ void texture_param_set(int index, int parameter, int value) glGetIntegerv(GL_TEXTURE_2D, &curr_texture); glBindTexture(GL_TEXTURE_2D, texture->handle); glTexParameteri(GL_TEXTURE_2D, parameter, value); - renderer_check_glerror("texture:param_set"); + renderer_check_glerror("texture:set_param"); if(curr_texture != 0) glBindTexture(GL_TEXTURE_2D, curr_texture); } diff --git a/src/texture.h b/src/texture.h index 2f237d3..8172b77 100644 --- a/src/texture.h +++ b/src/texture.h @@ -17,7 +17,7 @@ int texture_find(const char* name); void texture_cleanup(void); void texture_bind(int index); void texture_unbind(int index); -void texture_param_set(int index, int parameter, int value); +void texture_set_param(int index, int parameter, int value); int texture_get_textureunit(int index); int texture_get_texture_handle(int index); void texture_inc_refcount(int index); diff --git a/src/window_system.c b/src/window_system.c index a1076d5..7f10c56 100644 --- a/src/window_system.c +++ b/src/window_system.c @@ -101,3 +101,8 @@ void window_set_should_close(int should_close) { glfwSetWindowShouldClose(active_window, should_close ? GL_TRUE : GL_FALSE); } + +void window_get_size(int* width, int* height) +{ + glfwGetWindowSize(active_window, width, height); +} diff --git a/src/window_system.h b/src/window_system.h index 83989af..79b43d5 100644 --- a/src/window_system.h +++ b/src/window_system.h @@ -12,6 +12,7 @@ typedef void (*on_mouse_pos) (double, double); // Callback for mouse position int window_init(const char* title, int width, int height); void window_cleanup(void); void window_set_size(int width, int height); +void window_get_size(int* width, int* height); void window_poll_events(void); void window_swap_buffers(void); int window_should_close(void);