mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-02 11:47:56 +03:00
312 lines
10 KiB
C++
312 lines
10 KiB
C++
/*
|
|
by korenkonder
|
|
GitHub/GitLab: korenkonder
|
|
*/
|
|
|
|
#include "blur.hpp"
|
|
#include "../fbo.hpp"
|
|
#include "../gl_state.hpp"
|
|
#include "../post_process.hpp"
|
|
#include "../render_context.hpp"
|
|
#include "../shader_ft.hpp"
|
|
|
|
struct gaussian_coef_shader_data {
|
|
vec4 g_coef[8];
|
|
};
|
|
|
|
static void post_process_blur_radius_calculate(post_process_blur* blur);
|
|
static void post_process_blur_radius_calculate_gaussian_kernel(float_t* gaussian_kernel,
|
|
float_t radius, int32_t stride, int32_t offset);
|
|
|
|
post_process_blur::post_process_blur() : data(),
|
|
width(), height(), width_down(), height_down(), tex_down(), count_down() {
|
|
tex[0].init(256, 144, 0, GL_RGBA16F, 0);
|
|
tex[1].init(128, 72, 0, GL_RGBA16F, 0);
|
|
tex[2].init(64, 36, 0, GL_RGBA16F, 0);
|
|
tex[3].init(32, 18, 0, GL_RGBA16F, 0);
|
|
tex[4].init(8, 8, 0, GL_RGBA16F, 0);
|
|
tex[5].init(256, 144, 0, GL_RGBA16F, 0);
|
|
gaussian_coef_ubo.Create(sizeof(gaussian_coef_shader_data));
|
|
}
|
|
|
|
post_process_blur:: ~post_process_blur() {
|
|
if (!this)
|
|
return;
|
|
|
|
gaussian_coef_ubo.Destroy();
|
|
for (int32_t i = 0; i < count_down; i++)
|
|
tex_down[i].free();
|
|
free_def(tex_down);
|
|
free_def(height_down);
|
|
free_def(width_down);
|
|
}
|
|
|
|
void post_process_blur::get_blur(render_texture* rt) {
|
|
uniform_value[U_ALPHA_MASK] = 0;
|
|
|
|
vec3 intensity = data.intensity;
|
|
vec3* gauss = data.gauss;
|
|
|
|
gaussian_coef_shader_data gaussian_coef = {};
|
|
for (int32_t i = 0; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE && i < 8; i++) {
|
|
vec3 coef = gauss[i] * intensity;
|
|
gaussian_coef.g_coef[i] = { coef.x, coef.y, coef.z, 0.0f };
|
|
}
|
|
|
|
gaussian_coef_ubo.WriteMapMemory(gaussian_coef);
|
|
|
|
int32_t i = 0;
|
|
if (count_down > 0) {
|
|
uniform_value[U_REDUCE] = 1;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_REDUCE);
|
|
for (; i < count_down; i++) {
|
|
glViewport(0, 0, width_down[i], height_down[i]);
|
|
tex_down[i].bind();
|
|
gl_state_active_bind_texture_2d(0, i
|
|
? tex_down[i - 1].color_texture->tex
|
|
: rt->color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, width_down[i], height_down[i]);
|
|
}
|
|
i--;
|
|
}
|
|
|
|
uniform_value[U_REDUCE] = 3;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_REDUCE);
|
|
|
|
glViewport(0, 0, 256, 144);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, count_down > 0
|
|
? tex_down[i].color_texture->tex
|
|
: rt->color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, width, height, 1.0f, 1.1f, 1.1f, 1.1f, 0.0f);
|
|
|
|
uniform_value[U_GAUSS] = 1;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_GAUSS);
|
|
|
|
glViewport(0, 0, 256, 144);
|
|
tex[5].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[0].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 256, 144, 1.0f,
|
|
data.intensity.x * 0.5f, data.intensity.y * 0.5f, data.intensity.z * 0.5f, 1.0f);
|
|
|
|
uniform_value[U_REDUCE] = 1;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_REDUCE);
|
|
|
|
glViewport(0, 0, 128, 72);
|
|
tex[1].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[0].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 256, 144);
|
|
|
|
uniform_value[U_REDUCE] = 1;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_REDUCE);
|
|
|
|
glViewport(0, 0, 64, 36);
|
|
tex[2].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[1].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 128, 72);
|
|
|
|
uniform_value[U_REDUCE] = 1;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_REDUCE);
|
|
|
|
glViewport(0, 0, 32, 18);
|
|
tex[3].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[2].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 64, 36);
|
|
|
|
uniform_value[U_EXPOSURE] = 0;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_EXPOSURE);
|
|
|
|
glViewport(0, 0, 8, 8);
|
|
tex[4].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[3].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 32, 18);
|
|
|
|
uniform_value[U_GAUSS] = 0;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_GAUSS);
|
|
gaussian_coef_ubo.Bind(1);
|
|
|
|
glViewport(0, 0, 128, 72);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[1].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 128, 72, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f);
|
|
fbo::blit(tex[0].fbos[0], tex[1].fbos[0],
|
|
0, 0, 128, 72,
|
|
0, 0, 128, 72, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
|
|
glViewport(0, 0, 64, 36);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[2].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 64, 36, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f);
|
|
fbo::blit(tex[0].fbos[0], tex[2].fbos[0],
|
|
0, 0, 64, 36,
|
|
0, 0, 64, 36, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
|
|
glViewport(0, 0, 32, 18);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[3].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 32, 18);
|
|
fbo::blit(tex[0].fbos[0], tex[3].fbos[0],
|
|
0, 0, 32, 18,
|
|
0, 0, 32, 18, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
|
|
glViewport(0, 0, 128, 72);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[1].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 128, 72, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
fbo::blit(tex[0].fbos[0], tex[1].fbos[0],
|
|
0, 0, 128, 72,
|
|
0, 0, 128, 72, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
|
|
glViewport(0, 0, 64, 36);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[2].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 64, 36, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
fbo::blit(tex[0].fbos[0], tex[2].fbos[0],
|
|
0, 0, 64, 36,
|
|
0, 0, 64, 36, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
|
|
glViewport(0, 0, 32, 18);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[3].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 32, 18, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
fbo::blit(tex[0].fbos[0], tex[3].fbos[0],
|
|
0, 0, 32, 18,
|
|
0, 0, 32, 18, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
|
|
uniform_value[U_REDUCE] = 7;
|
|
shaders_ft.set_opengl_shader(SHADER_FT_REDUCE);
|
|
|
|
glViewport(0, 0, 256, 144);
|
|
tex[0].bind();
|
|
gl_state_active_bind_texture_2d(0, tex[5].color_texture->tex);
|
|
gl_state_active_bind_texture_2d(1, tex[1].color_texture->tex);
|
|
gl_state_active_bind_texture_2d(2, tex[2].color_texture->tex);
|
|
gl_state_active_bind_texture_2d(3, tex[3].color_texture->tex);
|
|
render_texture::draw_quad(&shaders_ft, 32, 18, 0.25f, 0.15f, 0.25f, 0.25f, 0.25f);
|
|
}
|
|
|
|
void post_process_blur::init_fbo(int32_t width, int32_t height) {
|
|
if (!this || (this->width == width && this->height == height))
|
|
return;
|
|
|
|
this->width = width > 1 ? width : 1;
|
|
this->height = height > 1 ? height : 1;
|
|
|
|
int32_t i = 0;
|
|
width = this->width;
|
|
height = this->height;
|
|
while (width > 512 && height > 288) {
|
|
width /= 2;
|
|
height /= 2;
|
|
i++;
|
|
}
|
|
|
|
render_texture* tex_down = this->tex_down;
|
|
int32_t* width_down = this->width_down;
|
|
int32_t* height_down = this->height_down;
|
|
|
|
if (!tex_down)
|
|
tex_down = force_malloc_s(render_texture, i);
|
|
else if (count_down < i) {
|
|
render_texture* temp = force_malloc_s(render_texture, i);
|
|
memcpy(temp, tex_down, sizeof(render_texture) * count_down);
|
|
free_def(tex_down);
|
|
tex_down = temp;
|
|
}
|
|
|
|
if (!width_down)
|
|
width_down = force_malloc_s(int32_t, i);
|
|
else if (count_down < i) {
|
|
int32_t* temp = force_malloc_s(int32_t, i);
|
|
memcpy(temp, width_down, sizeof(int32_t) * count_down);
|
|
free_def(width_down);
|
|
width_down = temp;
|
|
}
|
|
|
|
if (!height_down)
|
|
height_down = force_malloc_s(int32_t, i);
|
|
else if (count_down < i) {
|
|
int32_t* temp = force_malloc_s(int32_t, i);
|
|
memcpy(temp, height_down, sizeof(int32_t) * count_down);
|
|
free_def(height_down);
|
|
height_down = temp;
|
|
}
|
|
|
|
count_down = i;
|
|
|
|
i = 0;
|
|
width = this->width;
|
|
height = this->height;
|
|
while (width > 512 && height > 288) {
|
|
width_down[i] = width /= 2;
|
|
height_down[i] = height /= 2;
|
|
i++;
|
|
}
|
|
|
|
for (i = 0; i < count_down; i++)
|
|
tex_down[i].init(width_down[i], height_down[i], 0, GL_RGBA16F, 0);
|
|
|
|
gl_state_bind_framebuffer(0);
|
|
|
|
this->tex_down = tex_down;
|
|
this->width_down = width_down;
|
|
this->height_down = height_down;
|
|
}
|
|
|
|
void post_process_blur::initialize_data(const vec3& radius, const vec3& intensity) {
|
|
data.radius = vec3::clamp(radius, 1.0f, 3.0f);
|
|
data.intensity = vec3::clamp(intensity, 0.0f, 2.0f);
|
|
post_process_blur_radius_calculate(this);
|
|
}
|
|
|
|
vec3 post_process_blur::get_intensity() {
|
|
return data.intensity;
|
|
}
|
|
|
|
void post_process_blur::set_intensity(const vec3& value) {
|
|
data.intensity = vec3::clamp(value, 0.0f, 2.0f);
|
|
}
|
|
|
|
vec3 post_process_blur::get_radius() {
|
|
return data.radius;
|
|
}
|
|
|
|
void post_process_blur::set_radius(const vec3& value) {
|
|
vec3 temp = vec3::clamp(value, 1.0f, 3.0f);
|
|
if (temp != data.radius) {
|
|
data.radius = temp;
|
|
post_process_blur_radius_calculate(this);
|
|
}
|
|
}
|
|
|
|
static void post_process_blur_radius_calculate(post_process_blur* blur) {
|
|
float_t radius_scale = 0.8f;
|
|
vec3 radius = blur->data.radius;
|
|
post_process_blur_radius_calculate_gaussian_kernel((float_t*)blur->data.gauss, radius.x * radius_scale, 3, 0);
|
|
post_process_blur_radius_calculate_gaussian_kernel((float_t*)blur->data.gauss, radius.y * radius_scale, 3, 1);
|
|
post_process_blur_radius_calculate_gaussian_kernel((float_t*)blur->data.gauss, radius.z * radius_scale, 3, 2);
|
|
}
|
|
|
|
static void post_process_blur_radius_calculate_gaussian_kernel(float_t* gaussian_kernel,
|
|
float_t radius, int32_t stride, int32_t offset) {
|
|
if (stride < 1)
|
|
stride = 1;
|
|
if (offset < 0)
|
|
offset = 0;
|
|
|
|
gaussian_kernel[0 * stride + offset] = 1.0f;
|
|
for (int32_t i = 1; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++)
|
|
gaussian_kernel[i * stride + offset] = 0.0f;
|
|
double_t temp_gaussian_kernel[POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE];
|
|
double_t s = radius;
|
|
s = -1.0 / (2.0 * s * s);
|
|
double_t sum = 0.5;
|
|
temp_gaussian_kernel[0] = 1.0;
|
|
for (size_t i = 1; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++)
|
|
sum += temp_gaussian_kernel[i] = exp(i * i * s);
|
|
|
|
sum = 0.5 / sum;
|
|
for (size_t i = 0; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++)
|
|
gaussian_kernel[i * stride + offset] = (float_t)(temp_gaussian_kernel[i] * sum);
|
|
}
|