Files
korenkonder_ReDIVA/src/CRE/fbo_pp.c
T
2021-05-11 21:04:48 +03:00

446 lines
15 KiB
C

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "fbo_pp.h"
#include "fbo_helper.h"
#include "../KKdLib/half_t.h"
const GLenum fbo_pp_s_attachments[] = {
GL_COLOR_ATTACHMENT0,
};
const GLenum fbo_pp_d_attachments[] = {
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
};
static void fbo_pp_bind_fbo(fbo_pp* pfbo, vec2i* res);
fbo_pp* fbo_pp_init() {
fbo_pp* pfbo = force_malloc(sizeof(fbo_pp));
glGenFramebuffers(11, pfbo->fbo);
glGenTextures(16, pfbo->tcb);
return pfbo;
}
void fbo_pp_initialize(fbo_pp* pfbo, vec2i* res, int32_t vao,
shader_fbo* b_shader, shader_fbo* t_shader, int32_t tone_map_ubo) {
if (!pfbo)
return;
pfbo->vao = vao;
pfbo->tone_map_ubo = tone_map_ubo;
pfbo->dst_pixel = 0;
memset(&pfbo->tone_map, 0, sizeof(texture));
memcpy(pfbo->b_shader, b_shader, sizeof(shader_fbo) * 16);
pfbo->t_shader = *t_shader;
shader_fbo_use(&pfbo->b_shader[2]);
shader_fbo_set_vec4(&pfbo->b_shader[2], "res", 256.0f, 144.0f, 1.0f / 256.0f, 1.0f / 144.0f);
shader_fbo_use(&pfbo->b_shader[3]);
shader_fbo_set_vec4(&pfbo->b_shader[3], "res", 128.0f, 72.0f, 1.0f / 128.0f, 1.0f / 72.0f);
shader_fbo_use(&pfbo->b_shader[4]);
shader_fbo_set_vec4(&pfbo->b_shader[4], "res", 64.0f, 36.0f, 1.0f / 64.0f, 1.0f / 36.0f);
shader_fbo_use(&pfbo->b_shader[5]);
shader_fbo_set_vec4(&pfbo->b_shader[5], "res", 32.0f, 18.0f, 1.0f / 32.0f, 1.0f / 18.0f);
shader_fbo_use(&pfbo->b_shader[6]);
shader_fbo_set_vec2_array(&pfbo->b_shader[6], "direction", 6, ((vec2[]) {
{ 1.0f / 128.0f, 0.0f },
{ 2.0f / 128.0f, 0.0f },
{ 3.0f / 128.0f, 0.0f },
{ 4.0f / 128.0f, 0.0f },
{ 5.0f / 128.0f, 0.0f },
{ 6.0f / 128.0f, 0.0f },
}));
shader_fbo_use(&pfbo->b_shader[7]);
shader_fbo_set_vec2_array(&pfbo->b_shader[7], "direction", 6, ((vec2[]) {
{ 1.0f / 64.0f, 0.0f },
{ 2.0f / 64.0f, 0.0f },
{ 3.0f / 64.0f, 0.0f },
{ 4.0f / 64.0f, 0.0f },
{ 5.0f / 64.0f, 0.0f },
{ 6.0f / 64.0f, 0.0f },
}));
shader_fbo_use(&pfbo->b_shader[8]);
shader_fbo_set_vec2_array(&pfbo->b_shader[8], "direction", 6, ((vec2[]) {
{ 1.0f / 32.0f, 0.0f},
{ 2.0f / 32.0f, 0.0f },
{ 3.0f / 32.0f, 0.0f },
{ 4.0f / 32.0f, 0.0f },
{ 5.0f / 32.0f, 0.0f },
{ 6.0f / 32.0f, 0.0f },
}));
shader_fbo_use(&pfbo->b_shader[9]);
shader_fbo_set_vec2_array(&pfbo->b_shader[9], "direction", 6, ((vec2[]) {
{ 0.0f, 1.0f / 72.0f },
{ 0.0f, 2.0f / 72.0f },
{ 0.0f, 3.0f / 72.0f },
{ 0.0f, 4.0f / 72.0f },
{ 0.0f, 5.0f / 72.0f },
{ 0.0f, 6.0f / 72.0f },
}));
shader_fbo_use(&pfbo->b_shader[10]);
shader_fbo_set_vec2_array(&pfbo->b_shader[10], "direction", 6, ((vec2[]) {
{ 0.0f, 1.0f / 36.0f },
{ 0.0f, 2.0f / 36.0f },
{ 0.0f, 3.0f / 36.0f },
{ 0.0f, 4.0f / 36.0f },
{ 0.0f, 5.0f / 36.0f },
{ 0.0f, 6.0f / 36.0f },
}));
shader_fbo_use(&pfbo->b_shader[11]);
shader_fbo_set_vec2_array(&pfbo->b_shader[11], "direction", 6, ((vec2[]) {
{ 0.0f, 1.0f / 18.0f },
{ 0.0f, 2.0f / 18.0f },
{ 0.0f, 3.0f / 18.0f },
{ 0.0f, 4.0f / 18.0f },
{ 0.0f, 5.0f / 18.0f },
{ 0.0f, 6.0f / 18.0f },
}));
shader_fbo_use(&pfbo->b_shader[12]);
shader_fbo_set_vec4(&pfbo->b_shader[12], "res", 256.0f, 144.0f, 1.0f / 256.0f, 1.0f / 144.0f);
shader_fbo_use(&pfbo->b_shader[13]);
shader_fbo_set_vec4(&pfbo->b_shader[13], "res", 256.0f, 144.0f, 1.0f / 256.0f, 1.0f / 144.0f);
glGenFramebuffers(11, pfbo->fbo);
glGenTextures(16, pfbo->tcb);
bind_framebuffer(pfbo->fbo[0]);
fbo_helper_gen_texture_image_ms(pfbo->tcb[0], 256, 144, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_gen_texture_image_ms(pfbo->tcb[1], 256, 144, 1, GL_R16F, GL_RED, GL_HALF_FLOAT, 1);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[1]);
fbo_helper_gen_texture_image_ms(pfbo->tcb[2], 128, 72, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_gen_texture_image_ms(pfbo->tcb[3], 128, 72, 1, GL_R16F, GL_RED, GL_HALF_FLOAT, 1);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[2]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(pfbo->tcb[4], 128, 72, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[3]);
fbo_helper_gen_texture_image_ms(pfbo->tcb[5], 64, 36, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_gen_texture_image_ms(pfbo->tcb[6], 64, 36, 1, GL_R16F, GL_RED, GL_HALF_FLOAT, 1);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[4]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(pfbo->tcb[7], 64, 36, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[5]);
fbo_helper_gen_texture_image_ms(pfbo->tcb[8], 32, 18, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_gen_texture_image_ms(pfbo->tcb[9], 32, 18, 1, GL_R16F, GL_RED, GL_HALF_FLOAT, 1);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[6]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(pfbo->tcb[10], 32, 18, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[7]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(pfbo->tcb[11], 8, 8, 1, GL_R32F, GL_RED, GL_FLOAT, 0);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[8]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(pfbo->tcb[12], 256, 144, 1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[9]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(pfbo->tcb[13], 1, 1, 1, GL_R32F, GL_RED, GL_FLOAT, 0);
fbo_helper_get_error_code();
bind_framebuffer(pfbo->fbo[10]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(pfbo->tcb[14], 1, 1, 1, GL_R32F, GL_RED, GL_FLOAT, 0);
fbo_helper_get_error_code();
bind_tex2d(pfbo->tcb[15]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 32, 1, 0, GL_RED, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
bind_tex2d(0);
fbo_pp_bind_fbo(pfbo, res);
}
void fbo_pp_resize(fbo_pp* pfbo, vec2i* res) {
if (!pfbo)
return;
fbo_pp_bind_fbo(pfbo, res);
}
void fbo_pp_tone_map_set(fbo_pp* pfbo, vec2* tone_map_data, int32_t count) {
texture_data data;
memset(&data, 0, sizeof(texture_data));
data.type = TEXTURE_1D;
data.width = count;
data.pixel_format = GL_RG;
data.pixel_internal_format = GL_RG16F;
data.pixel_type = GL_FLOAT;
data.mag_filter = GL_LINEAR;
data.min_filter = GL_LINEAR;
data.wrap_mode_s = GL_CLAMP_TO_EDGE;
data.data = tone_map_data;
texture_load(&pfbo->tone_map, &data);
}
static void fbo_pp_bind_fbo(fbo_pp* pfbo, vec2i* res) {
pfbo->res.x = res->x > 1 ? res->x : 1;
pfbo->res.y = res->y > 1 ? res->y : 1;
int i = 0;
vec2i r = pfbo->res;
while (r.x > 512 && r.y > 288) {
r.x /= 2;
r.y /= 2;
i++;
}
if (i < pfbo->full_count_down)
pfbo->full_count_down = pfbo->count_down;
else
pfbo->full_count_down = i;
int32_t* fbo_down = pfbo->fbo_down;
int32_t* tcb_down = pfbo->tcb_down;
vec2i* res_down = pfbo->res_down;
if (!fbo_down)
fbo_down = force_malloc_s(int32_t, i);
else if (pfbo->count_down < i) {
void* temp = force_malloc_s(int32_t, i);
memcpy(temp, fbo_down, sizeof(int32_t) * pfbo->count_down);
free(fbo_down);
fbo_down = temp;
}
if (!tcb_down)
tcb_down = force_malloc_s(int32_t, i);
else if (pfbo->count_down < i) {
void* temp = force_malloc_s(int32_t, i);
memcpy(temp, tcb_down, sizeof(int32_t) * pfbo->count_down);
free(tcb_down);
tcb_down = temp;
}
if (!res_down)
res_down = force_malloc_s(vec2i, i);
else if (pfbo->count_down < i) {
void* temp = force_malloc_s(vec2i, i);
memcpy(temp, res_down, sizeof(vec2i) * pfbo->count_down);
free(res_down);
res_down = temp;
}
pfbo->count_down = i;
for (i = 0; i < pfbo->count_down; i++) {
if (fbo_down[i] == 0)
glGenFramebuffers(1, &fbo_down[i]);
if (tcb_down[i] == 0)
glGenTextures(1, &tcb_down[i]);
}
i = 0;
r = pfbo->res;
while (r.x > 512 && r.y > 288) {
res_down[i].x = r.x /= 2;
res_down[i].y = r.y /= 2;
i++;
}
shader_fbo_use(&pfbo->b_shader[1]);
shader_fbo_set_vec4(&pfbo->b_shader[1], "res",
(float_t)r.x, (float_t)r.y, 1.0f / (float_t)r.x, 1.0f / (float_t)r.y);
for (i = 0; i < pfbo->count_down; i++) {
bind_framebuffer(fbo_down[i]);
glDrawBuffers(1, fbo_pp_s_attachments);
fbo_helper_gen_texture_image_ms(tcb_down[i], res_down[i].x, res_down[i].y,
1, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0);
fbo_helper_get_error_code();
}
bind_framebuffer(0);
pfbo->fbo_down = fbo_down;
pfbo->tcb_down = tcb_down;
pfbo->res_down = res_down;
}
void fbo_pp_draw(fbo_pp* pfbo, int32_t in_tcb, int32_t out_fbo,
int32_t out_fbo_attachments_count, const GLenum* out_fbo_attachments) {
pfbo->dst_pixel++;
if (pfbo->dst_pixel > 31)
pfbo->dst_pixel = 0;
bind_vertex_array(pfbo->vao);
int i = 0;
if (pfbo->count_down > 0) {
shader_fbo_use(&pfbo->b_shader[0]);
for (; i < pfbo->count_down; i++) {
glViewport(0, 0, pfbo->res_down[i].x, pfbo->res_down[i].y); // 0
bind_framebuffer(pfbo->fbo_down[i]);
shader_fbo_set_vec4(&pfbo->b_shader[0], "res",
(float_t)pfbo->res_down[i].x, (float_t)pfbo->res_down[i].y,
1.0f / (float_t)pfbo->res_down[i].x, 1.0f / (float_t)pfbo->res_down[i].y);
bind_index_tex2d(0, i == 0 ? in_tcb : pfbo->tcb_down[i - 1]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
i--;
}
glViewport(0, 0, 256, 144); // 1
bind_framebuffer(pfbo->fbo[0]);
glDrawBuffers(2, fbo_pp_d_attachments);
shader_fbo_use(&pfbo->b_shader[1]);
bind_index_tex2d(0, pfbo->count_down > 0 ? pfbo->tcb_down[i] : in_tcb);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 128, 72); // 2
bind_framebuffer(pfbo->fbo[1]);
glDrawBuffers(2, fbo_pp_d_attachments);
shader_fbo_use(&pfbo->b_shader[2]);
bind_index_tex2d(0, pfbo->tcb[0]);
bind_index_tex2d(1, pfbo->tcb[1]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 64, 36); // 3
bind_framebuffer(pfbo->fbo[3]);
glDrawBuffers(2, fbo_pp_d_attachments);
shader_fbo_use(&pfbo->b_shader[3]);
bind_index_tex2d(0, pfbo->tcb[2]);
bind_index_tex2d(1, pfbo->tcb[3]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 32, 18); // 4
bind_framebuffer(pfbo->fbo[5]);
glDrawBuffers(2, fbo_pp_d_attachments);
shader_fbo_use(&pfbo->b_shader[4]);
bind_index_tex2d(0, pfbo->tcb[5]);
bind_index_tex2d(1, pfbo->tcb[6]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 8, 8); // 5
bind_framebuffer(pfbo->fbo[7]);
shader_fbo_use(&pfbo->b_shader[5]);
bind_index_tex2d(0, pfbo->tcb[9]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 128, 72); // 6
bind_framebuffer(pfbo->fbo[2]);
shader_fbo_use(&pfbo->b_shader[6]);
bind_index_tex2d(0, pfbo->tcb[2]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 64, 36); // 7
bind_framebuffer(pfbo->fbo[4]);
shader_fbo_use(&pfbo->b_shader[7]);
bind_index_tex2d(0, pfbo->tcb[5]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 32, 18); // 8
bind_framebuffer(pfbo->fbo[6]);
shader_fbo_use(&pfbo->b_shader[8]);
bind_index_tex2d(0, pfbo->tcb[8]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 128, 72); // 9
bind_framebuffer(pfbo->fbo[1]);
glDrawBuffers(1, fbo_pp_s_attachments);
shader_fbo_use(&pfbo->b_shader[9]);
bind_index_tex2d(0, pfbo->tcb[4]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 64, 36); // 10
bind_framebuffer(pfbo->fbo[3]);
glDrawBuffers(1, fbo_pp_s_attachments);
shader_fbo_use(&pfbo->b_shader[10]);
bind_index_tex2d(0, pfbo->tcb[7]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 32, 18); // 11
bind_framebuffer(pfbo->fbo[5]);
glDrawBuffers(1, fbo_pp_s_attachments);
shader_fbo_use(&pfbo->b_shader[11]);
bind_index_tex2d(0, pfbo->tcb[10]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 256, 144); // 12
bind_framebuffer(pfbo->fbo[8]);
shader_fbo_use(&pfbo->b_shader[12]);
bind_index_tex2d(0, pfbo->tcb[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 256, 144); // 13
bind_framebuffer(pfbo->fbo[0]);
glDrawBuffers(1, fbo_pp_s_attachments);
shader_fbo_use(&pfbo->b_shader[13]);
bind_index_tex2d(0, pfbo->tcb[12]);
bind_index_tex2d(1, pfbo->tcb[2]);
bind_index_tex2d(2, pfbo->tcb[5]);
bind_index_tex2d(3, pfbo->tcb[8]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, 1, 1); // 14
bind_framebuffer(pfbo->fbo[9]);
shader_fbo_use(&pfbo->b_shader[14]);
bind_index_tex2d(0, pfbo->tcb[11]);
bind_index_tex2d(1, pfbo->tcb[6]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
bind_framebuffer(pfbo->fbo[9]);
glReadBuffer(GL_COLOR_ATTACHMENT0);
bind_index_tex2d(0, pfbo->tcb[15]);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, pfbo->dst_pixel, 0, 0, 0, 1, 1);
glViewport(0, 0, 1, 1); // 15
bind_framebuffer(pfbo->fbo[10]);
shader_fbo_use(&pfbo->b_shader[15]);
bind_index_tex2d(0, pfbo->tcb[15]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
int32_t tone_map_shader_flags[8];
memset(tone_map_shader_flags, 0, sizeof(int32_t) * 8);
tone_map_shader_flags[1] = pfbo->tone_map_method;
tone_map_shader_flags[3] = pfbo->scene_fade ? 1 : 0;
glBindBufferBase(GL_UNIFORM_BUFFER, 1, pfbo->tone_map_ubo);
glViewport(0, 0, pfbo->res.x, pfbo->res.y); // 16
bind_framebuffer(out_fbo);
glDrawBuffers(out_fbo_attachments_count, out_fbo_attachments);
shader_fbo_use(&pfbo->t_shader);
shader_fbo_set_int_array(&pfbo->t_shader, "mode", 8, tone_map_shader_flags);
bind_index_tex2d(0, in_tcb);
bind_index_tex2d(1, pfbo->tcb[0]);
if (pfbo->tone_map_method == 0)
bind_index_tex1d(2, pfbo->tone_map.id);
bind_index_tex2d(3, pfbo->tcb[14]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void fbo_pp_dispose(fbo_pp* pfbo) {
if (!pfbo)
return;
glDeleteFramebuffers(pfbo->full_count_down, pfbo->fbo_down);
glDeleteTextures(pfbo->full_count_down, pfbo->tcb_down);
texture_free(&pfbo->tone_map);
glDeleteFramebuffers(11, pfbo->fbo);
glDeleteTextures(16, pfbo->tcb);
free(pfbo);
}