You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-22 15:06:45 +00:00
Overhaul screen space reflections.
This commit is contained in:
@@ -737,8 +737,17 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
|
||||
scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment);
|
||||
uint32_t ss_flags = 0;
|
||||
if (p_opaque_render_buffers) {
|
||||
ss_flags |= environment_get_ssao_enabled(p_render_data->environment) ? 1 : 0;
|
||||
ss_flags |= environment_get_ssil_enabled(p_render_data->environment) ? 2 : 0;
|
||||
ss_flags |= environment_get_ssao_enabled(p_render_data->environment) ? (1 << 0) : 0;
|
||||
ss_flags |= environment_get_ssil_enabled(p_render_data->environment) ? (1 << 1) : 0;
|
||||
ss_flags |= environment_get_ssr_enabled(p_render_data->environment) ? (1 << 2) : 0;
|
||||
|
||||
if (rd.is_valid()) {
|
||||
Ref<RenderBufferDataForwardClustered> rb_data;
|
||||
if (rd->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
|
||||
rb_data = rd->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
|
||||
ss_flags |= (rb_data.is_valid() && !rb_data->ss_effects_data.ssr.half_size) ? (1 << 3) : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
scene_state.ubo.ss_effects_flags = ss_flags;
|
||||
} else {
|
||||
@@ -1407,42 +1416,50 @@ void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_bu
|
||||
Projection correction;
|
||||
correction.set_depth_correction(true);
|
||||
Projection projection = correction * p_projections[v];
|
||||
Projection last_frame_projection = rb_data->ss_effects_data.last_frame_projections[v] * Projection(rb_data->ss_effects_data.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse();
|
||||
Projection last_frame_projection = rb_data->ss_effects_data.ssil_last_frame_projections[v] * Projection(rb_data->ss_effects_data.ssil_last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse();
|
||||
|
||||
ss_effects->screen_space_indirect_lighting(p_render_buffers, rb_data->ss_effects_data.ssil, v, p_normal_buffers[v], p_projections[v], last_frame_projection, settings);
|
||||
|
||||
rb_data->ss_effects_data.last_frame_projections[v] = projection;
|
||||
rb_data->ss_effects_data.ssil_last_frame_projections[v] = projection;
|
||||
}
|
||||
rb_data->ss_effects_data.last_frame_transform = transform;
|
||||
rb_data->ss_effects_data.ssil_last_frame_transform = transform;
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers) {
|
||||
void RenderForwardClustered::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_slices, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_transform) {
|
||||
ERR_FAIL_NULL(ss_effects);
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
|
||||
if (p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_LAST_FRAME)) {
|
||||
Size2i size = p_render_buffers->get_internal_size();
|
||||
uint32_t mipmaps = p_render_buffers->get_texture_format(RB_SCOPE_SSIL, RB_LAST_FRAME).mipmaps;
|
||||
for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
|
||||
RID source = p_render_buffers->get_internal_texture(v);
|
||||
RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, v, 0);
|
||||
copy_effects->copy_to_rect(source, dest, Rect2i(0, 0, size.x, size.y));
|
||||
Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
|
||||
ERR_FAIL_COND(rb_data.is_null());
|
||||
|
||||
int width = size.x;
|
||||
int height = size.y;
|
||||
for (uint32_t m = 1; m < mipmaps; m++) {
|
||||
width = MAX(1, width >> 1);
|
||||
height = MAX(1, height >> 1);
|
||||
RENDER_TIMESTAMP("Process SSR");
|
||||
|
||||
source = dest;
|
||||
dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, v, m);
|
||||
ss_effects->ssr_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssr, _render_buffers_get_color_format());
|
||||
|
||||
copy_effects->make_mipmap(source, dest, Size2i(width, height));
|
||||
}
|
||||
}
|
||||
Projection reprojections[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
|
||||
for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
|
||||
Projection correction;
|
||||
correction.set_depth_correction(true);
|
||||
|
||||
Projection projection = correction * p_projections[v];
|
||||
reprojections[v] = rb_data->ss_effects_data.ssr_last_frame_projections[v] * Projection(rb_data->ss_effects_data.ssr_last_frame_transform.affine_inverse()) * Projection(p_transform) * projection.inverse();
|
||||
|
||||
rb_data->ss_effects_data.ssr_last_frame_projections[v] = projection;
|
||||
}
|
||||
rb_data->ss_effects_data.ssr_last_frame_transform = p_transform;
|
||||
|
||||
ss_effects->screen_space_reflection(p_render_buffers, rb_data->ss_effects_data.ssr, p_normal_slices, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), p_projections, reprojections, p_eye_offsets, *copy_effects);
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer) {
|
||||
void RenderForwardClustered::_copy_framebuffer_to_ss_effects(Ref<RenderSceneBuffersRD> p_render_buffers, bool p_use_ssil, bool p_use_ssr) {
|
||||
ERR_FAIL_NULL(ss_effects);
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
|
||||
ss_effects->copy_internal_texture_to_last_frame(p_render_buffers, *copy_effects);
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_ssr, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer) {
|
||||
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
|
||||
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
@@ -1540,6 +1557,10 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
|
||||
// This should allow most of the processing to happen in parallel even if we're doing
|
||||
// drawcalls per eye/view. It will all sync up at the barrier.
|
||||
|
||||
if (p_use_ssil || p_use_ssr) {
|
||||
ss_effects->allocate_last_frame_buffer(rb, p_use_ssil, p_use_ssr);
|
||||
}
|
||||
|
||||
if (p_use_ssao || p_use_ssil) {
|
||||
RENDER_TIMESTAMP("Prepare Depth for SSAO/SSIL");
|
||||
// Convert our depth buffer data to linear data in
|
||||
@@ -1555,6 +1576,10 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
|
||||
_process_ssil(rb, p_render_data->environment, p_normal_roughness_slices, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform);
|
||||
}
|
||||
}
|
||||
|
||||
if (p_use_ssr) {
|
||||
_process_ssr(rb, p_render_data->environment, p_normal_roughness_slices, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform);
|
||||
}
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("Pre Opaque Render");
|
||||
@@ -1597,33 +1622,6 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
|
||||
}
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) {
|
||||
ERR_FAIL_NULL(ss_effects);
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
|
||||
Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
|
||||
ERR_FAIL_COND(rb_data.is_null());
|
||||
|
||||
Size2i internal_size = p_render_buffers->get_internal_size();
|
||||
bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8;
|
||||
uint32_t view_count = p_render_buffers->get_view_count();
|
||||
|
||||
if (!can_use_effects) {
|
||||
//just copy
|
||||
copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), RID(), view_count);
|
||||
return;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(p_environment.is_null());
|
||||
ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment));
|
||||
|
||||
ss_effects->ssr_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssr, _render_buffers_get_color_format());
|
||||
ss_effects->screen_space_reflection(p_render_buffers, rb_data->ss_effects_data.ssr, p_normal_slices, p_metallic_slices, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), p_projections, p_eye_offsets);
|
||||
|
||||
RID output = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_OUTPUT);
|
||||
copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), output, view_count);
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera) {
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
|
||||
@@ -1819,9 +1817,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
}
|
||||
if (environment_get_ssr_enabled(p_render_data->environment)) {
|
||||
if (!p_render_data->transparent_bg) {
|
||||
using_separate_specular = true;
|
||||
using_ssr = true;
|
||||
color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
|
||||
} else {
|
||||
WARN_PRINT_ONCE("Screen-space reflections are not supported in viewports with a transparent background. Disabling SSR in transparent viewport.");
|
||||
}
|
||||
@@ -2122,7 +2118,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
normal_roughness_views[v] = rb_data->get_normal_roughness(v);
|
||||
}
|
||||
}
|
||||
_pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, normal_roughness_views, rb_data.is_valid() && rb_data->has_voxelgi() ? rb_data->get_voxelgi() : RID());
|
||||
_pre_opaque_render(p_render_data, using_ssao, using_ssil, using_ssr, using_sdfgi || using_voxelgi, normal_roughness_views, rb_data.is_valid() && rb_data->has_voxelgi() ? rb_data->get_voxelgi() : RID());
|
||||
|
||||
RENDER_TIMESTAMP("Render Opaque Pass");
|
||||
|
||||
@@ -2279,16 +2275,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
if (using_ssr) {
|
||||
RENDER_TIMESTAMP("Screen-Space Reflections");
|
||||
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
|
||||
RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) {
|
||||
specular_views[v] = rb_data->get_specular(v);
|
||||
}
|
||||
_process_ssr(rb, color_only_framebuffer, normal_roughness_views, rb_data->get_specular(), specular_views, p_render_data->environment, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, !use_msaa);
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
} else {
|
||||
{
|
||||
//just mix specular back
|
||||
RENDER_TIMESTAMP("Merge Specular");
|
||||
copy_effects->merge_specular(color_only_framebuffer, rb_data->get_specular(), !use_msaa ? RID() : rb->get_internal_texture(), RID(), p_render_data->scene_data->view_count);
|
||||
@@ -2394,18 +2381,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Copy Framebuffer for SSIL/SSR");
|
||||
if (using_ssil || using_ssr) {
|
||||
RENDER_TIMESTAMP("Copy Final Framebuffer (SSIL/SSR)");
|
||||
_copy_framebuffer_to_ss_effects(rb, using_ssil, using_ssr);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
{
|
||||
RENDER_TIMESTAMP("Process Post Transparent Compositor Effects");
|
||||
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_TRANSPARENT, p_render_data);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Copy Framebuffer for SSIL");
|
||||
if (using_ssil) {
|
||||
RENDER_TIMESTAMP("Copy Final Framebuffer (SSIL)");
|
||||
_copy_framebuffer_to_ssil(rb);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
if (rb_data.is_valid() && (using_upscaling || using_taa)) {
|
||||
if (scale_type == SCALE_FSR2) {
|
||||
rb_data->ensure_fsr2(fsr2_effect);
|
||||
@@ -3577,6 +3564,38 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
|
||||
u.append_id(texture);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 35;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
|
||||
RID ssr;
|
||||
if (rb_data.is_valid()) {
|
||||
if (rb_data->ss_effects_data.ssr.half_size) {
|
||||
if (rb->has_texture(RB_SCOPE_SSR, RB_FINAL)) {
|
||||
ssr = rb->get_texture(RB_SCOPE_SSR, RB_FINAL);
|
||||
}
|
||||
} else {
|
||||
if (rb->has_texture(RB_SCOPE_SSR, RB_SSR)) {
|
||||
ssr = rb->get_texture(RB_SCOPE_SSR, RB_SSR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RID texture = ssr.is_valid() ? ssr : texture_storage->texture_rd_get_default(is_multiview ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
|
||||
u.append_id(texture);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 36;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
|
||||
RID ssr_mip_level = (rb_data.is_valid() && !rb_data->ss_effects_data.ssr.half_size && rb->has_texture(RB_SCOPE_SSR, RB_MIP_LEVEL)) ? rb->get_texture(RB_SCOPE_SSR, RB_MIP_LEVEL) : RID();
|
||||
RID texture = ssr_mip_level.is_valid() ? ssr_mip_level : texture_storage->texture_rd_get_default(is_multiview ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
|
||||
u.append_id(texture);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET, uniforms);
|
||||
}
|
||||
@@ -3814,10 +3833,13 @@ void RenderForwardClustered::environment_set_ssil_quality(RS::EnvironmentSSILQua
|
||||
ss_effects->ssil_set_quality(p_quality, p_half_size, p_adaptive_target, p_blur_passes, p_fadeout_from, p_fadeout_to);
|
||||
}
|
||||
|
||||
void RenderForwardClustered::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
|
||||
void RenderForwardClustered::environment_set_ssr_half_size(bool p_half_size) {
|
||||
ERR_FAIL_NULL(ss_effects);
|
||||
ERR_FAIL_COND(p_quality < RS::EnvironmentSSRRoughnessQuality::ENV_SSR_ROUGHNESS_QUALITY_DISABLED || p_quality > RS::EnvironmentSSRRoughnessQuality::ENV_SSR_ROUGHNESS_QUALITY_HIGH);
|
||||
ss_effects->ssr_set_roughness_quality(p_quality);
|
||||
ss_effects->ssr_set_half_size(p_half_size);
|
||||
}
|
||||
|
||||
void RenderForwardClustered::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
|
||||
WARN_PRINT_ONCE("environment_set_ssr_roughness_quality has been deprecated and no longer does anything.");
|
||||
}
|
||||
|
||||
void RenderForwardClustered::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
|
||||
|
||||
@@ -102,8 +102,11 @@ public:
|
||||
ClusterBuilderRD *cluster_builder = nullptr;
|
||||
|
||||
struct SSEffectsData {
|
||||
Projection last_frame_projections[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
Transform3D last_frame_transform;
|
||||
Projection ssil_last_frame_projections[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
Transform3D ssil_last_frame_transform;
|
||||
|
||||
Projection ssr_last_frame_projections[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
Transform3D ssr_last_frame_transform;
|
||||
|
||||
RendererRD::SSEffects::SSILRenderBuffers ssil;
|
||||
RendererRD::SSEffects::SSAORenderBuffers ssao;
|
||||
@@ -758,9 +761,9 @@ private:
|
||||
/* Render Scene */
|
||||
void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections);
|
||||
void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections, const Transform3D &p_transform);
|
||||
void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers);
|
||||
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer);
|
||||
void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
|
||||
void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_slices, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_transform);
|
||||
void _copy_framebuffer_to_ss_effects(Ref<RenderSceneBuffersRD> p_render_buffers, bool p_use_ssil, bool p_use_ssr);
|
||||
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_ssr, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer);
|
||||
void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera);
|
||||
|
||||
/* Debug */
|
||||
@@ -774,6 +777,7 @@ protected:
|
||||
|
||||
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
|
||||
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
|
||||
virtual void environment_set_ssr_half_size(bool p_half_size) override;
|
||||
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override;
|
||||
|
||||
Reference in New Issue
Block a user