Added fbos and changed texture creation

dev
Shariq Shah 10 years ago
parent d2ee943995
commit 3f4e84d6d3
  1. 1
      orgfile.org
  2. 163
      src/framebuffer.c
  3. 15
      src/framebuffer.h
  4. 4
      src/game.c
  5. 17
      src/renderer.c
  6. 2
      src/renderer.h
  7. 111
      src/texture.c
  8. 11
      src/texture.h

@ -36,6 +36,7 @@ while using as few libraries as possible.
- State "DONE" from "TODO" [2015-08-02 Sun 19:09] - State "DONE" from "TODO" [2015-08-02 Sun 19:09]
** TODO Fix readme markdown ** TODO Fix readme markdown
** TODO Framebuffer and resolution independent rendering ** TODO Framebuffer and resolution independent rendering
** TODO Remove Kazmath dependency
** DONE Entity ** DONE Entity
- State "DONE" from "TODO" [2015-09-15 Tue 12:17] - State "DONE" from "TODO" [2015-09-15 Tue 12:17]
** TODO Positive and negative values for input_maps and returning corresponding values when they are true ** TODO Positive and negative values for input_maps and returning corresponding values when they are true

@ -0,0 +1,163 @@
#include "framebuffer.h"
#include "array.h"
#include "num_types.h"
#include "renderer.h"
#include "log.h"
#include "texture.h"
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <assert.h>
struct FBO
{
uint handle;
uint renderbuffer;
int texture;
int width;
int height;
};
struct FBO* fbo_list;
int* empty_indices;
void framebuffer_init(void)
{
fbo_list = array_new(struct FBO);
empty_indices = array_new(int);
}
void framebuffer_cleanup(void)
{
for(int i = 0; i < array_len(fbo_list); i++)
framebuffer_remove(i);
array_free(fbo_list);
array_free(empty_indices);
}
int framebuffer_create(int width, int height, int has_depth, int has_color)
{
int index = -1;
GLuint fbo;
GLuint renderbuffer;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER,
GL_DEPTH24_STENCIL8,
width,
height);
renderer_check_glerror("framebuffer:create");
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER,
renderbuffer);
renderer_check_glerror("framebuffer:create");
if(has_color)
{
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
if(has_depth)
{
glDrawBuffer(GL_NONE);
}
renderer_check_glerror("framebuffer:create");
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
log_error("framebuffer:create", "Framebuffer not created!");
renderer_check_glerror("framebuffer:create");
}
else
{
struct FBO* framebuffer = NULL;
if(array_len(empty_indices) == 0)
{
framebuffer = array_grow(fbo_list, struct FBO);
index = array_len(fbo_list) - 1;
}
else
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
}
framebuffer->handle = fbo;
framebuffer->renderbuffer = renderbuffer;
framebuffer->texture = -1;
framebuffer->width = width;
framebuffer->height = height;
log_message("Framebuffer created successfully");
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
return index;
}
void framebuffer_bind(int index)
{
assert(index < array_len(fbo_list) && index > -1);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_list[index].handle);
}
void framebuffer_remove(int index)
{
assert(index < array_len(fbo_list) && index > -1);
struct FBO* fbo = &fbo_list[index];
if(fbo->texture != -1) texture_remove(fbo->texture);
glDeleteRenderbuffers(1, &fbo->renderbuffer);
glDeleteFramebuffers(1, &fbo->handle);
}
void framebuffer_unbind(void)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
int framebuffer_get_width(int index)
{
assert(index < array_len(fbo_list) && index > -1);
return fbo_list[index].width;
}
int framebuffer_get_height(int index)
{
assert(index < array_len(fbo_list) && index > -1);
return fbo_list[index].height;
}
void framebuffer_set_texture(int index, int texture, int attachment)
{
assert(index < array_len(fbo_list) && index > -1);
GLint current_fbo = 0;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_fbo);
renderer_check_glerror("framebuffer:set_texture:glGet");
framebuffer_bind(index);
glFramebufferTexture2D(GL_FRAMEBUFFER,
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);
fbo_list[index].texture = texture;
texture_inc_refcount(texture);
}
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
}
int framebuffer_get_texture(int index)
{
assert(index < array_len(fbo_list) && index > -1);
return fbo_list[index].texture;
}

@ -0,0 +1,15 @@
#ifndef framebuffer_H
#define framebuffer_H
void framebuffer_init(void);
void framebuffer_cleanup(void);
int framebuffer_create(int width, int height, int has_depth, int has_color);
void framebuffer_bind(int index);
void framebuffer_remove(int index);
void framebuffer_unbind(void);
int framebuffer_get_width(int index);
int framebuffer_get_height(int index);
void framebuffer_set_texture(int index, int texture, int attachment);
int framebuffer_get_texture(int index);
#endif

@ -20,6 +20,7 @@
#include "utils.h" #include "utils.h"
#include "texture.h" #include "texture.h"
#include "material.h" #include "material.h"
#include "framebuffer.h"
void run(void); void run(void);
void update(float dt); void update(float dt);
@ -32,6 +33,7 @@ int player_pitch_node = -1;
void game_init(void) void game_init(void)
{ {
/* TODO: Implement dealing with init failures */
GLFWwindow* window = window_get_active(); GLFWwindow* window = window_get_active();
/* Init systems */ /* Init systems */
input_init(window); input_init(window);
@ -39,6 +41,7 @@ void game_init(void)
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();
transform_init(); transform_init();
camera_init(); camera_init();
geom_init(); geom_init();
@ -273,6 +276,7 @@ void game_cleanup(void)
input_cleanup(); input_cleanup();
renderer_cleanup(); renderer_cleanup();
io_file_cleanup(); io_file_cleanup();
framebuffer_cleanup();
texture_cleanup(); texture_cleanup();
shader_cleanup(); shader_cleanup();
} }

@ -5,6 +5,8 @@
#include "camera.h" #include "camera.h"
#include "model.h" #include "model.h"
static int default_fbo = -1;
void on_framebuffer_size_change(GLFWwindow* window, int width, int height); void on_framebuffer_size_change(GLFWwindow* window, int width, int height);
void renderer_init(GLFWwindow* window) void renderer_init(GLFWwindow* window)
@ -38,11 +40,12 @@ void renderer_set_clearcolor(float red, float green, float blue, float alpha)
glClearColor(red, green, blue, alpha); glClearColor(red, green, blue, alpha);
} }
void renderer_check_glerror(const char* context) int renderer_check_glerror(const char* context)
{ {
GLenum error = glGetError(); int error = 1;
GLenum error_code = glGetError();
const char* errorString = "No Error"; const char* errorString = "No Error";
switch(error) switch(error_code)
{ {
case GL_INVALID_OPERATION: case GL_INVALID_OPERATION:
errorString = "Invalid Operation"; errorString = "Invalid Operation";
@ -70,8 +73,10 @@ void renderer_check_glerror(const char* context)
break; break;
} }
if(error != GL_NO_ERROR) if(error_code != GL_NO_ERROR)
{
log_error(context, errorString); log_error(context, errorString);
} else
error = 0;
return error;
} }

@ -7,6 +7,6 @@ void renderer_init(GLFWwindow* window);
void renderer_draw(void); void renderer_draw(void);
void renderer_cleanup(void); void renderer_cleanup(void);
void renderer_set_clearcolor(float r, float g, float b, float a); void renderer_set_clearcolor(float r, float g, float b, float a);
void renderer_check_glerror(const char* context); int renderer_check_glerror(const char* context);
#endif #endif

@ -44,6 +44,7 @@ static int* empty_indices;
int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt, int* internal_fmt); int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt, int* internal_fmt);
void debug_write_tga(struct Tga_Header* header, GLubyte* image_data); void debug_write_tga(struct Tga_Header* header, GLubyte* image_data);
void copy_tga_pixel(GLubyte* source, GLubyte* dest, size_t bytes_per_pixel); void copy_tga_pixel(GLubyte* source, GLubyte* dest, size_t bytes_per_pixel);
int create_gl_texture(uint* out_handle, int width, int height, int format, int int_fmt, int type, void* data);
void texture_init(void) void texture_init(void)
{ {
@ -62,7 +63,6 @@ int texture_create_from_file(const char* filename, int texture_unit)
return index; return index;
} }
/* If texture not already loaded then try to load it */ /* If texture not already loaded then try to load it */
uint handle = 0;
char* full_path = str_new("textures/"); char* full_path = str_new("textures/");
full_path = str_concat(full_path, filename); full_path = str_concat(full_path, filename);
FILE* file = io_file_open(full_path, "rb"); FILE* file = io_file_open(full_path, "rb");
@ -71,42 +71,25 @@ int texture_create_from_file(const char* filename, int texture_unit)
if(file) if(file)
{ {
/* Load texture here */ /* Load texture here */
int width, height, internal_fmt, fmt; int width, height, int_fmt, fmt;
GLubyte* img_data = NULL; GLubyte* img_data = NULL;
width = height = internal_fmt = fmt = -1; width = height = int_fmt = fmt = -1;
img_load_success = load_img(file, &img_data, &width, &height, &fmt, &internal_fmt); img_load_success = load_img(file, &img_data, &width, &height, &fmt, &int_fmt);
if(img_load_success) if(img_load_success)
{ {
struct Texture* new_texture = NULL; index = texture_create(filename, texture_unit, width, height, fmt, int_fmt, GL_UNSIGNED_BYTE, img_data);
if(array_len(empty_indices) > 0) if(index > -1)
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
new_texture = &texture_list[index];
}
else
{ {
new_texture = array_grow(texture_list, struct Texture);
index = array_len(texture_list) - 1;
new_texture->name = NULL;
}
assert(new_texture);
glGenTextures(1, &handle);
if(new_texture->name)
free(new_texture->name);
new_texture->name = str_new(filename);
new_texture->ref_count = 1;
new_texture->handle = handle;
new_texture->texture_unit = texture_unit;
glBindTexture(GL_TEXTURE_2D, handle);
texture_param_set(index, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 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_MAG_FILTER, GL_LINEAR);
texture_param_set(index,GL_TEXTURE_WRAP_S,GL_REPEAT); texture_param_set(index,GL_TEXTURE_WRAP_S,GL_REPEAT);
texture_param_set(index,GL_TEXTURE_WRAP_T,GL_REPEAT); texture_param_set(index,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, internal_fmt, width, height, 0, fmt, GL_UNSIGNED_BYTE, img_data); }
renderer_check_glerror("texture:create"); else
glBindTexture(GL_TEXTURE_2D, 0); {
log_error("texture:create_from_file", "Error creating texture");
}
free(img_data); free(img_data);
} }
fclose(file); fclose(file);
@ -358,3 +341,75 @@ int texture_get_textureunit(int index)
assert(index > -1 && index < array_len(texture_list)); assert(index > -1 && index < array_len(texture_list));
return texture_list[index].texture_unit; return texture_list[index].texture_unit;
} }
int texture_get_texture_handle(int index)
{
assert(index > -1 && index < array_len(texture_list));
return texture_list[index].handle;
}
void texture_inc_refcount(int index)
{
assert(index > -1 && index < array_len(texture_list));
texture_list[index].ref_count++;
}
void texture_dec_refcount(int index)
{
assert(index > -1 && index < array_len(texture_list));
texture_list[index].ref_count--;
}
int texture_create(const char* name,
int texture_unit,
int width,
int height,
int format,
int int_fmt,
int type,
void* data)
{
assert(name && texture_unit > -1 && texture_unit <= TU_SHADOWMAP4);
int index = -1;
uint handle = 0;
int success = create_gl_texture(&handle, width, height, format, int_fmt, type, data);
if(success)
{
struct Texture* new_tex = NULL;
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
new_tex = &texture_list[index];
}
else
{
new_tex = array_grow(texture_list, struct Texture);
index = array_len(texture_list) - 1;
}
new_tex->name = str_new(name);
new_tex->handle = handle;
new_tex->ref_count = 1;
new_tex->texture_unit = texture_unit;
}
return index;
}
int create_gl_texture(uint* out_handle, int width, int height, int format, int int_fmt, int type, void* data)
{
int success = 1;
glGenTextures(1, out_handle);
if(renderer_check_glerror("texture:create_gl_texture:glGentexture"))
{
success = 0;
}
else
{
glBindTexture(GL_TEXTURE_2D, *out_handle);
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, width, height, 0, format, type, data);
if(renderer_check_glerror("texture:create_gl_texture:glTexImage2d"))
success = 0;
glBindTexture(GL_TEXTURE_2D, 0);
}
return success;
}

@ -19,5 +19,16 @@ 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_param_set(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);
void texture_inc_refcount(int index);
void texture_dec_refcount(int index);
int texture_create(const char* name,
int texture_unit,
int width,
int height,
int format,
int int_fmt,
int type,
void* data);
#endif #endif

Loading…
Cancel
Save