diff --git a/src/CRE/render.cpp b/src/CRE/render.cpp index 22d37895..c6cacc11 100644 --- a/src/CRE/render.cpp +++ b/src/CRE/render.cpp @@ -149,8 +149,7 @@ namespace rndr { calc_exposure(cam); apply_tone_map(light_proj_tex, npr_param); - if (mlaa) - apply_mlaa(ss_alpha_mask); + apply_mlaa(taa_texture_selector, 2, ss_alpha_mask); for (int32_t i = 0; i < 16; i++) { if (!render_textures_data[i]) @@ -165,7 +164,7 @@ namespace rndr { uniform_value[U_REDUCE] = 0; gl_state_set_viewport(0, 0, t->width, t->height); - gl_state_active_bind_texture_2d(0, taa_tex[2]->glid); + gl_state_active_bind_texture_2d(0, taa_tex[taa_texture_selector]->glid); gl_state_bind_sampler(0, rctx->render_samplers[0]); shaders_ft.set(SHADER_FT_REDUCE); draw_quad(render_post_width[0], render_post_height[0], @@ -174,14 +173,80 @@ namespace rndr { } copy_to_frame_texture(rend_texture[0].GetColorTex(), - render_width[0], render_height[0], taa_tex[2]->glid); + render_width[0], render_height[0], taa_tex[taa_texture_selector]->glid); - frame_texture_reset_capture(); + if (taa) { + if (taa_blend >= 0.0f) + calc_taa_blend(); + else + taa_blend = 1.0f; + } + + if (taa_blend < 0.0f || taa_blend >= 1.0f) + taa_texture = taa_texture_selector; + else { + bool blur; + GLuint sampler; + if (taa_blend > 0.99f) { + blur = true; + sampler = rctx->render_samplers[0]; + } + else { + blur = false; + sampler = rctx->render_samplers[1]; + } + + taa_texture = 2; + taa_buffer[2].Bind(); + glViewport(0, 0, render_width[0], render_height[0]); + gl_state_active_bind_texture_2d(0, taa_tex[taa_texture_selector]->glid); + gl_state_bind_sampler(0, sampler); + + if (blur) { + gl_state_active_bind_texture_2d(2, rend_texture[0].depth_texture->glid); + gl_state_bind_sampler(2, sampler); + + mat4 mat; + mat4_invert(&cam_view_projection, &mat); + mat4_mul(&cam_view_projection_prev, &mat, &mat); + mat4_transpose(&mat, &mat); + uniform_value[U_REDUCE] = 6; + + camera_blur_shader_data shader_data = {}; + shader_data.g_transform[0] = mat.row0; + shader_data.g_transform[1] = mat.row1; + shader_data.g_transform[2] = mat.row2; + shader_data.g_transform[3] = mat.row3; + rctx->camera_blur_ubo.WriteMemory(shader_data); + rctx->camera_blur_ubo.Bind(1); + } + else { + int32_t taa_texture_selector = this->taa_texture_selector + 1; + if (taa_texture_selector > taa) + taa_texture_selector = 0; + gl_state_active_bind_texture_2d(1, taa_tex[taa_texture_selector]->glid); + gl_state_bind_sampler(1, sampler); + uniform_value[U_REDUCE] = 5; + } + + shaders_ft.set(SHADER_FT_REDUCE); + + draw_quad(render_post_width[0], render_post_height[0], + render_post_width_scale, render_post_height_scale, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, taa_blend); + } + + if (taa) { + int32_t taa_texture_selector = this->taa_texture_selector + 1; + if (taa_texture_selector > taa) + taa_texture_selector = 0; + this->taa_texture_selector = taa_texture_selector; + } rctx->screen_buffer.Bind(); gl_state_set_viewport(0, 0, rctx->sprite_width, rctx->sprite_height); if (ssaa) { - gl_state_active_bind_texture_2d(0, taa_tex[2]->glid); + gl_state_active_bind_texture_2d(0, taa_tex[taa_texture]->glid); gl_state_bind_sampler(0, rctx->render_samplers[0]); uniform_value[U_ALPHA_MASK] = ss_alpha_mask ? 1 : 0; uniform_value[U_REDUCE] = 0; @@ -192,7 +257,7 @@ namespace rndr { uniform_value[U_ALPHA_MASK] = 0; } else { - gl_state_active_bind_texture_2d(0, taa_tex[2]->glid); + gl_state_active_bind_texture_2d(0, taa_tex[taa_texture]->glid); if (mag_filter == MAG_FILTER_NEAREST) gl_state_bind_sampler(0, rctx->render_samplers[1]); else @@ -337,6 +402,9 @@ namespace rndr { else stage_index = task_stage_get_current_stage_index(); + cam_view_projection_prev = cam_view_projection; + cam_view_projection = cam->view_projection; + reset_exposure = cam->fast_change_hist1 && !cam->fast_change_hist0; if (reset_exposure) { float_t view_point_dist = vec3::distance(view_point, view_point_prev); @@ -1449,51 +1517,56 @@ namespace rndr { taa_blend = -1.0f; } - void Render::apply_mlaa(int32_t ss_alpha_mask) { - render_context* rctx = rctx_ptr; + void Render::apply_mlaa(int32_t destination, int32_t source, int32_t ss_alpha_mask) { + if (mlaa) { + gl_state_begin_event("PostProcess::mlaa"); + mlaa_buffer.Bind(); + gl_state_active_bind_texture_2d(0, taa_tex[source]->glid); + gl_state_bind_sampler(0, rctx_ptr->render_samplers[1]); + uniform_value[U_MLAA] = 0; + shaders_ft.set(SHADER_FT_MLAA); + draw_quad(render_post_width[0], render_post_height[0], + render_post_width_scale, render_post_height_scale, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); - gl_state_begin_event("PostProcess::mlaa"); - mlaa_buffer.Bind(); - gl_state_active_bind_texture_2d(0, taa_tex[2]->glid); - gl_state_bind_sampler(0, rctx->render_samplers[1]); - uniform_value[U_MLAA] = 0; - shaders_ft.set(SHADER_FT_MLAA); - draw_quad(render_post_width[0], render_post_height[0], - render_post_width_scale, render_post_height_scale, - 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + temp_buffer.Bind(); + gl_state_active_bind_texture_2d(0, mlaa_buffer.GetColorTex()); + gl_state_active_bind_texture_2d(1, mlaa_area_texture); + gl_state_bind_sampler(0, rctx_ptr->render_samplers[0]); + gl_state_bind_sampler(1, rctx_ptr->render_samplers[3]); + uniform_value[U_MLAA] = 1; + uniform_value[U_MLAA_SEARCH] = 2; + shaders_ft.set(SHADER_FT_MLAA); + draw_quad(render_post_width[0], render_post_height[0], + render_post_width_scale, render_post_height_scale, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); - temp_buffer.Bind(); - gl_state_active_bind_texture_2d(0, mlaa_buffer.GetColorTex()); - gl_state_active_bind_texture_2d(1, mlaa_area_texture); - gl_state_bind_sampler(0, rctx->render_samplers[0]); - gl_state_bind_sampler(1, rctx->render_samplers[3]); - uniform_value[U_MLAA] = 1; - uniform_value[U_MLAA_SEARCH] = 2; - shaders_ft.set(SHADER_FT_MLAA); - draw_quad(render_post_width[0], render_post_height[0], - render_post_width_scale, render_post_height_scale, - 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); - - RenderTexture& buf_texture = rctx->render_buffer; - buf_texture.Bind(); - gl_state_active_bind_texture_2d(0, taa_tex[2]->glid); - gl_state_active_bind_texture_2d(1, temp_buffer.GetColorTex()); - gl_state_bind_sampler(0, rctx->render_samplers[1]); - gl_state_bind_sampler(1, rctx->render_samplers[1]); - uniform_value[U_MLAA] = 2; - uniform_value[U_ALPHA_MASK] = ss_alpha_mask ? 1 : 0; - shaders_ft.set(SHADER_FT_MLAA); - draw_quad(render_post_width[0], render_post_height[0], - render_post_width_scale, render_post_height_scale, - 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); - uniform_value[U_ALPHA_MASK] = 0; - gl_state_active_bind_texture_2d(0, 0); - gl_state_active_bind_texture_2d(1, 0); - - fbo_blit(buf_texture.fbos[0], taa_buffer[2].fbos[0], - 0, 0, buf_texture.GetWidth(), buf_texture.GetHeight(), - 0, 0, taa_tex[2]->width, taa_tex[2]->height, GL_COLOR_BUFFER_BIT, GL_LINEAR); - gl_state_end_event(); + taa_buffer[destination].Bind(); + gl_state_active_bind_texture_2d(0, taa_tex[source]->glid); + gl_state_active_bind_texture_2d(1, temp_buffer.GetColorTex()); + gl_state_bind_sampler(0, rctx_ptr->render_samplers[1]); + gl_state_bind_sampler(1, rctx_ptr->render_samplers[1]); + uniform_value[U_MLAA] = 2; + uniform_value[U_ALPHA_MASK] = ss_alpha_mask ? 1 : 0; + shaders_ft.set(SHADER_FT_MLAA); + draw_quad(render_post_width[0], render_post_height[0], + render_post_width_scale, render_post_height_scale, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + uniform_value[U_ALPHA_MASK] = 0; + gl_state_active_bind_texture_2d(0, 0); + gl_state_active_bind_texture_2d(1, 0); + gl_state_end_event(); + } + else { + taa_buffer[destination].Bind(); + gl_state_active_bind_texture_2d(0, taa_tex[source]->glid); + gl_state_bind_sampler(0, rctx_ptr->render_samplers[1]); + uniform_value[U_REDUCE] = 0; + shaders_ft.set(SHADER_FT_REDUCE); + draw_quad(render_post_width[0], render_post_height[0], + render_post_width_scale, render_post_height_scale, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + } } void Render::apply_tone_map(texture* light_proj_tex, int32_t npr_param) { @@ -1816,6 +1889,23 @@ namespace rndr { rctx_ptr->gaussian_coef_ubo.WriteMemory(gaussian_coef); } + void Render::calc_taa_blend() { + float_t view_point_dist = vec3::distance(view_point, view_point_prev); + float_t interest_dist = vec3::distance(interest, interest_prev); + float_t dist = max_def(view_point_dist, interest_dist); + + if (!reset_exposure) { + if (dist < 0.0001f) + taa_blend = 0.5f; + else if (dist < 0.005f) + taa_blend = 0.75f; + else if (dist < 0.03f) + taa_blend = 0.875f; + else if (dist <= 0.05f && cam_blur) + taa_blend = 0.999f; + } + } + void Render::copy_to_frame_texture(GLuint pre_pp_tex, int32_t wight, int32_t height, GLuint post_pp_tex) { for (Render::FrameTexture& i : frame_texture) { if (!i.capture) @@ -1950,12 +2040,6 @@ namespace rndr { gl_state_set_blend_func(GL_ONE, GL_ZERO); } - void Render::frame_texture_reset_capture() { - for (Render::FrameTexture& i : frame_texture) - if (&i - frame_texture) - i.capture = false; - } - void Render::generate_mlaa_area_texture() { uint8_t* data = force_malloc(MLAA_SIDE_LEN * MLAA_SIDE_LEN * 2); if (!data) diff --git a/src/CRE/render.hpp b/src/CRE/render.hpp index 43bc1478..62fc5df4 100644 --- a/src/CRE/render.hpp +++ b/src/CRE/render.hpp @@ -258,15 +258,15 @@ namespace rndr { void update_res(bool set, int32_t base_downsample); private: - void apply_mlaa(int32_t ss_alpha_mask); + void apply_mlaa(int32_t destination, int32_t source, int32_t ss_alpha_mask); void apply_tone_map(texture* light_proj_tex, int32_t npr_param); void calc_exposure(camera* cam); void calc_gaussian_blur(float_t start, float_t step, int32_t kernel_size, float_t radius_scale, float_t intensity_scale); + void calc_taa_blend(); void copy_to_frame_texture(GLuint pre_pp_tex, int32_t wight, int32_t height, GLuint post_pp_tex); void draw_lens_ghost(); void downsample(); - void frame_texture_reset_capture(); void generate_mlaa_area_texture(); void get_blur(); void update_tone_map_lut(); diff --git a/src/CRE/render_context.cpp b/src/CRE/render_context.cpp index 7714288a..cc356bd9 100644 --- a/src/CRE/render_context.cpp +++ b/src/CRE/render_context.cpp @@ -401,6 +401,7 @@ sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_wi glGenVertexArrays(1, &common_vao); + camera_blur_ubo.Create(sizeof(camera_blur_shader_data)); contour_coef_ubo.Create(sizeof(contour_coef_shader_data)); contour_params_ubo.Create(sizeof(contour_params_shader_data)); filter_scene_ubo.Create(sizeof(filter_scene_shader_data)); @@ -569,6 +570,7 @@ render_context::~render_context() { filter_scene_ubo.Destroy(); contour_params_ubo.Destroy(); contour_coef_ubo.Destroy(); + camera_blur_ubo.Destroy(); if (common_vao) { glDeleteVertexArrays(1, &common_vao); diff --git a/src/CRE/render_context.hpp b/src/CRE/render_context.hpp index fa2ebea5..aa0e5ebe 100644 --- a/src/CRE/render_context.hpp +++ b/src/CRE/render_context.hpp @@ -95,6 +95,10 @@ struct light_proj { static bool set_mat(bool set_mat); }; +struct camera_blur_shader_data { + vec4 g_transform[4]; +}; + struct contour_coef_shader_data { vec4 g_contour; vec4 g_near_far; @@ -322,6 +326,7 @@ struct render_context { RenderTexture screen_buffer; RenderTexture shadow_buffer; + GL::UniformBuffer camera_blur_ubo; GL::UniformBuffer contour_coef_ubo; GL::UniformBuffer contour_params_ubo; GL::UniformBuffer filter_scene_ubo; diff --git a/src/ReDIVA/app.cpp b/src/ReDIVA/app.cpp index f8faf8ec..742ac014 100644 --- a/src/ReDIVA/app.cpp +++ b/src/ReDIVA/app.cpp @@ -600,6 +600,10 @@ static render_context* render_context_load() { stru_140EDA5B0.ss_alpha_mask, stru_140EDA5B0.screen_shot_4x == 1);*/ +#if BAKE_PNG || BAKE_VIDEO + rctx_ptr->render_manager->render->set_taa(false); +#endif + objset_info_storage_init(aft_obj_db); stage_param_data_storage_init(); pv_expression_file_storage_init(); diff --git a/src/ReDIVA/classes/graphics/post_process.cpp b/src/ReDIVA/classes/graphics/post_process.cpp index c27efde5..b725698d 100644 --- a/src/ReDIVA/classes/graphics/post_process.cpp +++ b/src/ReDIVA/classes/graphics/post_process.cpp @@ -66,6 +66,10 @@ void graphics_post_process_imgui(class_data* data) { ImGui::ColumnComboBox("MAG Filter", mag_filter_labels, rndr::Render::MAG_FILTER_MAX, (int32_t*)&rend->mag_filter, 0, false, &data->imgui_focus); + bool taa = !!rend->taa; + if (ImGui::CheckboxEnterKeyPressed("Temporal AA", &taa)) + rend->taa = taa ? 1 : 0; + bool mlaa = !!rend->mlaa; if (ImGui::CheckboxEnterKeyPressed("Morphological AA", &mlaa)) rend->mlaa = mlaa ? 1 : 0;