summaryrefslogtreecommitdiff
path: root/servers/visual/rasterizer_rd
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2020-01-26 20:09:40 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 12:16:01 +0100
commit2049dec79e0293f98d4c3f972f3a660ea5758983 (patch)
tree4562c4f50b5ca46ed4848d2915370d7cb7cb821b /servers/visual/rasterizer_rd
parentbed8980ca50cb6a197f37e3decaff963d5cedce1 (diff)
Added normalmap guided roughness mipmap generator, and a global roughness limiter.
Diffstat (limited to 'servers/visual/rasterizer_rd')
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp76
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.h18
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp44
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h6
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp25
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.h9
-rw-r--r--servers/visual/rasterizer_rd/shaders/SCsub1
-rw-r--r--servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl73
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_high_end.glsl8
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl2
10 files changed, 233 insertions, 29 deletions
diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
index 4f8e8c6944..b775401496 100644
--- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -664,7 +664,7 @@ void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer,
// Blur horizontal
ssao.blur_push_constant.edge_sharpness = p_edge_sharpness;
- ssao.blur_push_constant.filter_scale = p_blur + 1;
+ ssao.blur_push_constant.filter_scale = p_blur;
ssao.blur_push_constant.screen_size[0] = ssao.gather_push_constant.screen_size[0];
ssao.blur_push_constant.screen_size[1] = ssao.gather_push_constant.screen_size[1];
ssao.blur_push_constant.z_far = p_projection.get_z_far();
@@ -673,33 +673,35 @@ void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer,
ssao.blur_push_constant.axis[0] = 1;
ssao.blur_push_constant.axis[1] = 0;
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[p_half_size ? SSAO_BLUR_PASS_HALF : SSAO_BLUR_PASS]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0);
- if (p_half_size) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao2), 3);
+ if (p_blur != VS::ENV_SSAO_BLUR_DISABLED) {
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[p_half_size ? SSAO_BLUR_PASS_HALF : SSAO_BLUR_PASS]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0);
+ if (p_half_size) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 1);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao2), 3);
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
- /* THIRD PASS */
- // Blur vertical
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
- ssao.blur_push_constant.axis[0] = 0;
- ssao.blur_push_constant.axis[1] = 1;
+ /* THIRD PASS */
+ // Blur vertical
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao2), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 3);
+ ssao.blur_push_constant.axis[0] = 0;
+ ssao.blur_push_constant.axis[1] = 1;
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao2), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 3);
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ }
if (p_half_size) { //must upscale
/* FOURTH PASS */
@@ -727,6 +729,27 @@ void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer,
RD::get_singleton()->compute_list_end();
}
+void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
+
+ roughness_limiter.push_constant.screen_size[0] = p_size.x;
+ roughness_limiter.push_constant.screen_size[1] = p_size.y;
+ roughness_limiter.push_constant.curve = p_curve;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness_limiter.pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_normal), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_roughness), 1);
+
+ int x_groups = (p_size.x - 1) / 8 + 1;
+ int y_groups = (p_size.y - 1) / 8 + 1;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness_limiter.push_constant, sizeof(RoughnessLimiterPushConstant)); //not used but set anyway
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
RasterizerEffectsRD::RasterizerEffectsRD() {
{
@@ -905,6 +928,19 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
ERR_FAIL_COND(pipeline != SSAO_MAX);
}
+
+ {
+ // Initialize copier
+ Vector<String> shader_modes;
+ shader_modes.push_back("");
+
+ roughness_limiter.shader.initialize(shader_modes);
+
+ roughness_limiter.shader_version = roughness_limiter.shader.version_create();
+
+ roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0));
+ }
+
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
index 7a7d127e38..3495c9dcfe 100644
--- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
@@ -38,6 +38,7 @@
#include "servers/visual/rasterizer_rd/shaders/copy.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h"
+#include "servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/ssao.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/ssao_blur.glsl.gen.h"
@@ -339,6 +340,21 @@ class RasterizerEffectsRD {
RID pipelines[SSAO_MAX];
} ssao;
+ struct RoughnessLimiterPushConstant {
+ int32_t screen_size[2];
+ float curve;
+ uint32_t pad;
+ };
+
+ struct RoughnessLimiter {
+
+ RoughnessLimiterPushConstant push_constant;
+ RoughnessLimiterShaderRD shader;
+ RID shader_version;
+ RID pipeline;
+
+ } roughness_limiter;
+
RID default_sampler;
RID default_mipmap_sampler;
RID index_buffer;
@@ -407,6 +423,8 @@ public:
void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness);
+ void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
+
RasterizerEffectsRD();
~RasterizerEffectsRD();
};
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
index 29aef6916e..ad6d689b69 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
@@ -260,6 +260,8 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
blend_state_blend.attachments.push_back(blend_attachment);
RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2);
+ RD::PipelineColorBlendState blend_state_depth_normal = RD::PipelineColorBlendState::create_disabled(1);
+ RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(2);
//update pipelines
@@ -326,8 +328,10 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
blend_state = blend_state_opaque;
} else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
//none, leave empty
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
+ } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL) {
+ blend_state = blend_state_depth_normal;
+ } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_depth_normal;
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
@@ -941,7 +945,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
}
}
-void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar) {
+void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers) {
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
@@ -1031,7 +1035,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.use_reflection_cubemap = false;
}
- scene_state.ubo.ssao_enabled = environment_is_ssao_enabled(p_environment);
+ scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_environment);
scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_environment);
scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_environment);
@@ -1059,6 +1063,8 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.use_reflection_cubemap = false;
}
+ scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
+
RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
}
@@ -1723,9 +1729,15 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
screen_pixel_size.height = 1.0 / render_buffer->height;
opaque_framebuffer = render_buffer->color_fb;
+
if (p_environment.is_valid() && environment_is_ssr_enabled(p_environment)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
- } else if (p_environment.is_valid() && environment_is_ssao_enabled(p_environment)) {
+ } else if (screen_space_roughness_limiter_is_active()) {
+ depth_pass_mode = PASS_MODE_DEPTH_NORMAL;
+ //we need to allocate both these, if not allocated
+ _allocate_normal_texture(render_buffer);
+ _allocate_roughness_texture(render_buffer);
+ } else if (p_environment.is_valid() && (environment_is_ssao_enabled(p_environment) || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL;
}
@@ -1773,7 +1785,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
- _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far());
+ _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
cluster_builder.bake_cluster(); //bake to cluster
@@ -1855,12 +1867,18 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
_process_ssao(p_render_buffer, p_environment, render_buffer->normal_buffer, p_cam_projection);
}
+ if (p_render_buffer.is_valid() && screen_space_roughness_limiter_is_active()) {
+ storage->get_effects()->roughness_limit(render_buffer->normal_buffer, render_buffer->roughness_buffer, Size2(render_buffer->width, render_buffer->height), screen_space_roughness_limiter_get_curve());
+ }
+
if (p_render_buffer.is_valid()) {
//update the render buffers uniform set in case it changed
_update_render_buffers_uniform_set(p_render_buffer);
render_buffers_uniform_set = render_buffer->uniform_set;
}
+ _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid());
+
RENDER_TIMESTAMP("Render Opaque Pass");
{
@@ -1901,6 +1919,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
RENDER_TIMESTAMP("Render Transparent Pass");
+ _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
+
render_list.sort_by_reverse_depth_and_priority(true);
_fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false);
@@ -2275,6 +2295,18 @@ void RasterizerSceneHighEndRD::_render_buffers_uniform_set_changed(RID p_render_
_render_buffers_clear_uniform_set(rb);
}
+RID RasterizerSceneHighEndRD::_render_buffers_get_roughness_texture(RID p_render_buffers) {
+ RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers);
+
+ return rb->roughness_buffer;
+}
+
+RID RasterizerSceneHighEndRD::_render_buffers_get_normal_texture(RID p_render_buffers) {
+ RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers);
+
+ return rb->normal_buffer;
+}
+
void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_buffers) {
RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers);
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h
index e4349919f6..ef90d3a283 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h
@@ -229,6 +229,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
virtual void _base_uniforms_changed();
void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb);
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers);
+ virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers);
+ virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
void _update_render_base_uniform_set();
void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas);
@@ -347,7 +349,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
uint32_t ssao_enabled;
float ssao_light_affect;
float ssao_ao_affect;
- uint32_t pad_ssao;
+ uint32_t roughness_limiter_enabled;
float ao_color[4];
};
@@ -555,7 +557,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
PASS_MODE_DEPTH_MATERIAL,
};
- void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar);
+ void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false);
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
index 41acd05a30..a40211726c 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -2640,6 +2640,16 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
RID ao_buf = rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0];
effects->copy_to_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
}
+
+ if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER && _render_buffers_get_roughness_texture(p_render_buffers).is_valid()) {
+ Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ effects->copy_to_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ }
+
+ if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
+ Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ effects->copy_to_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize));
+ }
}
RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) {
@@ -2999,6 +3009,19 @@ void RasterizerSceneRD::set_time(double p_time, double p_step) {
time_step = p_step;
}
+void RasterizerSceneRD::screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) {
+ screen_space_roughness_limiter = p_enable;
+ screen_space_roughness_limiter_curve = p_curve;
+}
+
+bool RasterizerSceneRD::screen_space_roughness_limiter_is_active() const {
+ return screen_space_roughness_limiter;
+}
+
+float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const {
+ return screen_space_roughness_limiter_curve;
+}
+
RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
storage = p_storage;
@@ -3096,6 +3119,8 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape"))));
camera_effects_set_dof_blur_quality(VS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter"));
environment_set_ssao_quality(VS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"));
+ screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter");
+ screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter_curve");
}
RasterizerSceneRD::~RasterizerSceneRD() {
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
index cb917482cc..2b519ce2f5 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
@@ -64,6 +64,8 @@ protected:
virtual void _base_uniforms_changed() = 0;
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0;
+ virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers) = 0;
+ virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
@@ -575,6 +577,9 @@ private:
} ssao;
};
+ bool screen_space_roughness_limiter = false;
+ float screen_space_roughness_limiter_curve = 1.0;
+
mutable RID_Owner<RenderBuffers> render_buffers_owner;
void _free_render_buffer_data(RenderBuffers *rb);
@@ -923,6 +928,10 @@ public:
virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; }
_FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; }
+ virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve);
+ virtual bool screen_space_roughness_limiter_is_active() const;
+ virtual float screen_space_roughness_limiter_get_curve() const;
+
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub
index 98c14144e9..9a28ef062c 100644
--- a/servers/visual/rasterizer_rd/shaders/SCsub
+++ b/servers/visual/rasterizer_rd/shaders/SCsub
@@ -19,3 +19,4 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('ssao.glsl');
env.RD_GLSL('ssao_minify.glsl');
env.RD_GLSL('ssao_blur.glsl');
+ env.RD_GLSL('roughness_limiter.glsl');
diff --git a/servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl b/servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl
new file mode 100644
index 0000000000..5e0491c979
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl
@@ -0,0 +1,73 @@
+/* clang-format off */
+[compute]
+/* clang-format on */
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+
+layout(set = 0, binding = 0) uniform sampler2D source_normal;
+layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec2 screen_size;
+ float curve;
+ uint pad;
+} params;
+
+#define HALF_PI 1.5707963267948966
+
+void main() {
+
+ // Pixel being shaded
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThan(pos,params.screen_size))) { //too large, do nothing
+ return;
+ }
+
+ vec3 normal_accum = vec3(0.0);
+ float accum = 0.0;
+ for(int i=0;i<=1;i++) {
+ for(int j=0;j<=1;j++) {
+ normal_accum += normalize(texelFetch(source_normal,pos+ivec2(i,j),0).xyz * 2.0 - 1.0);
+ accum+=1.0;
+ }
+ }
+
+ normal_accum /= accum;
+
+ float r = length(normal_accum);
+
+ float limit;
+
+ if (r < 1.0) {
+ float threshold = 0.4;
+
+/*
+ //Formula from Filament, does not make sense to me.
+
+ float r2 = r * r;
+ float kappa = (3.0f * r - r * r2) / (1.0f - r2);
+ float variance = 0.25f / kappa;
+ limit = sqrt(min(2.0f * variance, threshold * threshold));
+//*/
+/*
+ //Formula based on probability distribution graph
+
+ float width = acos(max(0.0,r)); // convert to angle (width)
+ float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness
+ limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold
+//*/
+
+ limit = min(sqrt(pow(acos(max(0.0,r)) / HALF_PI ,params.curve)), threshold); //convert to perceptual roughness and apply threshold
+
+ //limit = 0.5;
+ } else {
+ limit = 0.0;
+ }
+
+ imageStore(dest_roughness,pos,vec4(limit));
+}
diff --git a/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl
index 66ce4b466f..8aee680c1e 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl
@@ -1272,6 +1272,7 @@ FRAGMENT_SHADER_CODE
#endif // !USE_SHADOW_TO_OPACITY
+
#if defined(NORMALMAP_USED)
normalmap.xy = normalmap.xy * 2.0 - 1.0;
@@ -1310,6 +1311,13 @@ FRAGMENT_SHADER_CODE
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
+ if (scene_data.roughness_limiter_enabled) {
+ float limit = texelFetch(sampler2D(roughness_buffer, material_samplers[SAMPLER_NEAREST_CLAMP]),ivec2(gl_FragCoord.xy),0).r;
+ roughness = max(roughness,limit);
+
+ }
+
+
if (scene_data.use_reflection_cubemap) {
vec3 ref_vec = reflect(-view, normal);
diff --git a/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl
index 5504d0fc2f..384e51bbce 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl
@@ -63,7 +63,7 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
bool ssao_enabled;
float ssao_light_affect;
float ssao_ao_affect;
- uint pad_ssao;
+ bool roughness_limiter_enabled;
vec4 ao_color;