Added render to texture support

dev
Shariq Shah 10 years ago
parent 3f4e84d6d3
commit 568d03f155
  1. 35
      src/array.c
  2. 3
      src/array.h
  3. 18
      src/framebuffer.c
  4. 4
      src/game.c
  5. 79
      src/geometry.c
  6. 6
      src/geometry.h
  7. 2
      src/model.c
  8. 103
      src/renderer.c
  9. 12
      src/texture.c
  10. 2
      src/texture.h
  11. 5
      src/window_system.c
  12. 1
      src/window_system.h

@ -17,7 +17,6 @@ struct Array
static struct Array* array_get_ptr(void* array_data); static struct Array* array_get_ptr(void* array_data);
static struct Array* array_reallocate(struct Array* array); static struct Array* array_reallocate(struct Array* array);
static void* array_top(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) 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) 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)); struct Array* new_array = malloc(sizeof(*new_array) + (object_size * capacity));
new_array->object_size = object_size; new_array->object_size = object_size;
new_array->length = 0; new_array->length = 0;
@ -41,11 +40,6 @@ void array_free(void* array)
free(array_ptr); 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) void* array_top(struct Array* array)
{ {
return array->data + (array->object_size * (array->length - 1)); 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; size_t object_size = array_ptr->object_size;
int new_capacity = length < ARRAY_MIN_CAPACITY ? ARRAY_MIN_CAPACITY : length; int new_capacity = length < ARRAY_MIN_CAPACITY ? ARRAY_MIN_CAPACITY : length;
int new_length = new_capacity; int new_length = new_capacity;
array_free(*array);
array_ptr = calloc(1, sizeof(*array_ptr) + (new_capacity * object_size)); array_ptr = calloc(1, sizeof(*array_ptr) + (new_capacity * object_size));
if(array_ptr) if(array_ptr)
{ {
@ -187,7 +182,8 @@ void array_inc_cap_by_(void** array, int cap)
if(cap > 0) if(cap > 0)
{ {
array_ptr->capacity += cap; 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) if(new_data)
{ {
array_ptr = (struct Array*)new_data; array_ptr = (struct Array*)new_data;
@ -195,8 +191,29 @@ void array_inc_cap_by_(void** array, int cap)
} }
else else
{ {
array_ptr->capacity = array_ptr->capacity -= cap; array_ptr->capacity -= cap;
/* TODO: Error handling here! */ /* 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;
}

@ -11,6 +11,7 @@ int array_pop_(void** array); // Remove object with highest index
int array_remove_at_(void** array, int index); int array_remove_at_(void** array, int index);
void array_match_len_cap_(void** array); void array_match_len_cap_(void** array);
void array_inc_cap_by_(void** array, int cap); void array_inc_cap_by_(void** array, int cap);
int array_copy_(void* arr_src, void** arr_dest);
/* Public Api */ /* Public Api */
#define array_new(type) (type*) array_new_(sizeof(type), 0); // Use this for array creation #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_reset(array, length) array_reset_((void**)&array, length);
#define array_match_len_cap(array) array_match_len_cap_((void**)&array); #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_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_len(void* array);
int array_capacity(void* array); int array_capacity(void* array);
void array_free(void* array); void array_free(void* array);
/* TODO function to increase capacity of array by certain number similar to reserve in stl vector? */ /* TODO function to increase capacity of array by certain number similar to reserve in stl vector? */
#endif #endif

@ -144,15 +144,15 @@ void framebuffer_set_texture(int index, int texture, int attachment)
GL_TEXTURE_2D, GL_TEXTURE_2D,
texture_get_texture_handle(texture), texture_get_texture_handle(texture),
0); 0);
if(!renderer_check_glerror("framebuffer:set_texture:glFramebuffertexture")) /* if(!renderer_check_glerror("framebuffer:set_texture:glFramebuffertexture")) */
{ /* { */
int current_fbo_tex = fbo_list[index].texture; /* int current_fbo_tex = fbo_list[index].texture; */
if(current_fbo_tex > -1) /* if(current_fbo_tex > -1) */
texture_remove(current_fbo_tex); /* texture_remove(current_fbo_tex); */
fbo_list[index].texture = texture; /* fbo_list[index].texture = texture; */
texture_inc_refcount(texture); /* texture_inc_refcount(texture); */
} /* } */
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
} }

@ -37,14 +37,14 @@ void game_init(void)
GLFWwindow* window = window_get_active(); GLFWwindow* window = window_get_active();
/* Init systems */ /* Init systems */
input_init(window); input_init(window);
renderer_init(window);
io_file_init("/mnt/Dev/Projects/Symmetry/assets/");/* TODO: Implement proper way of getting binary directory */ io_file_init("/mnt/Dev/Projects/Symmetry/assets/");/* TODO: Implement proper way of getting binary directory */
shader_init(); shader_init();
texture_init(); texture_init();
framebuffer_init(); framebuffer_init();
geom_init();
renderer_init(window);
transform_init(); transform_init();
camera_init(); camera_init();
geom_init();
material_init(); material_init();
model_init(); model_init();
entity_init(); entity_init();

@ -1,7 +1,5 @@
#include "geometry.h" #include "geometry.h"
#include "array.h" #include "array.h"
#include "num_types.h"
#include "linmath.h"
#include "string_utils.h" #include "string_utils.h"
#include "file_io.h" #include "file_io.h"
#include "log.h" #include "log.h"
@ -40,9 +38,9 @@ struct Geometry
static struct Geometry* geometry_list; static struct Geometry* geometry_list;
static int* empty_indices; static int* empty_indices;
/* Function definitions */ static int load_from_file(struct Geometry* geometry, const char* filename);
int load_from_file(struct Geometry* geometry, const char* filename); static void create_vao(struct Geometry* geometry);
void create_vao(struct Geometry* geometry); static struct Geometry* generate_new_index(int* out_new_index);
void geom_init(void) void geom_init(void)
{ {
@ -65,26 +63,35 @@ int geom_find(const char* filename)
return index; return index;
} }
int geom_create(const char* name) static struct Geometry* generate_new_index(int* out_new_index)
{ {
// check if exists assert(out_new_index);
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); int empty_len = array_len(empty_indices);
struct Geometry* new_geo = NULL;
if(empty_len > 0) if(empty_len > 0)
{ {
index = empty_indices[empty_len - 1]; *out_new_index = empty_indices[empty_len - 1];
array_pop(empty_indices); array_pop(empty_indices);
new_geo = &geometry_list[index]; new_geo = &geometry_list[*out_new_index];
} }
else else
{ {
new_geo = array_grow(geometry_list, struct Geometry); new_geo = array_grow(geometry_list, struct Geometry);
index = array_len(geometry_list) - 1; *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;
new_geo = generate_new_index(&index);
assert(new_geo); assert(new_geo);
if(load_from_file(new_geo, name)) if(load_from_file(new_geo, name))
@ -106,6 +113,38 @@ int geom_create(const char* name)
return index; 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) void geom_remove(int index)
{ {
if(index >= 0 && index < array_len(geometry_list)) 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->normals) array_free(geometry->normals);
if(geometry->vertex_colors) array_free(geometry->vertex_colors); if(geometry->vertex_colors) array_free(geometry->vertex_colors);
if(geometry->filename) free(geometry->filename); 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); array_push(empty_indices, index, int);
} }
} }
@ -137,7 +182,7 @@ void geom_cleanup(void)
array_free(empty_indices); 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); assert(filename);
int success = 1; int success = 1;
@ -195,7 +240,7 @@ int load_from_file(struct Geometry* geometry, const char* filename)
return success; 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); assert(geometry);

@ -1,8 +1,12 @@
#ifndef geometry_H #ifndef geometry_H
#define geometry_H #define geometry_H
#include "num_types.h"
#include "linmath.h"
void geom_init(void); 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); int geom_find(const char* filename);
void geom_remove(int index); void geom_remove(int index);
void geom_cleanup(void); void geom_cleanup(void);

@ -38,7 +38,7 @@ void model_init(void)
int model_create(int node, const char* geo_name) int model_create(int node, const char* geo_name)
{ {
assert(geo_name); assert(geo_name);
int geo_index = geom_create(geo_name); int geo_index = geom_create_from_file(geo_name);
int index = -1; int index = -1;
struct Model* new_model = NULL; struct Model* new_model = NULL;
if(geo_index > -1) if(geo_index > -1)

@ -4,8 +4,19 @@
#include "log.h" #include "log.h"
#include "camera.h" #include "camera.h"
#include "model.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); 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_DEPTH_TEST);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glfwSetFramebufferSizeCallback(window, on_framebuffer_size_change); 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) 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); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Hard coded version */
struct Camera* camera = camera_get(0); struct Camera* camera = camera_get(0);
model_render_all(camera); model_render_all(camera);
glDisable(GL_BLEND);
}
framebuffer_unbind();
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);
geom_render(quad_geo);
texture_unbind(def_render_tex);
shader_unbind();
} }
void renderer_cleanup(void) 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) void on_framebuffer_size_change(GLFWwindow* window, int width, int height)

@ -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); index = texture_create(filename, texture_unit, width, height, fmt, int_fmt, GL_UNSIGNED_BYTE, img_data);
if(index > -1) if(index > -1)
{ {
texture_param_set(index, GL_TEXTURE_MIN_FILTER, GL_LINEAR); texture_set_param(index, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_param_set(index, GL_TEXTURE_MAG_FILTER, GL_LINEAR); texture_set_param(index, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture_param_set(index,GL_TEXTURE_WRAP_S,GL_REPEAT); texture_set_param(index,GL_TEXTURE_WRAP_S,GL_REPEAT);
texture_param_set(index,GL_TEXTURE_WRAP_T,GL_REPEAT); texture_set_param(index,GL_TEXTURE_WRAP_T,GL_REPEAT);
} }
else else
{ {
@ -291,7 +291,7 @@ int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt
return success; 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; struct Texture* texture = NULL;
if(index > -1 && index < array_len(texture_list)) 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); glGetIntegerv(GL_TEXTURE_2D, &curr_texture);
glBindTexture(GL_TEXTURE_2D, texture->handle); glBindTexture(GL_TEXTURE_2D, texture->handle);
glTexParameteri(GL_TEXTURE_2D, parameter, value); glTexParameteri(GL_TEXTURE_2D, parameter, value);
renderer_check_glerror("texture:param_set"); renderer_check_glerror("texture:set_param");
if(curr_texture != 0) if(curr_texture != 0)
glBindTexture(GL_TEXTURE_2D, curr_texture); glBindTexture(GL_TEXTURE_2D, curr_texture);
} }

@ -17,7 +17,7 @@ int texture_find(const char* name);
void texture_cleanup(void); void texture_cleanup(void);
void texture_bind(int index); void texture_bind(int index);
void texture_unbind(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_textureunit(int index);
int texture_get_texture_handle(int index); int texture_get_texture_handle(int index);
void texture_inc_refcount(int index); void texture_inc_refcount(int index);

@ -101,3 +101,8 @@ void window_set_should_close(int should_close)
{ {
glfwSetWindowShouldClose(active_window, should_close ? GL_TRUE : GL_FALSE); glfwSetWindowShouldClose(active_window, should_close ? GL_TRUE : GL_FALSE);
} }
void window_get_size(int* width, int* height)
{
glfwGetWindowSize(active_window, width, height);
}

@ -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); int window_init(const char* title, int width, int height);
void window_cleanup(void); void window_cleanup(void);
void window_set_size(int width, int height); void window_set_size(int width, int height);
void window_get_size(int* width, int* height);
void window_poll_events(void); void window_poll_events(void);
void window_swap_buffers(void); void window_swap_buffers(void);
int window_should_close(void); int window_should_close(void);

Loading…
Cancel
Save