diff options
Diffstat (limited to 'servers/rendering')
16 files changed, 621 insertions, 263 deletions
diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index cf0afe6097..b28ec8e50f 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -106,7 +106,8 @@ public: virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; - virtual void shadow_filter_set(RS::ShadowFilter p_filter) = 0; + virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0; + virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0; struct InstanceBase; @@ -263,7 +264,7 @@ public: virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa) = 0; virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; virtual bool screen_space_roughness_limiter_is_active() const = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp index 973b422b14..c34eb4cd79 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp @@ -676,6 +676,10 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, tonemap.push_constant.use_color_correction = p_settings.use_color_correction; + tonemap.push_constant.use_fxaa = p_settings.use_fxaa; + tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x; + tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y; + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h index 64e16a58a6..aec381d193 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h @@ -170,6 +170,10 @@ class RasterizerEffectsRD { float exposure; float white; float auto_exposure_grey; + + float pixel_size[2]; + uint32_t use_fxaa; + uint32_t pad; }; /* tonemap actually writes to a framebuffer, which is @@ -595,6 +599,9 @@ public: bool use_color_correction = false; RID color_correction_texture; + + bool use_fxaa = false; + Vector2i texture_size; }; void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index ec05c9e964..8ed58c0ef5 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -77,6 +77,13 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_arra } } +static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) { + + for (int i = 0; i < 128; i++) { + p_array[i] = p_kernel[i]; + } +} + /* SCENE SHADER */ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { //compile @@ -535,46 +542,100 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() { tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = width; tf.height = height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + if (msaa != RS::VIEWPORT_MSAA_DISABLED) { + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } else { + tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } specular = RD::get_singleton()->texture_create(tf, RD::TextureView()); - { - Vector<RID> fb; - fb.push_back(color); - fb.push_back(specular); - fb.push_back(depth); + if (msaa == RS::VIEWPORT_MSAA_DISABLED) { - color_specular_fb = RD::get_singleton()->framebuffer_create(fb); - } - { - Vector<RID> fb; - fb.push_back(specular); + { + Vector<RID> fb; + fb.push_back(color); + fb.push_back(specular); + fb.push_back(depth); + + color_specular_fb = RD::get_singleton()->framebuffer_create(fb); + } + { + Vector<RID> fb; + fb.push_back(specular); + + specular_only_fb = RD::get_singleton()->framebuffer_create(fb); + } - specular_only_fb = RD::get_singleton()->framebuffer_create(fb); + } else { + + tf.samples = texture_samples; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + { + Vector<RID> fb; + fb.push_back(color_msaa); + fb.push_back(specular_msaa); + fb.push_back(depth_msaa); + + color_specular_fb = RD::get_singleton()->framebuffer_create(fb); + } + { + Vector<RID> fb; + fb.push_back(specular_msaa); + + specular_only_fb = RD::get_singleton()->framebuffer_create(fb); + } } } } void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { + if (color_msaa.is_valid()) { + RD::get_singleton()->free(color_msaa); + color_msaa = RID(); + } + + if (depth_msaa.is_valid()) { + RD::get_singleton()->free(depth_msaa); + depth_msaa = RID(); + } + if (specular.is_valid()) { + if (specular_msaa.is_valid()) { + RD::get_singleton()->free(specular_msaa); + specular_msaa = RID(); + } RD::get_singleton()->free(specular); specular = RID(); } + color = RID(); + depth = RID(); color_specular_fb = RID(); specular_only_fb = RID(); color_fb = RID(); + depth_fb = RID(); if (normal_buffer.is_valid()) { RD::get_singleton()->free(normal_buffer); + if (normal_buffer_msaa.is_valid()) { + RD::get_singleton()->free(normal_buffer_msaa); + normal_buffer_msaa = RID(); + } normal_buffer = RID(); depth_normal_fb = RID(); } if (roughness_buffer.is_valid()) { RD::get_singleton()->free(roughness_buffer); + if (roughness_buffer_msaa.is_valid()) { + RD::get_singleton()->free(roughness_buffer_msaa); + roughness_buffer_msaa = RID(); + } roughness_buffer = RID(); depth_normal_roughness_fb = RID(); } @@ -583,24 +644,69 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { clear(); + msaa = p_msaa; + width = p_width; height = p_height; color = p_color_buffer; depth = p_depth_buffer; - { - Vector<RID> fb; - fb.push_back(p_color_buffer); - fb.push_back(depth); + if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) { - color_fb = RD::get_singleton()->framebuffer_create(fb); - } - { - Vector<RID> fb; - fb.push_back(depth); + { + Vector<RID> fb; + fb.push_back(p_color_buffer); + fb.push_back(depth); + + color_fb = RD::get_singleton()->framebuffer_create(fb); + } + { + Vector<RID> fb; + fb.push_back(depth); + + depth_fb = RD::get_singleton()->framebuffer_create(fb); + } + } else { + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = p_width; + tf.height = p_height; + tf.type = RD::TEXTURE_TYPE_2D; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + + RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { + RD::TEXTURE_SAMPLES_1, + RD::TEXTURE_SAMPLES_2, + RD::TEXTURE_SAMPLES_4, + RD::TEXTURE_SAMPLES_8, + RD::TEXTURE_SAMPLES_16 + }; + + texture_samples = ts[p_msaa]; + tf.samples = texture_samples; + + color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + + depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + { + Vector<RID> fb; + fb.push_back(color_msaa); + fb.push_back(depth_msaa); + + color_fb = RD::get_singleton()->framebuffer_create(fb); + } + { + Vector<RID> fb; + fb.push_back(depth_msaa); - depth_fb = RD::get_singleton()->framebuffer_create(fb); + depth_fb = RD::get_singleton()->framebuffer_create(fb); + } } } @@ -613,13 +719,31 @@ void RasterizerSceneHighEndRD::_allocate_normal_texture(RenderBufferDataHighEnd tf.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; tf.width = rb->width; tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + + if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } else { + tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } rb->normal_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - Vector<RID> fb; - fb.push_back(rb->depth); - fb.push_back(rb->normal_buffer); - rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); + + if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) { + Vector<RID> fb; + fb.push_back(rb->depth); + fb.push_back(rb->normal_buffer); + rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); + } else { + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + tf.samples = rb->texture_samples; + rb->normal_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector<RID> fb; + fb.push_back(rb->depth_msaa); + fb.push_back(rb->normal_buffer_msaa); + rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); + } _render_buffers_clear_uniform_set(rb); } @@ -638,12 +762,32 @@ void RasterizerSceneHighEndRD::_allocate_roughness_texture(RenderBufferDataHighE tf.height = rb->height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } else { + tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } + rb->roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - Vector<RID> fb; - fb.push_back(rb->depth); - fb.push_back(rb->normal_buffer); - fb.push_back(rb->roughness_buffer); - rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); + + if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) { + + Vector<RID> fb; + fb.push_back(rb->depth); + fb.push_back(rb->normal_buffer); + fb.push_back(rb->roughness_buffer); + rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); + } else { + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + tf.samples = rb->texture_samples; + rb->roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector<RID> fb; + fb.push_back(rb->depth_msaa); + fb.push_back(rb->normal_buffer_msaa); + fb.push_back(rb->roughness_buffer_msaa); + rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); + } _render_buffers_clear_uniform_set(rb); } @@ -962,10 +1106,18 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer scene_state.ubo.z_far = p_zfar; scene_state.ubo.z_near = p_znear; - scene_state.ubo.shadow_filter_mode = shadow_filter_get(); scene_state.ubo.pancake_shadows = p_pancake_shadows; - scene_state.ubo.shadow_blocker_count = 16; + + store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); + store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); + store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); + store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); + + scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get(); + scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get(); + scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get(); + scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get(); scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x; scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y; @@ -1585,6 +1737,8 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep light_data.fade_to = -light_data.shadow_split_offsets[3]; + light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR); + float softshadow_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); if (softshadow_angle > 0.0) { // I know tan(0) is 0, but let's not risk it with numerical precision. @@ -1593,6 +1747,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig light_data.softshadow_angle = Math::tan(Math::deg2rad(softshadow_angle)); } else { light_data.softshadow_angle = 0; + light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF } } @@ -1703,6 +1858,8 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig light_data.atlas_rect[2] = rect.size.width; light_data.atlas_rect[3] = rect.size.height; + light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR); + if (type == RS::LIGHT_OMNI) { light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another @@ -1715,6 +1872,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig light_data.soft_shadow_size = size; } else { light_data.soft_shadow_size = 0.0; + light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF } } else if (type == RS::LIGHT_SPOT) { @@ -1738,6 +1896,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; } else { light_data.soft_shadow_size = 0.0; + light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF } } } else { @@ -1777,27 +1936,6 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor render_pass++; //fill up ubo -#if 0 - storage->info.render.object_count += p_cull_count; - - Environment *env = environment_owner.getornull(p_environment); - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); - - if (shadow_atlas && shadow_atlas->size) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); - scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size; - scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size; - } - - if (reflection_atlas && reflection_atlas->size) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); - } -#endif RENDER_TIMESTAMP("Setup 3D Scene"); @@ -1837,6 +1975,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor bool using_ssr = false; if (render_buffer) { + screen_pixel_size.width = 1.0 / render_buffer->width; screen_pixel_size.height = 1.0 / render_buffer->height; screen_size.x = render_buffer->width; @@ -1998,9 +2137,23 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor if (depth_pre_pass) { //depth pre pass RENDER_TIMESTAMP("Render Depth Pre-Pass"); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, using_ssao ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear); + bool finish_depth = using_ssao; + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear); _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID()); RD::get_singleton()->draw_list_end(); + + if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { + if (finish_depth) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth, true); + } + + if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->normal_buffer_msaa, render_buffer->normal_buffer, true); + if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->roughness_buffer_msaa, render_buffer->roughness_buffer, true); + } + } + } } if (using_ssao) { @@ -2080,6 +2233,19 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor _draw_sky(can_continue_color, can_continue_depth, opaque_framebuffer, p_environment, projection, p_cam_transform); } + if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { + + RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color, true); + if (using_separate_specular) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular, true); + } + } + + if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { + + RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth, true); + } + if (using_separate_specular) { if (using_sss) { @@ -2089,11 +2255,11 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor if (using_ssr) { RENDER_TIMESTAMP("Screen Space Reflection"); - _process_ssr(p_render_buffer, render_buffer->color_fb, render_buffer->normal_buffer, render_buffer->roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_environment, p_cam_projection, true); + _process_ssr(p_render_buffer, render_buffer->color_fb, render_buffer->normal_buffer, render_buffer->roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_environment, p_cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, RID(), RID()); + storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); } } @@ -2111,77 +2277,12 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor RD::get_singleton()->draw_list_end(); } - //_render_list -#if 0 - if (state.directional_light_count == 0) { - directional_light = nullptr; - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, false, shadow_atlas != nullptr); - } else { - for (int i = 0; i < state.directional_light_count; i++) { - directional_light = directional_lights[i]; - _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != nullptr && shadow_atlas->size > 0); - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, i > 0, shadow_atlas != nullptr); - } - } -#endif - -#if 0 - _post_process(env, p_cam_projection); - // Needed only for debugging - /* if (shadow_atlas && storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if (storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color); - //glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1)); - } - - if (reflection_atlas && storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if (directional_shadow.fbo) { + if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); + RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color, true); } - - if ( env_radiance_tex) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, env_radiance_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - }*/ - //disable all stuff -#endif } + void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake) { RENDER_TIMESTAMP("Setup Rendering Shadow"); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h index b4f5d25afd..6ae4720306 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -198,11 +198,22 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { struct RenderBufferDataHighEnd : public RenderBufferData { //for rendering, may be MSAAd + RID color; RID depth; RID specular; RID normal_buffer; RID roughness_buffer; + + RS::ViewportMSAA msaa; + RD::TextureSamples texture_samples; + + RID color_msaa; + RID depth_msaa; + RID specular_msaa; + RID normal_buffer_msaa; + RID roughness_buffer_msaa; + RID depth_fb; RID depth_normal_fb; RID depth_normal_roughness_fb; @@ -265,8 +276,9 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float shadow_normal_bias; float transmittance_bias; float soft_shadow_size; + float soft_shadow_scale; uint32_t mask; - uint32_t pad[3]; + uint32_t pad[2]; }; struct DirectionalLightData { @@ -278,7 +290,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float specular; uint32_t mask; float softshadow_angle; - uint32_t pad[1]; + float soft_shadow_scale; uint32_t blend_splits; uint32_t shadow_enabled; float fade_from; @@ -350,10 +362,17 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float reflection_multiplier; uint32_t pancake_shadows; - uint32_t shadow_filter_mode; + uint32_t pad; + + float directional_penumbra_shadow_kernel[128]; //32 vec4s + float directional_soft_shadow_kernel[128]; + float penumbra_shadow_kernel[128]; + float soft_shadow_kernel[128]; - uint32_t shadow_blocker_count; - uint32_t shadow_pad[3]; + uint32_t directional_penumbra_shadow_samples; + uint32_t directional_soft_shadow_samples; + uint32_t penumbra_shadow_samples; + uint32_t soft_shadow_samples; float ambient_light_color_energy[4]; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index 2426eb7ebe..2ec09b2528 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -36,6 +36,18 @@ uint64_t RasterizerSceneRD::auto_exposure_counter = 2; +void get_vogel_disk(float *r_kernel, int p_sample_count) { + const float golden_angle = 2.4; + + for (int i = 0; i < p_sample_count; i++) { + float r = Math::sqrt(float(i) + 0.5) / Math::sqrt(float(p_sample_count)); + float theta = float(i) * golden_angle; + + r_kernel[i * 4] = Math::cos(theta) * r; + r_kernel[i * 4 + 1] = Math::sin(theta) * r; + } +} + void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) { rd.layers.clear(); @@ -3439,6 +3451,12 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); } + if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { + tonemap.use_fxaa = true; + } + + tonemap.texture_size = Vector2i(rb->width, rb->height); + if (env) { tonemap.tonemap_mode = env->tone_mapper; tonemap.white = env->white; @@ -3517,13 +3535,14 @@ RID RasterizerSceneRD::render_buffers_get_ao_texture(RID p_render_buffers) { return rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; } -void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa) { +void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); rb->width = p_width; rb->height = p_height; rb->render_target = p_render_target; rb->msaa = p_msaa; + rb->screen_space_aa = p_screen_space_aa; _free_render_buffer_data(rb); { @@ -3531,7 +3550,12 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = rb->width; tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } else { + tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); } @@ -3542,6 +3566,9 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren tf.width = p_width; tf.height = p_height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); } @@ -3563,8 +3590,86 @@ void RasterizerSceneRD::sub_surface_scattering_set_scale(float p_scale, float p_ sss_depth_scale = p_depth_scale; } -void RasterizerSceneRD::shadow_filter_set(RS::ShadowFilter p_filter) { - shadow_filter = p_filter; +void RasterizerSceneRD::shadows_quality_set(RS::ShadowQuality p_quality) { + + ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); + + if (shadows_quality != p_quality) { + shadows_quality = p_quality; + + switch (shadows_quality) { + case RS::SHADOW_QUALITY_HARD: { + penumbra_shadow_samples = 4; + soft_shadow_samples = 1; + shadows_quality_radius = 1.0; + } break; + case RS::SHADOW_QUALITY_SOFT_LOW: { + penumbra_shadow_samples = 8; + soft_shadow_samples = 4; + shadows_quality_radius = 2.0; + } break; + case RS::SHADOW_QUALITY_SOFT_MEDIUM: { + penumbra_shadow_samples = 12; + soft_shadow_samples = 8; + shadows_quality_radius = 2.0; + } break; + case RS::SHADOW_QUALITY_SOFT_HIGH: { + penumbra_shadow_samples = 24; + soft_shadow_samples = 16; + shadows_quality_radius = 3.0; + } break; + case RS::SHADOW_QUALITY_SOFT_ULTRA: { + penumbra_shadow_samples = 32; + soft_shadow_samples = 32; + shadows_quality_radius = 4.0; + } break; + case RS::SHADOW_QUALITY_MAX: + break; + } + get_vogel_disk(penumbra_shadow_kernel, penumbra_shadow_samples); + get_vogel_disk(soft_shadow_kernel, soft_shadow_samples); + } +} + +void RasterizerSceneRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) { + + ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); + + if (directional_shadow_quality != p_quality) { + directional_shadow_quality = p_quality; + + switch (directional_shadow_quality) { + case RS::SHADOW_QUALITY_HARD: { + directional_penumbra_shadow_samples = 4; + directional_soft_shadow_samples = 1; + directional_shadow_quality_radius = 1.0; + } break; + case RS::SHADOW_QUALITY_SOFT_LOW: { + directional_penumbra_shadow_samples = 8; + directional_soft_shadow_samples = 4; + directional_shadow_quality_radius = 2.0; + } break; + case RS::SHADOW_QUALITY_SOFT_MEDIUM: { + directional_penumbra_shadow_samples = 12; + directional_soft_shadow_samples = 8; + directional_shadow_quality_radius = 2.0; + } break; + case RS::SHADOW_QUALITY_SOFT_HIGH: { + directional_penumbra_shadow_samples = 24; + directional_soft_shadow_samples = 16; + directional_shadow_quality_radius = 3.0; + } break; + case RS::SHADOW_QUALITY_SOFT_ULTRA: { + directional_penumbra_shadow_samples = 32; + directional_soft_shadow_samples = 32; + directional_shadow_quality_radius = 4.0; + } break; + case RS::SHADOW_QUALITY_MAX: + break; + } + get_vogel_disk(directional_penumbra_shadow_kernel, directional_penumbra_shadow_samples); + get_vogel_disk(directional_soft_shadow_kernel, directional_soft_shadow_samples); + } } int RasterizerSceneRD::get_roughness_layers() const { @@ -4125,17 +4230,22 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS); } - camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape")))); - camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter")); + camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_shape")))); + camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter")); environment_set_ssao_quality(RS::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"); + screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter"); + screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_curve"); glow_bicubic_upscale = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0; ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality"))); sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality"))); sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale"); sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale"); - shadow_filter = RS::ShadowFilter(int(GLOBAL_GET("rendering/quality/shadows/filter_mode"))); + directional_penumbra_shadow_kernel = memnew_arr(float, 128); + directional_soft_shadow_kernel = memnew_arr(float, 128); + penumbra_shadow_kernel = memnew_arr(float, 128); + soft_shadow_kernel = memnew_arr(float, 128); + shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/shadows/soft_shadow_quality")))); + directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/directional_shadow/soft_shadow_quality")))); } RasterizerSceneRD::~RasterizerSceneRD() { @@ -4164,4 +4274,8 @@ RasterizerSceneRD::~RasterizerSceneRD() { memdelete_arr(sky_scene_state.last_frame_directional_lights); storage->free(sky_shader.default_shader); storage->free(sky_shader.default_material); + memdelete_arr(directional_penumbra_shadow_kernel); + memdelete_arr(directional_soft_shadow_kernel); + memdelete_arr(penumbra_shadow_kernel); + memdelete_arr(soft_shadow_kernel); } diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h index 21c3c08d16..859b654214 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -527,7 +527,19 @@ private: bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); - RS::ShadowFilter shadow_filter = RS::SHADOW_FILTER_NONE; + RS::ShadowQuality shadows_quality = RS::SHADOW_QUALITY_MAX; //So it always updates when first set + RS::ShadowQuality directional_shadow_quality = RS::SHADOW_QUALITY_MAX; + float shadows_quality_radius = 1.0; + float directional_shadow_quality_radius = 1.0; + + float *directional_penumbra_shadow_kernel; + float *directional_soft_shadow_kernel; + float *penumbra_shadow_kernel; + float *soft_shadow_kernel; + int directional_penumbra_shadow_samples = 0; + int directional_soft_shadow_samples = 0; + int penumbra_shadow_samples = 0; + int soft_shadow_samples = 0; /* DIRECTIONAL SHADOW */ @@ -716,6 +728,8 @@ private: RenderBufferData *data = nullptr; int width = 0, height = 0; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; + RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + RID render_target; uint64_t auto_exposure_version = 1; @@ -1149,7 +1163,7 @@ public: GIProbeQuality gi_probe_get_quality() const; RID render_buffers_create(); - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa); + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa); RID render_buffers_get_ao_texture(RID p_render_buffers); RID render_buffers_get_back_buffer_texture(RID p_render_buffers); @@ -1175,8 +1189,22 @@ public: RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const; virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale); - virtual void shadow_filter_set(RS::ShadowFilter p_filter); - _FORCE_INLINE_ RS::ShadowFilter shadow_filter_get() const { return shadow_filter; } + virtual void shadows_quality_set(RS::ShadowQuality p_quality); + virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality); + _FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; } + _FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; } + _FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; } + _FORCE_INLINE_ float directional_shadow_quality_radius_get() const { return directional_shadow_quality_radius; } + + _FORCE_INLINE_ float *directional_penumbra_shadow_kernel_get() { return directional_penumbra_shadow_kernel; } + _FORCE_INLINE_ float *directional_soft_shadow_kernel_get() { return directional_soft_shadow_kernel; } + _FORCE_INLINE_ float *penumbra_shadow_kernel_get() { return penumbra_shadow_kernel; } + _FORCE_INLINE_ float *soft_shadow_kernel_get() { return soft_shadow_kernel; } + + _FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const { return directional_penumbra_shadow_samples; } + _FORCE_INLINE_ int directional_soft_shadow_samples_get() const { return directional_soft_shadow_samples; } + _FORCE_INLINE_ int penumbra_shadow_samples_get() const { return penumbra_shadow_samples; } + _FORCE_INLINE_ int soft_shadow_samples_get() const { return soft_shadow_samples; } int get_roughness_layers() const; bool is_using_radiance_cubemap_array() const; diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index 00dfdc612a..6ac1f7c95e 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -4637,14 +4637,14 @@ RasterizerStorageRD::RasterizerStorageRD() { sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy"); + sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/texture_filters/max_anisotropy"); } break; case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy"); + sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/texture_filters/max_anisotropy"); } break; default: { diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl index 70ce8d61e4..ea9d50c11d 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl @@ -686,61 +686,63 @@ LIGHT_SHADER_CODE #ifndef USE_NO_SHADOWS -const vec2 shadow_poisson_disk[16] = vec2[]( - vec2(-0.94201624, -0.39906216), - vec2(0.94558609, -0.76890725), - vec2(-0.094184101, -0.92938870), - vec2(0.34495938, 0.29387760), - vec2(-0.91588581, 0.45771432), - vec2(-0.81544232, -0.87912464), - vec2(-0.38277543, 0.27676845), - vec2(0.97484398, 0.75648379), - vec2(0.44323325, -0.97511554), - vec2(0.53742981, -0.47373420), - vec2(-0.26496911, -0.41893023), - vec2(0.79197514, 0.19090188), - vec2(-0.24188840, 0.99706507), - vec2(-0.81409955, 0.91437590), - vec2(0.19984126, 0.78641367), - vec2(0.14383161, -0.14100790)); - -float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { +// Produces cheap but low-quality white noise, nothing special +float quick_hash(vec2 pos) { + return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237); +} + +float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { vec2 pos = coord.xy; float depth = coord.z; - switch (scene_data.shadow_filter_mode) { - case SHADOW_MODE_NO_FILTER: { - return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); - }; - case SHADOW_MODE_PCF5: { - float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); - return avg * (1.0 / 5.0); - }; - case SHADOW_MODE_PCF13: { - - float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0)); - return avg * (1.0 / 13.0); - }; + //if only one sample is taken, take it from the center + if (scene_data.directional_soft_shadow_samples == 1) { + return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); + } + + mat2 disk_rotation; + { + float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float sr = sin(r); + float cr = cos(r); + disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); + } + + float avg = 0.0; + + for (uint i = 0; i < scene_data.directional_soft_shadow_samples; i++) { + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0)); } - return 0; + return avg * (1.0 / float(scene_data.directional_soft_shadow_samples)); +} + +float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { + + vec2 pos = coord.xy; + float depth = coord.z; + + //if only one sample is taken, take it from the center + if (scene_data.soft_shadow_samples == 1) { + return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); + } + + mat2 disk_rotation; + { + float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float sr = sin(r); + float cr = cos(r); + disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); + } + + float avg = 0.0; + + for (uint i = 0; i < scene_data.soft_shadow_samples; i++) { + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0)); + } + + return avg * (1.0 / float(scene_data.soft_shadow_samples)); } float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) { @@ -749,17 +751,17 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex float blocker_count = 0.0; float blocker_average = 0.0; - mat2 poisson_rotate; - + mat2 disk_rotation; { - float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123)); + float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); - poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr)); + disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); } - for (uint i = 0; i < scene_data.shadow_blocker_count; i++) { - vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * tex_scale; + for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) { + + vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r; if (d < pssm_coord.z) { blocker_average += d; @@ -775,12 +777,12 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex tex_scale *= penumbra; float s = 0.0; - for (uint i = 0; i < scene_data.shadow_blocker_count; i++) { - vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * tex_scale; + for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) { + vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0)); } - return s / float(scene_data.shadow_blocker_count); + return s / float(scene_data.directional_penumbra_shadow_samples); } else { //no blockers found, so no shadow @@ -862,13 +864,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a float blocker_count = 0.0; float blocker_average = 0.0; - mat2 poisson_rotate; - + mat2 disk_rotation; { - float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123)); + float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); - poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr)); + disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); } vec3 normal = normalize(splane.xyz); @@ -877,12 +878,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a vec3 bitangent = normalize(cross(tangent, normal)); float z_norm = shadow_len * lights.data[idx].inv_radius; - tangent *= lights.data[idx].soft_shadow_size; - bitangent *= lights.data[idx].soft_shadow_size; + tangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale; + bitangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale; + + for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { + + vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy; - for (uint i = 0; i < scene_data.shadow_blocker_count; i++) { - vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]); - vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.y; + vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y; pos = normalize(pos); vec4 uv_rect = lights.data[idx].atlas_rect; @@ -919,10 +922,10 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a z_norm -= lights.data[idx].inv_radius * lights.data[idx].shadow_bias; shadow = 0.0; - for (uint i = 0; i < scene_data.shadow_blocker_count; i++) { + for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { - vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]); - vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.y; + vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy; + vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y; pos = normalize(pos); vec4 uv_rect = lights.data[idx].atlas_rect; @@ -943,7 +946,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0)); } - shadow /= float(scene_data.shadow_blocker_count); + shadow /= float(scene_data.penumbra_shadow_samples); } else { //no blockers found, so no shadow @@ -970,12 +973,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a splane.z = (shadow_len - lights.data[idx].shadow_bias) * lights.data[idx].inv_radius; splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; splane.w = 1.0; //needed? i think it should be 1 already - shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane); + shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane); } #ifdef LIGHT_TRANSMITTANCE_USED { + vec4 clamp_rect = lights.data[idx].atlas_rect; + //redo shadowmapping, but shrink the model a bit to avoid arctifacts splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0)); @@ -1120,18 +1125,18 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a float blocker_count = 0.0; float blocker_average = 0.0; - mat2 poisson_rotate; - + mat2 disk_rotation; { - float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123)); + float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); - poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr)); + disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); } - float uv_size = lights.data[idx].soft_shadow_size * z_norm; - for (uint i = 0; i < scene_data.shadow_blocker_count; i++) { - vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size; + float uv_size = lights.data[idx].soft_shadow_size * z_norm * lights.data[idx].soft_shadow_scale; + for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { + + vec2 suv = splane.xy + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size; suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw); float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r; if (d < z_norm) { @@ -1148,13 +1153,13 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a uv_size *= penumbra; shadow = 0.0; - for (uint i = 0; i < scene_data.shadow_blocker_count; i++) { - vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size; + for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { + vec2 suv = splane.xy + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size; suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw); shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0)); } - shadow /= float(scene_data.shadow_blocker_count); + shadow /= float(scene_data.penumbra_shadow_samples); } else { //no blockers found, so no shadow @@ -1164,7 +1169,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a } else { //hard shadow splane.z = z_norm; - shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane); + shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane); } shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow); @@ -1888,9 +1893,9 @@ FRAGMENT_SHADER_CODE float range_begin = directional_lights.data[i].shadow_range_begin.x; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); } else { - shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); } shadow_color = directional_lights.data[i].shadow_color1.rgb; @@ -1922,9 +1927,9 @@ FRAGMENT_SHADER_CODE float range_begin = directional_lights.data[i].shadow_range_begin.y; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); } else { - shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); } shadow_color = directional_lights.data[i].shadow_color2.rgb; @@ -1955,9 +1960,9 @@ FRAGMENT_SHADER_CODE float range_begin = directional_lights.data[i].shadow_range_begin.z; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); } else { - shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); } shadow_color = directional_lights.data[i].shadow_color3.rgb; @@ -1989,9 +1994,9 @@ FRAGMENT_SHADER_CODE float range_begin = directional_lights.data[i].shadow_range_begin.w; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); } else { - shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); } shadow_color = directional_lights.data[i].shadow_color4.rgb; @@ -2028,9 +2033,9 @@ FRAGMENT_SHADER_CODE float range_begin = directional_lights.data[i].shadow_range_begin.y; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale); + shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); } else { - shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); } pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); @@ -2046,9 +2051,9 @@ FRAGMENT_SHADER_CODE float range_begin = directional_lights.data[i].shadow_range_begin.z; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale); + shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); } else { - shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); } pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); @@ -2064,9 +2069,9 @@ FRAGMENT_SHADER_CODE float range_begin = directional_lights.data[i].shadow_range_begin.w; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale); + shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); } else { - shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); } pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl index 59f326bc9b..db11e4b005 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl @@ -22,10 +22,6 @@ draw_call; #define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10 #define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11 -#define SHADOW_MODE_NO_FILTER 0 -#define SHADOW_MODE_PCF5 1 -#define SHADOW_MODE_PCF13 2 - layout(set = 0, binding = 1) uniform sampler material_samplers[12]; layout(set = 0, binding = 2) uniform sampler shadow_sampler; @@ -45,12 +41,18 @@ layout(set = 0, binding = 3, std140) uniform SceneData { float reflection_multiplier; // one normally, zero when rendering reflections bool pancake_shadows; - uint shadow_filter_mode; + uint pad; + + //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted + vec4 directional_penumbra_shadow_kernel[32]; + vec4 directional_soft_shadow_kernel[32]; + vec4 penumbra_shadow_kernel[32]; + vec4 soft_shadow_kernel[32]; - uint shadow_blocker_count; - uint shadow_pad0; - uint shadow_pad1; - uint shadow_pad2; + uint directional_penumbra_shadow_samples; + uint directional_soft_shadow_samples; + uint penumbra_shadow_samples; + uint soft_shadow_samples; vec4 ambient_light_color_energy; @@ -157,8 +159,9 @@ struct LightData { //this structure needs to be as packed as possible float shadow_normal_bias; float transmittance_bias; float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle + float soft_shadow_scale; // scales the shadow kernel for blurrier shadows uint mask; - uint pad[3]; + uint pad[2]; }; layout(set = 0, binding = 5, std430) buffer Lights { @@ -191,7 +194,7 @@ struct DirectionalLightData { float specular; uint mask; float softshadow_angle; - uint pad1; + float soft_shadow_scale; bool blend_splits; bool shadow_enabled; float fade_from; diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl index 524ca5e2ea..a142d263e2 100644 --- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl +++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl @@ -48,6 +48,10 @@ layout(push_constant, binding = 1, std430) uniform Params { float exposure; float white; float auto_exposure_grey; + + vec2 pixel_size; + bool use_fxaa; + uint pad; } params; @@ -255,16 +259,63 @@ vec3 apply_color_correction(vec3 color, sampler3D correction_tex) { return texture(correction_tex, color).rgb; } +vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { + + const float FXAA_REDUCE_MIN = (1.0 / 128.0); + const float FXAA_REDUCE_MUL = (1.0 / 8.0); + const float FXAA_SPAN_MAX = 8.0; + + vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure; + vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure; + vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure; + vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure; + vec3 rgbM = color; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), + FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * + params.pixel_size; + + vec3 rgbA = 0.5 * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz * exposure + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz) * exposure; + vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz * exposure + + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz * exposure); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + return rgbA; + else + return rgbB; +} + void main() { vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb; // Exposure + float exposure = params.exposure; + if (params.use_auto_exposure) { - color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey; + exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey); } - color *= params.exposure; + color *= exposure; // Early Tonemap & SRGB Conversion @@ -274,6 +325,9 @@ void main() { color.rgb = mix(color.rgb, glow, params.glow_intensity); } + if (params.use_fxaa) { + color = do_fxaa(color, exposure, uv_interp); + } color = apply_tonemapping(color, params.white); color = linear_to_srgb(color); // regular linear -> SRGB conversion diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 393bbc9f2f..63aa8dde1c 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -428,6 +428,7 @@ public: virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false) = 0; virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw = false) = 0; + virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, bool p_sync_with_draw = false) = 0; /*********************/ /**** FRAMEBUFFER ****/ diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index 7ea7d0a4dc..8eb4dea9e6 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -489,6 +489,7 @@ public: BIND2(viewport_set_shadow_atlas_size, RID, int) BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) BIND2(viewport_set_msaa, RID, ViewportMSAA) + BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo) BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw) @@ -558,7 +559,8 @@ public: BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) BIND3(camera_effects_set_custom_exposure, RID, bool, float) - BIND1(shadow_filter_set, ShadowFilter) + BIND1(shadows_quality_set, ShadowQuality); + BIND1(directional_shadow_quality_set, ShadowQuality); /* SCENARIO API */ diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp index 152e79f3e0..6fb8f6ca63 100644 --- a/servers/rendering/rendering_server_viewport.cpp +++ b/servers/rendering/rendering_server_viewport.cpp @@ -119,7 +119,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) { //wants to draw 3D but there is no render buffer, create p_viewport->render_buffers = RSG::scene_render->render_buffers_create(); - RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa); + RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa); } RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor); @@ -506,7 +506,7 @@ void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int RSG::scene_render->free(viewport->render_buffers); viewport->render_buffers = RID(); } else { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa); + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa); } } } @@ -736,7 +736,20 @@ void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA } viewport->msaa = p_msaa; if (viewport->render_buffers.is_valid()) { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa); + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa); + } +} + +void RenderingServerViewport::viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (viewport->screen_space_aa == p_mode) { + return; + } + viewport->screen_space_aa = p_mode; + if (viewport->render_buffers.is_valid()) { + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode); } } diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h index 910d1ef5e9..fcba7886c5 100644 --- a/servers/rendering/rendering_server_viewport.h +++ b/servers/rendering/rendering_server_viewport.h @@ -59,6 +59,7 @@ public: RID render_buffers; RS::ViewportMSAA msaa; + RS::ViewportScreenSpaceAA screen_space_aa; DisplayServer::WindowID viewport_to_screen; Rect2 viewport_to_screen_rect; @@ -130,6 +131,8 @@ public: debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; msaa = RS::VIEWPORT_MSAA_DISABLED; + screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) { render_info[i] = 0; } @@ -206,6 +209,7 @@ public: void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv); void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa); + void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode); virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info); virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw); diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index 834cf82d79..c7d563c07c 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -403,6 +403,7 @@ public: FUNC2(viewport_set_shadow_atlas_size, RID, int) FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) FUNC2(viewport_set_msaa, RID, ViewportMSAA) + FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) //this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) { @@ -475,7 +476,8 @@ public: FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) FUNC3(camera_effects_set_custom_exposure, RID, bool, float) - FUNC1(shadow_filter_set, ShadowFilter) + FUNC1(shadows_quality_set, ShadowQuality); + FUNC1(directional_shadow_quality_set, ShadowQuality); FUNCRID(scenario) |