You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
3.8 KiB
163 lines
3.8 KiB
#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, ¤t_fbo);
|
|
renderer_check_glerror("framebuffer:set_texture:glGet");
|
|
framebuffer_bind(index);
|
|
glFramebufferTexture2D(GL_DRAW_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;
|
|
}
|
|
|