diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
43 files changed, 748 insertions, 686 deletions
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index f5b6be4795..236eb5e596 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -759,7 +759,7 @@ void EffectsRD::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuff RD::get_singleton()->draw_list_end(); } -void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip) { +void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { CopyToDPPushConstant push_constant; push_constant.screen_rect[0] = p_rect.position.x; push_constant.screen_rect[1] = p_rect.position.y; @@ -767,7 +767,9 @@ void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffe push_constant.screen_rect[3] = p_rect.size.height; push_constant.z_far = p_z_far; push_constant.z_near = p_z_near; - push_constant.z_flip = p_dp_flip; + push_constant.texel_size[0] = 1.0f / p_dst_size.x; + push_constant.texel_size[1] = 1.0f / p_dst_size.y; + push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); @@ -810,6 +812,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone tonemap.push_constant.exposure = p_settings.exposure; tonemap.push_constant.white = p_settings.white; tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey; + tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier; tonemap.push_constant.use_color_correction = p_settings.use_color_correction; @@ -862,6 +865,7 @@ void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_colo tonemap.push_constant.use_color_correction = p_settings.use_color_correction; tonemap.push_constant.use_debanding = p_settings.use_debanding; + tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier; RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass())); RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0); @@ -1914,7 +1918,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } } - { // Initialize copy + if (!prefer_raster_effects) { // Initialize copy Vector<String> copy_modes; copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n"); @@ -2113,7 +2117,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } } - { + if (!prefer_raster_effects) { // Initialize ssao RD::SamplerState sampler; @@ -2169,10 +2173,8 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { for (int pass = 0; pass < 4; pass++) { for (int subPass = 0; subPass < sub_pass_count; subPass++) { int a = pass; - int b = subPass; - int spmap[5]{ 0, 1, 4, 3, 2 }; - b = spmap[subPass]; + int b = spmap[subPass]; float ca, sa; float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f; @@ -2257,7 +2259,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { ERR_FAIL_COND(pipeline != SSAO_MAX); } - { + if (!prefer_raster_effects) { // Initialize roughness limiter Vector<String> shader_modes; shader_modes.push_back(""); @@ -2355,7 +2357,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } } - { + if (!prefer_raster_effects) { Vector<String> specular_modes; specular_modes.push_back("\n#define MODE_MERGE\n"); specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); @@ -2391,72 +2393,74 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } } - { - Vector<String> ssr_modes; - ssr_modes.push_back("\n"); - ssr_modes.push_back("\n#define MODE_ROUGH\n"); + if (!prefer_raster_effects) { + { + Vector<String> ssr_modes; + ssr_modes.push_back("\n"); + ssr_modes.push_back("\n#define MODE_ROUGH\n"); - ssr.shader.initialize(ssr_modes); + ssr.shader.initialize(ssr_modes); - ssr.shader_version = ssr.shader.version_create(); + ssr.shader_version = ssr.shader.version_create(); - for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) { - ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i)); + for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) { + ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i)); + } } - } - { - Vector<String> ssr_filter_modes; - ssr_filter_modes.push_back("\n"); - ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); + { + Vector<String> ssr_filter_modes; + ssr_filter_modes.push_back("\n"); + ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); - ssr_filter.shader.initialize(ssr_filter_modes); + ssr_filter.shader.initialize(ssr_filter_modes); - ssr_filter.shader_version = ssr_filter.shader.version_create(); + ssr_filter.shader_version = ssr_filter.shader.version_create(); - for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) { - ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i)); + for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) { + ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i)); + } } - } - { - Vector<String> ssr_scale_modes; - ssr_scale_modes.push_back("\n"); + { + Vector<String> ssr_scale_modes; + ssr_scale_modes.push_back("\n"); - ssr_scale.shader.initialize(ssr_scale_modes); + ssr_scale.shader.initialize(ssr_scale_modes); - ssr_scale.shader_version = ssr_scale.shader.version_create(); + ssr_scale.shader_version = ssr_scale.shader.version_create(); - ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0)); - } + ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0)); + } - { - Vector<String> sss_modes; - sss_modes.push_back("\n#define USE_11_SAMPLES\n"); - sss_modes.push_back("\n#define USE_17_SAMPLES\n"); - sss_modes.push_back("\n#define USE_25_SAMPLES\n"); + { + Vector<String> sss_modes; + sss_modes.push_back("\n#define USE_11_SAMPLES\n"); + sss_modes.push_back("\n#define USE_17_SAMPLES\n"); + sss_modes.push_back("\n#define USE_25_SAMPLES\n"); - sss.shader.initialize(sss_modes); + sss.shader.initialize(sss_modes); - sss.shader_version = sss.shader.version_create(); + sss.shader_version = sss.shader.version_create(); - for (int i = 0; i < sss_modes.size(); i++) { - sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i)); + for (int i = 0; i < sss_modes.size(); i++) { + sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i)); + } } - } - { - Vector<String> resolve_modes; - resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); - resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n"); - resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n"); + { + Vector<String> resolve_modes; + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n"); - resolve.shader.initialize(resolve_modes); + resolve.shader.initialize(resolve_modes); - resolve.shader_version = resolve.shader.version_create(); + resolve.shader_version = resolve.shader.version_create(); - for (int i = 0; i < RESOLVE_MODE_MAX; i++) { - resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i)); + for (int i = 0; i < RESOLVE_MODE_MAX; i++) { + resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i)); + } } } @@ -2522,10 +2526,6 @@ EffectsRD::~EffectsRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency RD::get_singleton()->free(filter.coefficient_buffer); - RD::get_singleton()->free(ssao.mirror_sampler); - RD::get_singleton()->free(ssao.gather_constants_buffer); - RD::get_singleton()->free(ssao.importance_map_load_counter); - if (prefer_raster_effects) { blur_raster.shader.version_free(blur_raster.shader_version); bokeh.raster_shader.version_free(blur_raster.shader_version); @@ -2540,21 +2540,27 @@ EffectsRD::~EffectsRD() { cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version); filter.compute_shader.version_free(filter.shader_version); } - copy.shader.version_free(copy.shader_version); + if (!prefer_raster_effects) { + copy.shader.version_free(copy.shader_version); + resolve.shader.version_free(resolve.shader_version); + specular_merge.shader.version_free(specular_merge.shader_version); + ssao.blur_shader.version_free(ssao.blur_shader_version); + ssao.gather_shader.version_free(ssao.gather_shader_version); + ssao.downsample_shader.version_free(ssao.downsample_shader_version); + ssao.interleave_shader.version_free(ssao.interleave_shader_version); + ssao.importance_map_shader.version_free(ssao.importance_map_shader_version); + roughness_limiter.shader.version_free(roughness_limiter.shader_version); + ssr.shader.version_free(ssr.shader_version); + ssr_filter.shader.version_free(ssr_filter.shader_version); + ssr_scale.shader.version_free(ssr_scale.shader_version); + sss.shader.version_free(sss.shader_version); + + RD::get_singleton()->free(ssao.mirror_sampler); + RD::get_singleton()->free(ssao.gather_constants_buffer); + RD::get_singleton()->free(ssao.importance_map_load_counter); + } copy_to_fb.shader.version_free(copy_to_fb.shader_version); cube_to_dp.shader.version_free(cube_to_dp.shader_version); - resolve.shader.version_free(resolve.shader_version); - roughness_limiter.shader.version_free(roughness_limiter.shader_version); sort.shader.version_free(sort.shader_version); - specular_merge.shader.version_free(specular_merge.shader_version); - ssao.blur_shader.version_free(ssao.blur_shader_version); - ssao.gather_shader.version_free(ssao.gather_shader_version); - ssao.downsample_shader.version_free(ssao.downsample_shader_version); - ssao.interleave_shader.version_free(ssao.interleave_shader_version); - ssao.importance_map_shader.version_free(ssao.importance_map_shader_version); - ssr.shader.version_free(ssr.shader_version); - ssr_filter.shader.version_free(ssr_filter.shader_version); - ssr_scale.shader.version_free(ssr_scale.shader_version); - sss.shader.version_free(sss.shader_version); tonemap.shader.version_free(tonemap.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 0c9b2efb7f..0db0919dbc 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -255,7 +255,7 @@ private: float exposure; // 4 - 84 float white; // 4 - 88 float auto_exposure_grey; // 4 - 92 - uint32_t pad2; // 4 - 96 + float luminance_multiplier; // 4 - 96 float pixel_size[2]; // 8 - 104 uint32_t use_fxaa; // 4 - 108 @@ -308,7 +308,7 @@ private: float exposure_adjust; float min_luminance; float max_luminance; - float pad[1]; + uint32_t pad1; }; struct LuminanceReduceFragment { @@ -321,8 +321,7 @@ private: struct CopyToDPPushConstant { float z_far; float z_near; - uint32_t z_flip; - uint32_t pad; + float texel_size[2]; float screen_rect[4]; }; @@ -770,7 +769,7 @@ public: void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size); - void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip); + void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); @@ -819,6 +818,7 @@ public: bool use_auto_exposure = false; float auto_exposure_grey = 0.5; RID exposure_texture; + float luminance_multiplier = 1.0; bool use_bcs = false; float brightness = 1.0; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 5a0ad97c7c..1b730567d9 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -484,7 +484,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p if (material_uniform_set != prev_material_uniform_set) { // Update uniform set. - if (RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set. + if (material_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set. RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET); } @@ -3062,7 +3062,7 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) : defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; } defines += "\n#define SDFGI_OCT_SIZE " + itos(gi.sdfgi_get_lightprobe_octahedron_size()) + "\n"; - defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(get_max_directional_lights()) + "\n"; + defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n"; { //lightmaps diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index be18a73989..d0f02b44cb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -601,10 +601,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.usage_defines["UV2"] = "#define UV2_USED\n"; actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n"; actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n"; - actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n"; - actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n"; - actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n"; - actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; @@ -683,6 +683,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin default_shader = storage->shader_allocate(); storage->shader_initialize(default_shader); storage->shader_set_code(default_shader, R"( +// Default 3D material shader (clustered). + shader_type spatial; void vertex() { @@ -712,6 +714,8 @@ void fragment() { storage->shader_initialize(overdraw_material_shader); // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished. storage->shader_set_code(overdraw_material_shader, R"( +// 3D editor Overdraw debug draw mode shader (clustered). + shader_type spatial; render_mode blend_add, unshaded; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 96b3cdadd4..276a44bc27 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -86,12 +86,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() { void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) { clear(); - bool is_half_resolution = false; // Set this once we support this feature. - msaa = p_msaa; + Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer); + width = p_width; height = p_height; + bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height); view_count = p_view_count; color = p_color_buffer; @@ -124,7 +125,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b passes.push_back(pass); color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); - if (!is_half_resolution) { + if (!is_scaled) { // - add blit to 2D pass fb.push_back(p_target_buffer); // 2 - target buffer @@ -211,7 +212,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count); } - if (!is_half_resolution) { + if (!is_scaled) { // - add blit to 2D pass fb.push_back(p_target_buffer); // 3 - target buffer RD::FramebufferPass blit_pass; @@ -271,6 +272,12 @@ bool RenderForwardMobile::free(RID p_rid) { /* Render functions */ +float RenderForwardMobile::_render_buffers_get_luminance_multiplier() { + // On mobile renderer we need to multiply source colors by 2 due to using a UNORM buffer + // and multiplying by the output color during 3D rendering by 0.5 + return 2.0; +} + RD::DataFormat RenderForwardMobile::_render_buffers_get_color_format() { // Using 32bit buffers enables AFBC on mobile devices which should have a definite performance improvement (MALI G710 and newer support this on 64bit RTs) return RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; @@ -491,7 +498,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color bool using_subpass_transparent = true; bool using_subpass_post_process = true; - bool is_half_resolution = false; // Set this once we support this feature. bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out @@ -512,7 +518,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color screen_size.x = render_buffer->width; screen_size.y = render_buffer->height; - if (is_half_resolution) { + if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) { // can't do blit subpass using_subpass_post_process = false; } else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) { @@ -631,7 +637,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RID sky_rid = env->sky; if (sky_rid.is_valid()) { - sky.update(env, projection, p_render_data->cam_transform, time); + sky.update(env, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid @@ -750,9 +756,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color CameraMatrix correction; correction.set_depth_correction(true); CameraMatrix projection = correction * p_render_data->cam_projection; - sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time); + sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); } else { - sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); + sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); } RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass @@ -1976,7 +1982,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr if (material_uniform_set != prev_material_uniform_set) { // Update uniform set. - if (RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set. + if (material_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_uniform_set)) { // Material may not have a uniform set. RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET); } @@ -2630,7 +2636,7 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) : defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; } // defines += "\n#define SDFGI_OCT_SIZE " + itos(gi.sdfgi_get_lightprobe_octahedron_size()) + "\n"; - defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(get_max_directional_lights()) + "\n"; + defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n"; { //lightmaps diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 764d8e80df..38f80c5347 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -202,6 +202,7 @@ protected: } }; + virtual float _render_buffers_get_luminance_multiplier() override; virtual RD::DataFormat _render_buffers_get_color_format() override; virtual bool _render_buffers_can_be_storage() override; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 735014a2ec..cd314d8c56 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -593,10 +593,10 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.usage_defines["UV2"] = "#define UV2_USED\n"; actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n"; actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n"; - actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n"; - actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n"; - actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n"; - actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; @@ -665,6 +665,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.global_buffer_array_variable = "global_variables.data"; actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; + actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture + compiler.initialize(actions); } @@ -673,6 +675,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p default_shader = storage->shader_allocate(); storage->shader_initialize(default_shader); storage->shader_set_code(default_shader, R"( +// Default 3D material shader (mobile). + shader_type spatial; void vertex() { @@ -701,6 +705,8 @@ void fragment() { storage->shader_initialize(overdraw_material_shader); // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished. storage->shader_set_code(overdraw_material_shader, R"( +// 3D editor Overdraw debug draw mode shader (mobile). + shader_type spatial; render_mode blend_add, unshaded; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index bd06f54816..3c66fadbe9 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -541,6 +541,14 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend src_rect = Rect2(0, 0, 1, 1); } + if (rect->flags & CANVAS_RECT_MSDF) { + push_constant.flags |= FLAGS_USE_MSDF; + push_constant.msdf[0] = rect->px_range; // Pixel range. + push_constant.msdf[1] = rect->outline; // Outline size. + push_constant.msdf[2] = 0.f; // Reserved. + push_constant.msdf[3] = 0.f; // Reserved. + } + push_constant.modulation[0] = rect->modulate.r * base_color.r; push_constant.modulation[1] = rect->modulate.g * base_color.g; push_constant.modulation[2] = rect->modulate.b * base_color.b; @@ -1094,7 +1102,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) { pipeline_variants = &material_data->shader_data->pipeline_variants; // Update uniform set. - if (RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set. + if (material_data->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set. RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET); } } else { @@ -2577,6 +2585,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { storage->shader_initialize(default_canvas_group_shader); storage->shader_set_code(default_canvas_group_shader, R"( +// Default CanvasGroup shader. + shader_type canvas_item; void fragment() { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 7c4f62832c..ec7d7e2854 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -84,8 +84,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender { FLAGS_LIGHT_COUNT_SHIFT = 20, FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26), - FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27) + FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), + FLAGS_USE_MSDF = (1 << 28), }; enum { @@ -388,7 +389,10 @@ class RendererCanvasRenderRD : public RendererCanvasRender { //rect struct { float modulation[4]; - float ninepatch_margins[4]; + union { + float msdf[4]; + float ninepatch_margins[4]; + }; float dst_rect[4]; float src_rect[4]; float pad[2]; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 02d548bf13..c53c202bab 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -46,6 +46,8 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID RID rd_texture = storage->texture_get_rd_texture(texture); ERR_CONTINUE(rd_texture.is_null()); + // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in. + if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) { Vector<RD::Uniform> uniforms; RD::Uniform u; @@ -65,10 +67,14 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0); - blit.push_constant.rect[0] = p_render_targets[i].rect.position.x / screen_size.width; - blit.push_constant.rect[1] = p_render_targets[i].rect.position.y / screen_size.height; - blit.push_constant.rect[2] = p_render_targets[i].rect.size.width / screen_size.width; - blit.push_constant.rect[3] = p_render_targets[i].rect.size.height / screen_size.height; + blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x; + blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y; + blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width; + blit.push_constant.src_rect[3] = p_render_targets[i].src_rect.size.height; + blit.push_constant.dst_rect[0] = p_render_targets[i].dst_rect.position.x / screen_size.width; + blit.push_constant.dst_rect[1] = p_render_targets[i].dst_rect.position.y / screen_size.height; + blit.push_constant.dst_rect[2] = p_render_targets[i].dst_rect.size.width / screen_size.width; + blit.push_constant.dst_rect[3] = p_render_targets[i].dst_rect.size.height / screen_size.height; blit.push_constant.layer = p_render_targets[i].multi_view.layer; blit.push_constant.eye_center[0] = p_render_targets[i].lens_distortion.eye_center.x; blit.push_constant.eye_center[1] = p_render_targets[i].lens_distortion.eye_center.y; @@ -203,10 +209,14 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0); - blit.push_constant.rect[0] = screenrect.position.x; - blit.push_constant.rect[1] = screenrect.position.y; - blit.push_constant.rect[2] = screenrect.size.width; - blit.push_constant.rect[3] = screenrect.size.height; + blit.push_constant.src_rect[0] = 0.0; + blit.push_constant.src_rect[1] = 0.0; + blit.push_constant.src_rect[2] = 1.0; + blit.push_constant.src_rect[3] = 1.0; + blit.push_constant.dst_rect[0] = screenrect.position.x; + blit.push_constant.dst_rect[1] = screenrect.position.y; + blit.push_constant.dst_rect[2] = screenrect.size.width; + blit.push_constant.dst_rect[3] = screenrect.size.height; blit.push_constant.layer = 0; blit.push_constant.eye_center[0] = 0; blit.push_constant.eye_center[1] = 0; @@ -281,6 +291,8 @@ RendererCompositorRD::RendererCompositorRD() { scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage)); } + scene->init(); + // now we're ready to create our effects, storage->init_effects(!scene->_render_buffers_can_be_storage()); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 8639362da9..0230c46800 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -55,7 +55,8 @@ protected: }; struct BlitPushConstant { - float rect[4]; + float src_rect[4]; + float dst_rect[4]; float eye_center[2]; float k1; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 98d08f68e8..36943c5e5c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -1469,7 +1469,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; lights[idx].type = RS::LIGHT_DIRECTIONAL; - lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); lights[idx].has_shadow = storage->light_has_shadow(li->light); idx++; @@ -1514,7 +1514,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; lights[idx].type = storage->light_get_type(li->light); - lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); lights[idx].has_shadow = storage->light_has_shadow(li->light); lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); @@ -1953,7 +1953,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32 lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; - lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); lights[idx].has_shadow = storage->light_has_shadow(li->light); lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); @@ -2812,8 +2812,6 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p { //kinda complicated to compute the amount of slots, we try to use as many as we can - voxel_gi_max_lights = 32; - voxel_gi_lights = memnew_arr(VoxelGILight, voxel_gi_max_lights); voxel_gi_lights_uniform = RD::get_singleton()->uniform_buffer_create(voxel_gi_max_lights * sizeof(VoxelGILight)); voxel_gi_quality = RS::VoxelGIQuality(CLAMP(int(GLOBAL_GET("rendering/global_illumination/voxel_gi/quality")), 0, 1)); @@ -3009,7 +3007,9 @@ void RendererSceneGIRD::free() { sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader); sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader); - memdelete_arr(voxel_gi_lights); + if (voxel_gi_lights) { + memdelete_arr(voxel_gi_lights); + } } RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index 128bf09063..0b4622646f 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -110,8 +110,8 @@ private: float pad[3]; }; - VoxelGILight *voxel_gi_lights; - uint32_t voxel_gi_max_lights; + VoxelGILight *voxel_gi_lights = nullptr; + uint32_t voxel_gi_max_lights = 32; RID voxel_gi_lights_uniform; enum { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 5016c99a1e..fa66ed85a9 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -860,7 +860,7 @@ void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool shadow_atlas->shadow_owners.clear(); shadow_atlas->size = p_size; - shadow_atlas->use_16_bits = p_size; + shadow_atlas->use_16_bits = p_16_bits; } void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { @@ -935,7 +935,7 @@ bool RendererSceneRenderRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, //look for an empty space int sc = shadow_atlas->quadrants[qidx].shadows.size(); - ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptrw(); + const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr(); int found_free_idx = -1; //found a free one int found_used_idx = -1; //found existing one, must steal it @@ -980,6 +980,78 @@ bool RendererSceneRenderRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, return false; } +bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(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) { + for (int i = p_quadrant_count - 1; i >= 0; i--) { + int qidx = p_in_quadrants[i]; + + if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { + return false; + } + + //look for an empty space + int sc = shadow_atlas->quadrants[qidx].shadows.size(); + const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr(); + + int found_idx = -1; + uint64_t min_pass = 0; // sum of currently selected spots, try to get the least recently used pair + + for (int j = 0; j < sc - 1; j++) { + uint64_t pass = 0; + + if (sarr[j].owner.is_valid()) { + LightInstance *sli = light_instance_owner.getornull(sarr[j].owner); + ERR_CONTINUE(!sli); + + if (sli->last_scene_pass == scene_pass) { + continue; + } + + //was just allocated, don't kill it so soon, wait a bit.. + if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) { + continue; + } + pass += sli->last_scene_pass; + } + + if (sarr[j + 1].owner.is_valid()) { + LightInstance *sli = light_instance_owner.getornull(sarr[j + 1].owner); + ERR_CONTINUE(!sli); + + if (sli->last_scene_pass == scene_pass) { + continue; + } + + //was just allocated, don't kill it so soon, wait a bit.. + if (p_tick - sarr[j + 1].alloc_tick < shadow_atlas_realloc_tolerance_msec) { + continue; + } + pass += sli->last_scene_pass; + } + + if (found_idx == -1 || pass < min_pass) { + found_idx = j; + min_pass = pass; + + // we found two empty spots, no need to check the rest + if (pass == 0) { + break; + } + } + } + + if (found_idx == -1) { + continue; //nothing found + } + + r_quadrant = qidx; + r_shadow = found_idx; + + return true; + } + + return false; +} + bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); ERR_FAIL_COND_V(!shadow_atlas, false); @@ -1025,94 +1097,104 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i uint64_t tick = OS::get_singleton()->get_ticks_msec(); - //see if it already exists + uint32_t old_key = ShadowAtlas::SHADOW_INVALID; + uint32_t old_quadrant = ShadowAtlas::SHADOW_INVALID; + uint32_t old_shadow = ShadowAtlas::SHADOW_INVALID; + int old_subdivision = -1; + + bool should_realloc = false; + bool should_redraw = false; if (shadow_atlas->shadow_owners.has(p_light_intance)) { - //it does! - uint32_t key = shadow_atlas->shadow_owners[p_light_intance]; - uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; + old_key = shadow_atlas->shadow_owners[p_light_intance]; + old_quadrant = (old_key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; + old_shadow = old_key & ShadowAtlas::SHADOW_INDEX_MASK; - bool should_realloc = shadow_atlas->quadrants[q].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec); - bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version; + should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec); + should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version; if (!should_realloc) { - shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = p_light_version; //already existing, see if it should redraw or it's just OK return should_redraw; } - int new_quadrant, new_shadow; + old_subdivision = shadow_atlas->quadrants[old_quadrant].subdivision; + } - //find a better place - if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) { - //found a better place! - ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; - if (sh->owner.is_valid()) { - //is taken, but is invalid, erasing it - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.getornull(sh->owner); - sli->shadow_atlases.erase(p_atlas); - } + bool is_omni = li->light_type == RS::LIGHT_OMNI; + bool found_shadow = false; + int new_quadrant = -1; + int new_shadow = -1; - //erase previous - shadow_atlas->quadrants[q].shadows.write[s].version = 0; - shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); + if (is_omni) { + found_shadow = _shadow_atlas_find_omni_shadows(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow); + } else { + found_shadow = _shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow); + } - sh->owner = p_light_intance; - sh->alloc_tick = tick; - sh->version = p_light_version; - li->shadow_atlases.insert(p_atlas); - - //make new key - key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; - //update it in map - shadow_atlas->shadow_owners[p_light_intance] = key; - //make it dirty, as it should redraw anyway - return true; + if (found_shadow) { + if (old_quadrant != ShadowAtlas::SHADOW_INVALID) { + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = 0; + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].owner = RID(); + + if (old_key & ShadowAtlas::OMNI_LIGHT_FLAG) { + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].version = 0; + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].owner = RID(); + } } - //no better place for this shadow found, keep current + uint32_t new_key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; + new_key |= new_shadow; - //already existing, see if it should redraw or it's just OK + ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; + _shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow); - shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; + sh->owner = p_light_intance; + sh->alloc_tick = tick; + sh->version = p_light_version; - return should_redraw; - } + if (is_omni) { + new_key |= ShadowAtlas::OMNI_LIGHT_FLAG; - int new_quadrant, new_shadow; + int new_omni_shadow = new_shadow + 1; + ShadowAtlas::Quadrant::Shadow *extra_sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_omni_shadow]; + _shadow_atlas_invalidate_shadow(extra_sh, p_atlas, shadow_atlas, new_quadrant, new_omni_shadow); - //find a better place - if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) { - //found a better place! - ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; - if (sh->owner.is_valid()) { - //is taken, but is invalid, erasing it - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.getornull(sh->owner); - sli->shadow_atlases.erase(p_atlas); + extra_sh->owner = p_light_intance; + extra_sh->alloc_tick = tick; + extra_sh->version = p_light_version; } - sh->owner = p_light_intance; - sh->alloc_tick = tick; - sh->version = p_light_version; li->shadow_atlases.insert(p_atlas); - //make new key - uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; //update it in map - shadow_atlas->shadow_owners[p_light_intance] = key; + shadow_atlas->shadow_owners[p_light_intance] = new_key; //make it dirty, as it should redraw anyway - return true; } - //no place to allocate this light, apologies + return should_redraw; +} + +void RendererSceneRenderRD::_shadow_atlas_invalidate_shadow(RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, RendererSceneRenderRD::ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx) { + if (p_shadow->owner.is_valid()) { + LightInstance *sli = light_instance_owner.getornull(p_shadow->owner); + uint32_t old_key = p_shadow_atlas->shadow_owners[p_shadow->owner]; - return false; + if (old_key & ShadowAtlas::OMNI_LIGHT_FLAG) { + uint32_t s = old_key & ShadowAtlas::SHADOW_INDEX_MASK; + uint32_t omni_shadow_idx = p_shadow_idx + (s == (uint32_t)p_shadow_idx ? 1 : -1); + RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *omni_shadow = &p_shadow_atlas->quadrants[p_quadrant].shadows.write[omni_shadow_idx]; + omni_shadow->version = 0; + omni_shadow->owner = RID(); + } + + p_shadow->version = 0; + p_shadow->owner = RID(); + sli->shadow_atlases.erase(p_atlas); + p_shadow_atlas->shadow_owners.erase(p_shadow->owner); + } } void RendererSceneRenderRD::_update_directional_shadow_atlas() { @@ -1137,6 +1219,7 @@ void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size, bool p } directional_shadow.size = p_size; + directional_shadow.use_16_bits = p_16_bits; if (directional_shadow.depth.is_valid()) { RD::get_singleton()->free(directional_shadow.depth); @@ -2154,6 +2237,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } } + tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier(); tonemap.view_count = p_render_data->view_count; storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); @@ -2218,6 +2302,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr tonemap.use_debanding = rb->use_debanding; tonemap.texture_size = Vector2i(rb->width, rb->height); + tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier(); tonemap.view_count = p_render_data->view_count; storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap); @@ -2490,6 +2575,10 @@ float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID return rb->volumetric_fog->spread; } +float RendererSceneRenderRD::_render_buffers_get_luminance_multiplier() { + return 1.0; +} + RD::DataFormat RendererSceneRenderRD::_render_buffers_get_color_format() { return RD::DATA_FORMAT_R16G16B16A16_SFLOAT; } @@ -2502,6 +2591,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view"); RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + + // Should we add an overrule per viewport? rb->width = p_width; rb->height = p_height; rb->render_target = p_render_target; @@ -2548,8 +2639,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p tf.format = RD::DATA_FORMAT_R32_SFLOAT; } - tf.width = p_width; - tf.height = p_height; + tf.width = rb->width; + tf.height = rb->height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; tf.array_layers = rb->view_count; // create a layer for every view @@ -2571,10 +2662,10 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p } RID target_texture = storage->render_target_get_rd_texture(rb->render_target); - rb->data->configure(rb->texture, rb->depth_texture, target_texture, p_width, p_height, p_msaa, p_view_count); + rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->height, p_msaa, p_view_count); if (is_clustered_enabled()) { - rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture); + rb->cluster_builder->setup(Size2i(rb->width, rb->height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture); } } @@ -3120,18 +3211,19 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.shadow_enabled = true; - if (type == RS::LIGHT_SPOT) { - light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0); + float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas); + light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0; - } else { //omni + if (type == RS::LIGHT_SPOT) { light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0; - float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas); - light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space + } else { //omni + light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS); } light_data.transmittance_bias = storage->light_get_transmittance_bias(base); - Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas); + Vector2i omni_offset; + Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas, omni_offset); light_data.atlas_rect[0] = rect.position.x; light_data.atlas_rect[1] = rect.position.y; @@ -3142,7 +3234,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base); if (type == RS::LIGHT_OMNI) { - light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another Transform3D proj = (inverse_transform * light_transform).inverse(); RendererStorageRD::store_transform(proj, light_data.shadow_matrix); @@ -3154,6 +3245,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF } + light_data.direction[0] = omni_offset.x * float(rect.size.width); + light_data.direction[1] = omni_offset.y * float(rect.size.height); } else if (type == RS::LIGHT_SPOT) { Transform3D modelview = (inverse_transform * light_transform).inverse(); CameraMatrix bias; @@ -4066,7 +4159,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_state.voxel_gi_count = 0; - if (rb != nullptr) { + if (rb != nullptr && is_dynamic_gi_supported()) { if (rb->sdfgi) { rb->sdfgi->update_cascades(); rb->sdfgi->pre_process_gi(render_data.cam_transform, &render_data, this); @@ -4139,6 +4232,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, bool using_dual_paraboloid = false; bool using_dual_paraboloid_flip = false; + Vector2i dual_paraboloid_offset; RID render_fb; RID render_texture; float zfar; @@ -4232,6 +4326,9 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE); if (storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) { + bool wrap = (shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision == 0; + dual_paraboloid_offset = wrap ? Vector2i(1 - shadow_atlas->quadrants[quadrant].subdivision, 1) : Vector2i(1, 0); + if (storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) { ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2); @@ -4251,12 +4348,16 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, } } else { + atlas_rect.position.x += 1; + atlas_rect.position.y += 1; + atlas_rect.size.x -= 2; + atlas_rect.size.y -= 2; + + atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset; + light_projection = light_instance->shadow_transform[0].camera; light_transform = light_instance->shadow_transform[0].transform; - atlas_rect.size.height /= 2; - atlas_rect.position.y += p_pass * atlas_rect.size.height; - using_dual_paraboloid = true; using_dual_paraboloid_flip = p_pass == 1; render_fb = shadow_atlas->fb; @@ -4285,10 +4386,9 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, atlas_rect_norm.position.y /= float(atlas_size); atlas_rect_norm.size.x /= float(atlas_size); atlas_rect_norm.size.y /= float(atlas_size); - atlas_rect_norm.size.height /= 2; - storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, light_projection.get_z_near(), light_projection.get_z_far(), false); - atlas_rect_norm.position.y += atlas_rect_norm.size.height; - storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, light_projection.get_z_near(), light_projection.get_z_far(), true); + storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false); + atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size; + storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true); //restore transform so it can be properly used light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0); @@ -4390,6 +4490,12 @@ bool RendererSceneRenderRD::free(RID p_rid) { uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); + + if (key & ShadowAtlas::OMNI_LIGHT_FLAG) { + // Omni lights use two atlas spots, make sure to clear the other as well + shadow_atlas->quadrants[q].shadows.write[s + 1].owner = RID(); + } + shadow_atlas->shadow_owners.erase(p_rid); } @@ -4587,10 +4693,12 @@ uint32_t RendererSceneRenderRD::get_max_elements() const { } RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { - max_cluster_elements = get_max_elements(); - storage = p_storage; singleton = this; +} + +void RendererSceneRenderRD::init() { + max_cluster_elements = get_max_elements(); directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size"); directional_shadow.use_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits"); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 5306df36f0..eb61af517a 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -255,7 +255,8 @@ private: struct ShadowAtlas { enum { QUADRANT_SHIFT = 27, - SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1, + OMNI_LIGHT_FLAG = 1 << 26, + SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1, SHADOW_INVALID = 0xFFFFFFFF }; @@ -299,7 +300,9 @@ private: void _update_shadow_atlas(ShadowAtlas *shadow_atlas); + void _shadow_atlas_invalidate_shadow(RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, RendererSceneRenderRD::ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx); 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); + bool _shadow_atlas_find_omni_shadows(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::ShadowQuality shadows_quality = RS::SHADOW_QUALITY_MAX; //So it always updates when first set RS::ShadowQuality directional_shadow_quality = RS::SHADOW_QUALITY_MAX; @@ -379,10 +382,6 @@ private: uint32_t cull_mask = 0; uint32_t light_directional_index = 0; - uint32_t current_shadow_atlas_key = 0; - - Vector2 dp; - Rect2 directional_rect; Set<RID> shadow_atlases; //shadow atlases where this light is registered @@ -575,7 +574,7 @@ private: struct LightData { float position[3]; float inv_radius; - float direction[3]; + float direction[3]; // in omni, x and y are used for dual paraboloid offset float size; float color[3]; @@ -964,7 +963,7 @@ public: return li->transform; } - _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas) { + _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas, Vector2i &r_omni_offset) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); LightInstance *li = light_instance_owner.getornull(p_light_instance); uint32_t key = shadow_atlas->shadow_owners[li->self]; @@ -984,6 +983,16 @@ public: x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + if (key & ShadowAtlas::OMNI_LIGHT_FLAG) { + if (((shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision) == 0) { + r_omni_offset.x = 1 - int(shadow_atlas->quadrants[quadrant].subdivision); + r_omni_offset.y = 1; + } else { + r_omni_offset.x = 1; + r_omni_offset.y = 0; + } + } + uint32_t width = shadow_size; uint32_t height = shadow_size; @@ -1181,6 +1190,7 @@ public: /* render buffers */ + virtual float _render_buffers_get_luminance_multiplier(); virtual RD::DataFormat _render_buffers_get_color_format(); virtual bool _render_buffers_can_be_storage(); virtual RID render_buffers_create() override; @@ -1290,6 +1300,8 @@ public: virtual bool is_volumetric_supported() const; virtual uint32_t get_max_elements() const; + void init(); + RendererSceneRenderRD(RendererStorageRD *p_storage); ~RendererSceneRenderRD(); }; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 9e85608f1e..c388da755c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -259,7 +259,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar p_array[11] = 0; } -void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) { +void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) { SkyPushConstant sky_push_constant; memset(&sky_push_constant, 0, sizeof(SkyPushConstant)); @@ -276,6 +276,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_ sky_push_constant.position[2] = p_position.z; sky_push_constant.multiplier = p_multiplier; sky_push_constant.time = p_time; + sky_push_constant.luminance_multiplier = p_luminance_multiplier; store_transform_3x3(p_orientation, sky_push_constant.orientation); RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb); @@ -287,7 +288,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_ // Update uniform sets. { RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0); - if (RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { // Material may not have a uniform set. + if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { // Material may not have a uniform set. RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1); } RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2); @@ -855,6 +856,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { storage->shader_initialize(sky_shader.default_shader); storage->shader_set_code(sky_shader.default_shader, R"( +// Default sky shader. + shader_type sky; void sky() { @@ -942,6 +945,8 @@ void sky() { storage->shader_initialize(sky_scene_state.fog_shader); storage->shader_set_code(sky_scene_state.fog_shader, R"( +// Default clear color sky shader. + shader_type sky; uniform vec4 clear_color; @@ -1191,7 +1196,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo); } -void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time) { +void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { ERR_FAIL_COND(!p_env); Sky *sky = get_sky(p_env->sky); @@ -1283,7 +1288,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1302,7 +1307,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1317,7 +1322,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1435,7 +1440,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont clear_colors.push_back(Color(0.0, 0.0, 0.0)); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin); + _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); RD::get_singleton()->draw_list_end(); } @@ -1448,7 +1453,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont clear_colors.push_back(Color(0.0, 0.0, 0.0)); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin); + _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); RD::get_singleton()->draw_list_end(); } @@ -1462,11 +1467,11 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont } RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin); + _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); RD::get_singleton()->draw_list_end(); } -void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) { +void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1542,7 +1547,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u clear_colors.push_back(Color(0.0, 0.0, 0.0)); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin); + _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } @@ -1555,12 +1560,12 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u clear_colors.push_back(Color(0.0, 0.0, 0.0)); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin); + _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } } -void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) { +void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { ERR_FAIL_COND(!p_env); ERR_FAIL_COND(p_view_count == 0); @@ -1636,7 +1641,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set; } - _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin); + _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); } void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) { diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 7b670bddd5..7f563c9bc4 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -100,7 +100,8 @@ private: float position[3]; // 12 - 92 float multiplier; // 4 - 96 float time; // 4 - 100 - float pad[3]; // 12 - 112 // Using pad to align on 16 bytes + float luminance_multiplier; // 4 - 104 + float pad[2]; // 8 - 112 // Using pad to align on 16 bytes // 128 is the max size of a push constant. We can replace "pad" but we can't add any more. }; @@ -138,7 +139,7 @@ private: virtual ~SkyShaderData(); }; - void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position); + void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier); public: struct SkySceneState { @@ -293,10 +294,10 @@ public: ~RendererSceneSkyRD(); void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); - void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time); - void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); - void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); - void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); + void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer + void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); void invalidate_sky(Sky *p_sky); void update_dirty_skys(); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 7d438345f1..ec0d25376f 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -4848,7 +4848,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2); - if (m->uniform_set.is_valid()) { + if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3); } @@ -9310,15 +9310,6 @@ RendererStorageRD::RendererStorageRD() { } } - { - Vector<String> sdf_versions; - sdf_versions.push_back(""); //one only - voxel_gi_sdf_shader.initialize(sdf_versions); - voxel_gi_sdf_shader_version = voxel_gi_sdf_shader.version_create(); - voxel_gi_sdf_shader_version_shader = voxel_gi_sdf_shader.version_get_shader(voxel_gi_sdf_shader_version, 0); - voxel_gi_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(voxel_gi_sdf_shader_version_shader); - } - using_lightmap_array = true; // high end if (using_lightmap_array) { uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); @@ -9407,6 +9398,8 @@ RendererStorageRD::RendererStorageRD() { particles_shader.default_shader = shader_allocate(); shader_initialize(particles_shader.default_shader); shader_set_code(particles_shader.default_shader, R"( +// Default particles shader. + shader_type particles; void process() { @@ -9538,7 +9531,6 @@ RendererStorageRD::~RendererStorageRD() { RD::get_singleton()->free(mesh_default_rd_buffers[i]); } - voxel_gi_sdf_shader.version_free(voxel_gi_sdf_shader_version); particles_shader.copy_shader.version_free(particles_shader.copy_shader_version); rt_sdf.shader.version_free(rt_sdf.shader_version); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index b7adef6c60..02395a884f 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -1100,11 +1100,6 @@ private: Dependency dependency; }; - VoxelGiSdfShaderRD voxel_gi_sdf_shader; - RID voxel_gi_sdf_shader_version; - RID voxel_gi_sdf_shader_version_shader; - RID voxel_gi_sdf_shader_pipeline; - mutable RID_Owner<VoxelGI, true> voxel_gi_owner; /* REFLECTION PROBE */ diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 8aa03b6426..b95d4b642c 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -213,7 +213,7 @@ static String _interpstr(SL::DataInterpolation p_interp) { return ""; } -static String _prestr(SL::DataPrecision p_pres) { +static String _prestr(SL::DataPrecision p_pres, bool p_force_highp = false) { switch (p_pres) { case SL::PRECISION_LOWP: return "lowp "; @@ -222,7 +222,7 @@ static String _prestr(SL::DataPrecision p_pres) { case SL::PRECISION_HIGHP: return "highp "; case SL::PRECISION_DEFAULT: - return ""; + return p_force_highp ? "highp " : ""; } return ""; } @@ -617,7 +617,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge //this is an integer to index the global table ucode += _typestr(ShaderLanguage::TYPE_UINT); } else { - ucode += _prestr(uniform.precision); + ucode += _prestr(uniform.precision, ShaderLanguage::is_float_type(uniform.type)); ucode += _typestr(uniform.type); } @@ -742,7 +742,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge String vcode; String interp_mode = _interpstr(varying.interpolation); - vcode += _prestr(varying.precision); + vcode += _prestr(varying.precision, ShaderLanguage::is_float_type(varying.type)); vcode += _typestr(varying.type); vcode += " " + _mkid(varying_name); if (varying.array_size > 0) { @@ -777,7 +777,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge const SL::ShaderNode::Constant &cnode = pnode->vconstants[i]; String gcode; gcode += "const "; - gcode += _prestr(cnode.precision); + gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type)); if (cnode.type == SL::TYPE_STRUCT) { gcode += _mkid(cnode.type_str); } else { @@ -1165,6 +1165,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0]; bool is_texture_func = false; + bool is_screen_texture = false; if (onode->op == SL::OP_STRUCT) { code += _mkid(vnode->name); } else if (onode->op == SL::OP_CONSTRUCT) { @@ -1197,6 +1198,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]); StringName texture_uniform = varnode->name; + is_screen_texture = (texture_uniform == "SCREEN_TEXTURE"); String sampler_name; @@ -1236,6 +1238,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } } code += ")"; + if (is_screen_texture && actions.apply_luminance_multiplier) { + code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))"; + } } break; case SL::OP_INDEX: { code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h index 2da127ffa3..0fe9047967 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.h +++ b/servers/rendering/renderer_rd/shader_compiler_rd.h @@ -95,6 +95,7 @@ public: String global_buffer_array_variable; String instance_uniform_index_variable; uint32_t base_varying_index = 0; + bool apply_luminance_multiplier = false; }; private: diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 5bb12fc168..82efa1318c 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -279,7 +279,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { return; } - Vector<uint8_t> shader_data = RD::get_singleton()->shader_compile_binary_from_spirv(stages); + Vector<uint8_t> shader_data = RD::get_singleton()->shader_compile_binary_from_spirv(stages, name + ":" + itos(p_variant)); ERR_FAIL_COND(shader_data.size() == 0); diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl index 967da1e6e4..8051f96738 100644 --- a/servers/rendering/renderer_rd/shaders/blit.glsl +++ b/servers/rendering/renderer_rd/shaders/blit.glsl @@ -5,6 +5,7 @@ #VERSION_DEFINES layout(push_constant, binding = 0, std140) uniform Pos { + vec4 src_rect; vec4 dst_rect; vec2 eye_center; @@ -22,8 +23,8 @@ layout(location = 0) out vec2 uv; void main() { vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - uv = base_arr[gl_VertexIndex]; - vec2 vtx = data.dst_rect.xy + uv * data.dst_rect.zw; + uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw; + vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw; gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0); } @@ -34,6 +35,7 @@ void main() { #VERSION_DEFINES layout(push_constant, binding = 0, std140) uniform Pos { + vec4 src_rect; vec4 dst_rect; vec2 eye_center; diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/blur_raster.glsl index 0789a4b396..f8b4e3f610 100644 --- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/blur_raster.glsl @@ -38,6 +38,8 @@ layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; layout(location = 0) out vec4 frag_color; void main() { + // We do not apply our color scale for our mobile renderer here, we'll leave our colors at half brightness and apply scale in the tonemap raster. + #ifdef MODE_MIPMAP vec2 pix_size = blur.pixel_size; diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl index 43a2a29616..a3b3938ee9 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl @@ -47,7 +47,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight; #endif //DOF -// Bokeh single pass implementation based on http://tuxedolabs.blogspot.com/2018/05/bokeh-depth-of-field-in-single-pass.html +// Bokeh single pass implementation based on https://tuxedolabs.blogspot.com/2018/05/bokeh-depth-of-field-in-single-pass.html #ifdef MODE_GEN_BLUR_SIZE diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index a443bcdcb8..2911e8b731 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -458,6 +458,14 @@ void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) { #endif +float msdf_median(float r, float g, float b, float a) { + return min(max(min(r, g), min(max(r, g), b)), a); +} + +vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) { + return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min); +} + void main() { vec4 color = color_interp; vec2 uv = uv_interp; @@ -485,7 +493,34 @@ void main() { #endif - color *= texture(sampler2D(color_texture, texture_sampler), uv); +#ifndef USE_PRIMITIVE + if (bool(draw_data.flags & FLAGS_USE_MSDF)) { + float px_range = draw_data.ninepatch_margins.x; + float outline_thickness = draw_data.ninepatch_margins.y; + //float reserved1 = draw_data.ninepatch_margins.z; + //float reserved2 = draw_data.ninepatch_margins.w; + + vec4 msdf_sample = texture(sampler2D(color_texture, texture_sampler), uv); + vec2 msdf_size = vec2(textureSize(sampler2D(color_texture, texture_sampler), 0)); + vec2 dest_size = vec2(1.0) / fwidth(uv); + float px_size = max(0.5 * dot((vec2(px_range) / msdf_size), dest_size), 1.0); + float d = msdf_median(msdf_sample.r, msdf_sample.g, msdf_sample.b, msdf_sample.a) - 0.5; + + if (outline_thickness > 0) { + float cr = clamp(outline_thickness, 0.0, px_range / 2) / px_range; + float a = clamp((d + cr) * px_size, 0.0, 1.0); + color.a = a * color.a; + } else { + float a = clamp(d * px_size + 0.5, 0.0, 1.0); + color.a = a * color.a; + } + + } else { +#else + { +#endif + color *= texture(sampler2D(color_texture, texture_sampler), uv); + } uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights bool using_light = light_count > 0 || canvas_data.directional_light_count > 0; diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 451f9b0089..0cff505cae 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -24,6 +24,8 @@ #define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26) #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) +#define FLAGS_USE_MSDF (1 << 28) + #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 #define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl index da7d189281..6d95722a57 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl @@ -117,7 +117,7 @@ void main() { uint cluster_thread_group_index; if (!gl_HelperInvocation) { - //http://advances.realtimerendering.com/s2017/2017_Sig_Improved_Culling_final.pdf + //https://advances.realtimerendering.com/s2017/2017_Sig_Improved_Culling_final.pdf uvec4 mask; diff --git a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl index dfbce29119..69b895ed29 100644 --- a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl +++ b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl @@ -7,8 +7,7 @@ layout(push_constant, binding = 1, std430) uniform Params { float z_far; float z_near; - bool z_flip; - uint pad; + vec2 texel_size; vec4 screen_rect; } params; @@ -35,22 +34,23 @@ layout(set = 0, binding = 0) uniform samplerCube source_cube; layout(push_constant, binding = 1, std430) uniform Params { float z_far; float z_near; - bool z_flip; - uint pad; + vec2 texel_size; vec4 screen_rect; } params; void main() { vec2 uv = uv_interp; + vec2 texel_size = abs(params.texel_size); - vec3 normal = vec3(uv * 2.0 - 1.0, 0.0); + uv = clamp(uv * (1.0 + 2.0 * texel_size) - texel_size, vec2(0.0), vec2(1.0)); - normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); + vec3 normal = vec3(uv * 2.0 - 1.0, 0.0); + normal.z = 0.5 * (1.0 - dot(normal.xy, normal.xy)); // z = 1/2 - 1/2 * (x^2 + y^2) normal = normalize(normal); normal.y = -normal.y; //needs to be flipped to match projection matrix - if (!params.z_flip) { + if (params.texel_size.x >= 0.0) { // Sign is used to encode Z flip normal.z = -normal.z; } diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl index 80c0ac4fb4..be12be5dec 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl @@ -69,13 +69,13 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { return TangentX * H.x + TangentY * H.y + N * H.z; } -// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html float GGX(float NdotV, float a) { float k = a / 2.0; return NdotV / (NdotV * (1.0 - k) + k); } -// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html float G_Smith(float a, float nDotV, float nDotL) { return GGX(nDotL, a * a) * GGX(nDotV, a * a); } diff --git a/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl b/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl index ccaad13311..158096d3c7 100644 --- a/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/decal_data_inc.glsl @@ -1,18 +1,18 @@ struct DecalData { - mat4 xform; //to decal transform - vec3 inv_extents; - float albedo_mix; - vec4 albedo_rect; - vec4 normal_rect; - vec4 orm_rect; - vec4 emission_rect; - vec4 modulate; - float emission_energy; + highp mat4 xform; //to decal transform + highp vec3 inv_extents; + mediump float albedo_mix; + highp vec4 albedo_rect; + highp vec4 normal_rect; + highp vec4 orm_rect; + highp vec4 emission_rect; + highp vec4 modulate; + mediump float emission_energy; uint mask; - float upper_fade; - float lower_fade; - mat3x4 normal_xform; - vec3 normal; - float normal_fade; + mediump float upper_fade; + mediump float lower_fade; + mediump mat3x4 normal_xform; + mediump vec3 normal; + mediump float normal_fade; }; diff --git a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl index 5dc2d08a3b..25d87ca45d 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl @@ -202,12 +202,7 @@ void main() { vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission & 0x3FF, (cell_data.data[cell_index].emission >> 10) & 0x7FF, cell_data.data[cell_index].emission >> 21)) * params.emission_scale; vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); -#ifdef MODE_ANISOTROPIC - vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); -#else vec3 accum = vec3(0.0); -#endif for (uint i = 0; i < params.light_count; i++) { float attenuation; @@ -242,77 +237,35 @@ void main() { vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy; -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - accum[j] += max(0.0, dot(accum_dir, -light_dir)) * light + emission; - } -#else if (length(normal.xyz) > 0.2) { accum += max(0.0, dot(normal.xyz, -light_dir)) * light + emission; } else { //all directions accum += light + emission; } -#endif } -#ifdef MODE_ANISOTROPIC - - output.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); - output.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); - output.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); - output.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); - output.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); - output.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); -#else output.data[cell_index] = vec4(accum, 0.0); -#endif - #endif //MODE_COMPUTE_LIGHT #ifdef MODE_UPDATE_MIPMAPS { -#ifdef MODE_ANISOTROPIC - vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); -#else vec3 light_accum = vec3(0.0); -#endif float count = 0.0; for (uint i = 0; i < 8; i++) { uint child_index = cell_children.data[cell_index].children[i]; if (child_index == NO_CHILDREN) { continue; } -#ifdef MODE_ANISOTROPIC - light_accum[1] += output.data[child_index * 6 + 0].rgb; - light_accum[2] += output.data[child_index * 6 + 1].rgb; - light_accum[3] += output.data[child_index * 6 + 2].rgb; - light_accum[4] += output.data[child_index * 6 + 3].rgb; - light_accum[5] += output.data[child_index * 6 + 4].rgb; - light_accum[6] += output.data[child_index * 6 + 5].rgb; - -#else light_accum += output.data[child_index].rgb; -#endif - count += 1.0; } float divisor = mix(8.0, count, params.propagation); -#ifdef MODE_ANISOTROPIC - output.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); - output.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); - output.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); - output.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); - output.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); - output.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); - -#else output.data[cell_index] = vec4(light_accum / divisor, 0.0); -#endif } #endif diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl index 9155216d7e..fdc7729338 100644 --- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl @@ -4,28 +4,28 @@ struct LightData { //this structure needs to be as packed as possible highp vec3 position; - float inv_radius; + highp float inv_radius; - vec3 direction; - float size; + mediump vec3 direction; + highp float size; - vec3 color; - float attenuation; + mediump vec3 color; + mediump float attenuation; - float cone_attenuation; - float cone_angle; - float specular_amount; + mediump float cone_attenuation; + mediump float cone_angle; + mediump float specular_amount; bool shadow_enabled; highp vec4 atlas_rect; // rect in the shadow atlas highp mat4 shadow_matrix; - float shadow_bias; - 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 + highp float shadow_bias; + highp float shadow_normal_bias; + highp float transmittance_bias; + highp float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle + highp float soft_shadow_scale; // scales the shadow kernel for blurrier shadows uint mask; - float shadow_volumetric_fog_fade; + mediump float shadow_volumetric_fog_fade; uint bake_mode; highp vec4 projector_rect; //projector rect in srgb decal atlas }; @@ -35,53 +35,53 @@ struct LightData { //this structure needs to be as packed as possible #define REFLECTION_AMBIENT_COLOR 2 struct ReflectionData { - vec3 box_extents; - float index; - vec3 box_offset; + highp vec3 box_extents; + mediump float index; + highp vec3 box_offset; uint mask; - vec3 ambient; // ambient color - float intensity; + mediump vec3 ambient; // ambient color + mediump float intensity; bool exterior; bool box_project; uint ambient_mode; uint pad; //0-8 is intensity,8-9 is ambient, mode - mat4 local_matrix; // up to here for spot and omni, rest is for directional + highp mat4 local_matrix; // up to here for spot and omni, rest is for directional // notes: for ambientblend, use distance to edge to blend between already existing global environment }; struct DirectionalLightData { - vec3 direction; - float energy; - vec3 color; - float size; - float specular; + mediump vec3 direction; + mediump float energy; + mediump vec3 color; + mediump float size; + mediump float specular; uint mask; - float softshadow_angle; - float soft_shadow_scale; + highp float softshadow_angle; + highp float soft_shadow_scale; bool blend_splits; bool shadow_enabled; - float fade_from; - float fade_to; + highp float fade_from; + highp float fade_to; uvec2 pad; uint bake_mode; - float shadow_volumetric_fog_fade; - vec4 shadow_bias; - vec4 shadow_normal_bias; - vec4 shadow_transmittance_bias; + mediump float shadow_volumetric_fog_fade; + highp vec4 shadow_bias; + highp vec4 shadow_normal_bias; + highp vec4 shadow_transmittance_bias; highp vec4 shadow_z_range; highp vec4 shadow_range_begin; - vec4 shadow_split_offsets; + highp vec4 shadow_split_offsets; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; highp mat4 shadow_matrix3; highp mat4 shadow_matrix4; - vec4 shadow_color1; - vec4 shadow_color2; - vec4 shadow_color3; - vec4 shadow_color4; - vec2 uv_scale1; - vec2 uv_scale2; - vec2 uv_scale3; - vec2 uv_scale4; + mediump vec4 shadow_color1; + mediump vec4 shadow_color2; + mediump vec4 shadow_color3; + mediump vec4 shadow_color4; + highp vec2 uv_scale1; + highp vec2 uv_scale2; + highp vec2 uv_scale3; + highp vec2 uv_scale4; }; diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl index ed389ffe56..3cde9923fa 100644 --- a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl @@ -6,6 +6,6 @@ layout(push_constant, binding = 1, std430) uniform PushConstant { float exposure_adjust; float min_luminance; float max_luminance; - float pad; + uint pad1; } settings; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 4f140dd10d..edbe1031b7 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -118,7 +118,7 @@ void main() { mat3 world_normal_matrix; if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { - world_normal_matrix = inverse(mat3(world_matrix)); + world_normal_matrix = transpose(inverse(mat3(world_matrix))); } else { world_normal_matrix = mat3(world_matrix); } @@ -374,6 +374,9 @@ layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4; layout(constant_id = 10) const bool sc_decal_use_mipmaps = true; layout(constant_id = 11) const bool sc_projector_use_mipmaps = true; +// not used in clustered renderer but we share some code with the mobile renderer that requires this. +const float sc_luminance_multiplier = 1.0; + #include "scene_forward_clustered_inc.glsl" /* Varyings */ @@ -881,7 +884,7 @@ void main() { #ifdef NORMAL_USED if (scene_data.roughness_limiter_enabled) { - //http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf + //https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf float roughness2 = roughness * roughness; vec3 dndu = dFdx(normal), dndv = dFdy(normal); float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv)); @@ -1601,7 +1604,7 @@ void main() { continue; // Statically baked light and object uses lightmap, skip } - float shadow = light_process_omni_shadow(light_index, vertex, view); + float shadow = light_process_omni_shadow(light_index, vertex, normal); shadow = blur_shadow(shadow); @@ -1677,7 +1680,7 @@ void main() { continue; // Statically baked light and object uses lightmap, skip } - float shadow = light_process_spot_shadow(light_index, vertex, view); + float shadow = light_process_spot_shadow(light_index, vertex, normal); shadow = blur_shadow(shadow); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 4a41c66ef3..f3db4abe3b 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -279,7 +279,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte } #ifdef USE_SHADOW_TO_OPACITY - alpha = min(alpha, clamp(1.0 - attenuation), 0.0, 1.0)); + alpha = min(alpha, clamp(1.0 - attenuation, 0.0, 1.0)); #endif #endif //defined(LIGHT_CODE_USED) @@ -288,7 +288,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #ifndef USE_NO_SHADOWS // Interleaved Gradient Noise -// http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare +// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare float quick_hash(vec2 pos) { const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); return fract(magic.z * fract(dot(pos, magic.xy))); @@ -320,7 +320,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve return avg * (1.0 / float(sc_directional_soft_shadow_samples)); } -float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { +float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) { vec2 pos = coord.xy; float depth = coord.z; @@ -346,6 +346,49 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { return avg * (1.0 / float(sc_soft_shadow_samples)); } +float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth) { + //if only one sample is taken, take it from the center + if (sc_soft_shadow_samples == 1) { + vec2 pos = coord * 0.5 + 0.5; + pos = uv_rect.xy + pos * uv_rect.zw; + 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; + vec2 offset_scale = blur_scale * 2.0 * scene_data.shadow_atlas_pixel_size / uv_rect.zw; + + for (uint i = 0; i < sc_soft_shadow_samples; i++) { + vec2 offset = offset_scale * (disk_rotation * scene_data.soft_shadow_kernel[i].xy); + vec2 sample_coord = coord + offset; + + float sample_coord_length_sqaured = dot(sample_coord, sample_coord); + bool do_flip = sample_coord_length_sqaured > 1.0; + + if (do_flip) { + float len = sqrt(sample_coord_length_sqaured); + sample_coord = sample_coord * (2.0 / len - 1.0); + } + + sample_coord = sample_coord * 0.5 + 0.5; + sample_coord = uv_rect.xy + sample_coord * uv_rect.zw; + + if (do_flip) { + sample_coord += flip_offset; + } + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(sample_coord, depth, 1.0)); + } + + return avg * (1.0 / float(sc_soft_shadow_samples)); +} + float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) { //find blocker float blocker_count = 0.0; @@ -403,15 +446,21 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { #ifndef USE_NO_SHADOWS if (omni_lights.data[idx].shadow_enabled) { // there is a shadowmap + vec2 texel_size = scene_data.shadow_atlas_pixel_size; + vec4 base_uv_rect = omni_lights.data[idx].atlas_rect; + base_uv_rect.xy += texel_size; + base_uv_rect.zw -= texel_size * 2.0; - vec3 light_rel_vec = omni_lights.data[idx].position - vertex; - float light_length = length(light_rel_vec); + // Omni lights use direction.xy to store to store the offset between the two paraboloid regions + vec2 flip_offset = omni_lights.data[idx].direction.xy; - vec4 v = vec4(vertex, 1.0); + vec3 local_vert = (omni_lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz; - vec4 splane = (omni_lights.data[idx].shadow_matrix * v); + float shadow_len = length(local_vert); //need to remember shadow len from here + vec3 shadow_dir = normalize(local_vert); - float shadow_len = length(splane.xyz); //need to remember shadow len from here + vec3 local_normal = normalize(mat3(omni_lights.data[idx].shadow_matrix) * normal); + vec3 normal_bias = local_normal * omni_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(local_normal, shadow_dir))); float shadow; @@ -431,10 +480,10 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); } - vec3 normal = normalize(splane.xyz); - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); - vec3 tangent = normalize(cross(v0, normal)); - vec3 bitangent = normalize(cross(tangent, normal)); + vec3 basis_normal = shadow_dir; + vec3 v0 = abs(basis_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, basis_normal)); + vec3 bitangent = normalize(cross(tangent, basis_normal)); float z_norm = shadow_len * omni_lights.data[idx].inv_radius; tangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale; @@ -443,18 +492,17 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy; - vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y; + vec3 pos = local_vert + tangent * disk.x + bitangent * disk.y; pos = normalize(pos); - vec4 uv_rect = omni_lights.data[idx].atlas_rect; + + vec4 uv_rect = base_uv_rect; if (pos.z >= 0.0) { - pos.z += 1.0; - uv_rect.y += uv_rect.w; - } else { - pos.z = 1.0 - pos.z; + uv_rect.xy += flip_offset; } + pos.z = 1.0 + abs(pos.z); pos.xy /= pos.z; pos.xy = pos.xy * 0.5 + 0.5; @@ -479,18 +527,18 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { shadow = 0.0; for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy; - vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y; + vec3 pos = local_vert + tangent * disk.x + bitangent * disk.y; pos = normalize(pos); - vec4 uv_rect = omni_lights.data[idx].atlas_rect; + pos = normalize(pos + normal_bias); + + vec4 uv_rect = base_uv_rect; if (pos.z >= 0.0) { - pos.z += 1.0; - uv_rect.y += uv_rect.w; - } else { - pos.z = 1.0 - pos.z; + uv_rect.xy += flip_offset; } + pos.z = 1.0 + abs(pos.z); pos.xy /= pos.z; pos.xy = pos.xy * 0.5 + 0.5; @@ -505,26 +553,19 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { shadow = 1.0; } } else { - splane.xyz = normalize(splane.xyz); - vec4 clamp_rect = omni_lights.data[idx].atlas_rect; - - if (splane.z >= 0.0) { - splane.z += 1.0; + vec4 uv_rect = base_uv_rect; - clamp_rect.y += clamp_rect.w; - - } else { - splane.z = 1.0 - splane.z; + vec3 shadow_sample = normalize(shadow_dir + normal_bias); + if (shadow_sample.z >= 0.0) { + uv_rect.xy += flip_offset; + flip_offset *= -1.0; } - splane.xy /= splane.z; - - splane.xy = splane.xy * 0.5 + 0.5; - splane.z = shadow_len * omni_lights.data[idx].inv_radius; - splane.z -= omni_lights.data[idx].shadow_bias; - splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; - splane.w = 1.0; //needed? i think it should be 1 already - shadow = sample_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane); + shadow_sample.z = 1.0 + abs(shadow_sample.z); + vec2 pos = shadow_sample.xy / shadow_sample.z; + float depth = shadow_len - omni_lights.data[idx].shadow_bias; + depth *= omni_lights.data[idx].inv_radius; + shadow = sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth); } return shadow; @@ -608,13 +649,11 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v vec4 atlas_rect = omni_lights.data[idx].projector_rect; if (local_v.z >= 0.0) { - local_v.z += 1.0; atlas_rect.y += atlas_rect.w; - - } else { - local_v.z = 1.0 - local_v.z; } + local_v.z = 1.0 + abs(local_v.z); + local_v.xy /= local_v.z; local_v.xy = local_v.xy * 0.5 + 0.5; vec2 proj_uv = local_v.xy * atlas_rect.zw; @@ -694,15 +733,18 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { vec3 light_rel_vec = spot_lights.data[idx].position - vertex; float light_length = length(light_rel_vec); vec3 spot_dir = spot_lights.data[idx].direction; - //there is a shadowmap - vec4 v = vec4(vertex, 1.0); - float shadow; + vec3 shadow_dir = light_rel_vec / light_length; + vec3 normal_bias = normal * light_length * spot_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(normal, shadow_dir))); + + //there is a shadowmap + vec4 v = vec4(vertex + normal_bias, 1.0); vec4 splane = (spot_lights.data[idx].shadow_matrix * v); + splane.z -= spot_lights.data[idx].shadow_bias / (light_length * spot_lights.data[idx].inv_radius); splane /= splane.w; - splane.z -= spot_lights.data[idx].shadow_bias; + float shadow; if (sc_use_light_soft_shadows && spot_lights.data[idx].soft_shadow_size > 0.0) { //soft shadow @@ -753,11 +795,9 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { //no blockers found, so no shadow shadow = 1.0; } - } else { //hard shadow - vec4 shadow_uv = vec4(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z, 1.0); - + vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z); shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv); } @@ -929,7 +969,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes vec4 reflection; - reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb; + reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier; if (reflections.data[ref_index].exterior) { reflection.rgb = mix(specular_light, reflection.rgb, blend); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 663100a0b3..518b0a6c7f 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -92,7 +92,7 @@ layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms #ifdef MODE_DUAL_PARABOLOID -layout(location = 8) out float dp_clip; +layout(location = 8) out highp float dp_clip; #endif @@ -124,7 +124,7 @@ void main() { mat3 world_normal_matrix; if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { - world_normal_matrix = inverse(mat3(world_matrix)); + world_normal_matrix = transpose(inverse(mat3(world_matrix))); } else { world_normal_matrix = mat3(world_matrix); } @@ -370,11 +370,6 @@ void main() { #VERSION_DEFINES -//use medium precision for floats on mobile. - -precision mediump float; -precision highp int; - /* Specialization Constants */ #if !defined(MODE_RENDER_DEPTH) @@ -406,6 +401,8 @@ layout(constant_id = 14) const bool sc_disable_fog = false; #endif //!MODE_RENDER_DEPTH +layout(constant_id = 15) const float sc_luminance_multiplier = 2.0; + /* Include our forward mobile UBOs definitions etc. */ #include "scene_forward_mobile_inc.glsl" @@ -498,7 +495,7 @@ layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter) #else -layout(location = 0) out vec4 frag_color; +layout(location = 0) out mediump vec4 frag_color; #endif // MODE_MULTIPLE_RENDER_TARGETS #endif // RENDER DEPTH @@ -852,7 +849,7 @@ void main() { #ifdef NORMAL_USED if (scene_data.roughness_limiter_enabled) { - //http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf + //https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf float roughness2 = roughness * roughness; vec3 dndu = dFdx(normal), dndv = dFdy(normal); float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv)); @@ -1392,7 +1389,7 @@ void main() { break; } - float shadow = light_process_omni_shadow(light_index, vertex, view); + float shadow = light_process_omni_shadow(light_index, vertex, normal); shadow = blur_shadow(shadow); @@ -1440,7 +1437,7 @@ void main() { break; } - float shadow = light_process_spot_shadow(light_index, vertex, view); + float shadow = light_process_spot_shadow(light_index, vertex, normal); shadow = blur_shadow(shadow); @@ -1556,12 +1553,15 @@ void main() { frag_color = vec4(albedo, alpha); #else // MODE_UNSHADED frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); - //frag_color = vec4(1.0); #endif // MODE_UNSHADED // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); + // On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking + // We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images + frag_color.rgb = frag_color.rgb / sc_luminance_multiplier; + #endif //MODE_MULTIPLE_RENDER_TARGETS #endif //MODE_RENDER_DEPTH diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index f1e554d01c..dd8879acb4 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -93,7 +93,7 @@ directional_lights; #define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2 struct Lightmap { - mat3 normal_xform; + mediump mat3 normal_xform; }; layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps { @@ -102,7 +102,7 @@ layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps { lightmaps; struct LightmapCapture { - vec4 sh[9]; + mediump vec4 sh[9]; }; layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures { @@ -110,8 +110,8 @@ layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures } lightmap_captures; -layout(set = 0, binding = 11) uniform texture2D decal_atlas; -layout(set = 0, binding = 12) uniform texture2D decal_atlas_srgb; +layout(set = 0, binding = 11) uniform mediump texture2D decal_atlas; +layout(set = 0, binding = 12) uniform mediump texture2D decal_atlas_srgb; layout(set = 0, binding = 13, std430) restrict readonly buffer Decals { DecalData data[]; @@ -119,7 +119,7 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals { decals; layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData { - vec4 data[]; + highp vec4 data[]; } global_variables; @@ -135,56 +135,56 @@ layout(set = 1, binding = 0, std140) uniform SceneData { highp mat4 projection_matrix_view[MAX_VIEWS]; highp mat4 inv_projection_matrix_view[MAX_VIEWS]; - vec2 viewport_size; - vec2 screen_pixel_size; + highp vec2 viewport_size; + highp vec2 screen_pixel_size; // Use vec4s because std140 doesn't 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]; + highp vec4 directional_penumbra_shadow_kernel[32]; + highp vec4 directional_soft_shadow_kernel[32]; + highp vec4 penumbra_shadow_kernel[32]; + highp vec4 soft_shadow_kernel[32]; - vec4 ambient_light_color_energy; + mediump vec4 ambient_light_color_energy; - float ambient_color_sky_mix; + mediump float ambient_color_sky_mix; bool use_ambient_light; bool use_ambient_cubemap; bool use_reflection_cubemap; - mat3 radiance_inverse_xform; + mediump mat3 radiance_inverse_xform; - vec2 shadow_atlas_pixel_size; - vec2 directional_shadow_pixel_size; + highp vec2 shadow_atlas_pixel_size; + highp vec2 directional_shadow_pixel_size; uint directional_light_count; - float dual_paraboloid_side; - float z_far; - float z_near; + mediump float dual_paraboloid_side; + highp float z_far; + highp float z_near; bool ssao_enabled; - float ssao_light_affect; - float ssao_ao_affect; + mediump float ssao_light_affect; + mediump float ssao_ao_affect; bool roughness_limiter_enabled; - float roughness_limiter_amount; - float roughness_limiter_limit; + mediump float roughness_limiter_amount; + mediump float roughness_limiter_limit; uvec2 roughness_limiter_pad; - vec4 ao_color; + mediump vec4 ao_color; bool fog_enabled; - float fog_density; - float fog_height; - float fog_height_density; + highp float fog_density; + highp float fog_height; + highp float fog_height_density; - vec3 fog_light_color; - float fog_sun_scatter; + mediump vec3 fog_light_color; + mediump float fog_sun_scatter; - float fog_aerial_perspective; + mediump float fog_aerial_perspective; bool material_uv2_mode; - float time; - float reflection_multiplier; // one normally, zero when rendering reflections + highp float time; + mediump float reflection_multiplier; // one normally, zero when rendering reflections bool pancake_shadows; uint pad1; @@ -195,30 +195,30 @@ scene_data; #ifdef USE_RADIANCE_CUBEMAP_ARRAY -layout(set = 1, binding = 2) uniform textureCubeArray radiance_cubemap; +layout(set = 1, binding = 2) uniform mediump textureCubeArray radiance_cubemap; #else -layout(set = 1, binding = 2) uniform textureCube radiance_cubemap; +layout(set = 1, binding = 2) uniform mediump textureCube radiance_cubemap; #endif -layout(set = 1, binding = 3) uniform textureCubeArray reflection_atlas; +layout(set = 1, binding = 3) uniform mediump textureCubeArray reflection_atlas; -layout(set = 1, binding = 4) uniform texture2D shadow_atlas; +layout(set = 1, binding = 4) uniform highp texture2D shadow_atlas; -layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas; +layout(set = 1, binding = 5) uniform highp texture2D directional_shadow_atlas; // this needs to change to providing just the lightmap we're using.. layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; -layout(set = 1, binding = 9) uniform texture2D depth_buffer; -layout(set = 1, binding = 10) uniform texture2D color_buffer; +layout(set = 1, binding = 9) uniform highp texture2D depth_buffer; +layout(set = 1, binding = 10) uniform mediump texture2D color_buffer; /* Set 2 Skeleton & Instancing (can change per item) */ layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms { - vec4 data[]; + highp vec4 data[]; } transforms; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl index 0eacbc5363..4290d5b869 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl @@ -24,7 +24,7 @@ layout(push_constant, binding = 0, std430) uniform Params { } params; -// http://in4k.untergrund.net/html_articles/hugi_27_-_coding_corner_polaris_sphere_tessellation_101.htm +// https://in4k.untergrund.net/html_articles/hugi_27_-_coding_corner_polaris_sphere_tessellation_101.htm vec3 get_sphere_vertex(uint p_vertex_id) { float x_angle = float(p_vertex_id & 1u) + (p_vertex_id >> params.band_power); diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl index 41c6325bc5..d07a454ade 100644 --- a/servers/rendering/renderer_rd/shaders/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/sky.glsl @@ -17,6 +17,8 @@ layout(push_constant, binding = 1, std430) uniform Params { vec4 projections[MAX_VIEWS]; vec4 position_multiplier; float time; + float luminance_multiplier; + float pad[2]; } params; @@ -55,6 +57,8 @@ layout(push_constant, binding = 1, std430) uniform Params { vec4 projections[MAX_VIEWS]; vec4 position_multiplier; float time; + float luminance_multiplier; + float pad[2]; } params; @@ -199,17 +203,17 @@ void main() { vec3 inverted_cube_normal = cube_normal; inverted_cube_normal.z *= -1.0; #ifdef USES_HALF_RES_COLOR - half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal); + half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier; #endif #ifdef USES_QUARTER_RES_COLOR - quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal); + quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier; #endif #else #ifdef USES_HALF_RES_COLOR - half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); + half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier; #endif #ifdef USES_QUARTER_RES_COLOR - quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); + quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier; #endif #endif @@ -246,4 +250,7 @@ void main() { if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) { frag_color.a = 0.0; } + + // For mobile renderer we're dividing by 2.0 as we're using a UNORM buffer + frag_color.rgb = frag_color.rgb / params.luminance_multiplier; } diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl index 3c685c25b9..1ce3e04421 100644 --- a/servers/rendering/renderer_rd/shaders/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl @@ -37,15 +37,15 @@ layout(location = 0) in vec2 uv_interp; #ifdef SUBPASS layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput input_color; -#else -#if MULTIVIEW +#elif defined(MULTIVIEW) layout(set = 0, binding = 0) uniform sampler2DArray source_color; #else layout(set = 0, binding = 0) uniform sampler2D source_color; #endif -#endif + layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; layout(set = 2, binding = 0) uniform sampler2D source_glow; + #ifdef USE_1D_LUT layout(set = 3, binding = 0) uniform sampler2D source_color_correction; #else @@ -71,7 +71,7 @@ layout(push_constant, binding = 1, std430) uniform Params { float exposure; float white; float auto_exposure_grey; - uint pad2; + float luminance_multiplier; vec2 pixel_size; bool use_fxaa; @@ -169,16 +169,33 @@ vec3 tonemap_filmic(vec3 color, float white) { return color_tonemapped / white_tonemapped; } +// Adapted from https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl +// (MIT License). vec3 tonemap_aces(vec3 color, float white) { - const float exposure_bias = 0.85f; - const float A = 2.51f * exposure_bias * exposure_bias; - const float B = 0.03f * exposure_bias; - const float C = 2.43f * exposure_bias * exposure_bias; - const float D = 0.59f * exposure_bias; - const float E = 0.14f; - - vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E); - float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E); + const float exposure_bias = 1.8f; + const float A = 0.0245786f; + const float B = 0.000090537f; + const float C = 0.983729f; + const float D = 0.432951f; + const float E = 0.238081f; + + // Exposure bias baked into transform to save shader instructions. Equivalent to `color *= exposure_bias` + const mat3 rgb_to_rrt = mat3( + vec3(0.59719f * exposure_bias, 0.35458f * exposure_bias, 0.04823f * exposure_bias), + vec3(0.07600f * exposure_bias, 0.90834f * exposure_bias, 0.01566f * exposure_bias), + vec3(0.02840f * exposure_bias, 0.13383f * exposure_bias, 0.83777f * exposure_bias)); + + const mat3 odt_to_rgb = mat3( + vec3(1.60475f, -0.53108f, -0.07367f), + vec3(-0.10208f, 1.10813f, -0.00605f), + vec3(-0.00327f, -0.07276f, 1.07602f)); + + color *= rgb_to_rrt; + vec3 color_tonemapped = (color * (color + A) - B) / (color * (C * color + D) + E); + color_tonemapped *= odt_to_rgb; + + white *= exposure_bias; + float white_tonemapped = (white * (white + A) - B) / (white * (C * white + D) + E); return color_tonemapped / white_tonemapped; } @@ -200,15 +217,16 @@ vec3 linear_to_srgb(vec3 color) { #define TONEMAPPER_ACES 3 vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always outputs clamped [0;1] color - + // Ensure color values passed to tonemappers are positive. + // They can be negative in the case of negative lights, which leads to undesired behavior. if (params.tonemapper == TONEMAPPER_LINEAR) { return color; } else if (params.tonemapper == TONEMAPPER_REINHARD) { - return tonemap_reinhard(color, white); + return tonemap_reinhard(max(vec3(0.0f), color), white); } else if (params.tonemapper == TONEMAPPER_FILMIC) { - return tonemap_filmic(color, white); + return tonemap_filmic(max(vec3(0.0f), color), white); } else { // TONEMAPPER_ACES - return tonemap_aces(color, white); + return tonemap_aces(max(vec3(0.0f), color), white); } } @@ -298,15 +316,15 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { const float FXAA_SPAN_MAX = 8.0; #ifdef MULTIVIEW - vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure; - vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure; - vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure; - vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure; + vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; + vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; + vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; + vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; #else - 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 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; + vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; + vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; + vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; #endif vec3 rgbM = color; vec3 luma = vec3(0.299, 0.587, 0.114); @@ -333,11 +351,11 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { params.pixel_size; #ifdef MULTIVIEW - vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz); - vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz); + vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz) * params.luminance_multiplier; + vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz) * params.luminance_multiplier; #else - vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz); - vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz); + vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz) * params.luminance_multiplier; + vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz) * params.luminance_multiplier; #endif float lumaB = dot(rgbB, luma); @@ -349,7 +367,7 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { } #endif // !SUBPASS -// From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf +// From https://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf // and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom) // NOTE: `frag_coord` is in pixels (i.e. not normalized UV). vec3 screen_space_dither(vec2 frag_coord) { @@ -364,11 +382,11 @@ vec3 screen_space_dither(vec2 frag_coord) { void main() { #ifdef SUBPASS // SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer - vec3 color = subpassLoad(input_color).rgb; -#elif MULTIVIEW - vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb; + vec3 color = subpassLoad(input_color).rgb * params.luminance_multiplier; +#elif defined(MULTIVIEW) + vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb * params.luminance_multiplier; #else - vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb; + vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb * params.luminance_multiplier; #endif // Exposure @@ -377,7 +395,7 @@ void main() { #ifndef SUBPASS if (params.use_auto_exposure) { - exposure *= 1.0 / (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.luminance_multiplier / params.auto_exposure_grey); } #endif @@ -386,7 +404,7 @@ void main() { // Early Tonemap & SRGB Conversion #ifndef SUBPASS if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) { - vec3 glow = gather_glow(source_glow, uv_interp); + vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier; color.rgb = mix(color.rgb, glow, params.glow_intensity); } @@ -401,9 +419,7 @@ void main() { color += screen_space_dither(gl_FragCoord.xy); } - // Ensure color values passed to tonemappers are positive. - // They can be negative in the case of negative lights, which leads to undesired behavior. - color = apply_tonemapping(max(vec3(0.0), color), params.white); + color = apply_tonemapping(color, params.white); color = linear_to_srgb(color); // regular linear -> SRGB conversion @@ -411,7 +427,7 @@ void main() { // Glow if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) { - vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity; + vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity * params.luminance_multiplier; // high dynamic range -> SRGB glow = apply_tonemapping(glow, params.white); diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl index 49a493cdc7..779f04ed35 100644 --- a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl +++ b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl @@ -71,11 +71,6 @@ lights; layout(set = 0, binding = 5) uniform texture3D color_texture; -#ifdef MODE_ANISOTROPIC -layout(set = 0, binding = 7) uniform texture3D aniso_pos_texture; -layout(set = 0, binding = 8) uniform texture3D aniso_neg_texture; -#endif // MODE ANISOTROPIC - #endif // MODE_SECOND_BOUNCE #ifndef MODE_DYNAMIC @@ -110,13 +105,6 @@ layout(set = 0, binding = 10) uniform sampler texture_sampler; layout(rgba8, set = 0, binding = 5) uniform restrict writeonly image3D color_tex; -#ifdef MODE_ANISOTROPIC - -layout(r16ui, set = 0, binding = 6) uniform restrict writeonly uimage3D aniso_pos_tex; -layout(r16ui, set = 0, binding = 7) uniform restrict writeonly uimage3D aniso_neg_tex; - -#endif - #endif #ifdef MODE_DYNAMIC @@ -170,13 +158,6 @@ layout(r32f, set = 0, binding = 8) uniform restrict writeonly image2D depth; layout(rgba8, set = 0, binding = 11) uniform restrict image3D color_texture; -#ifdef MODE_ANISOTROPIC - -layout(r16ui, set = 0, binding = 12) uniform restrict writeonly uimage3D aniso_pos_texture; -layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_neg_texture; - -#endif // MODE ANISOTROPIC - #endif //MODE_DYNAMIC_SHRINK_PLOT #endif // MODE_DYNAMIC_SHRINK @@ -374,12 +355,7 @@ void main() { vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz; -#ifdef MODE_ANISOTROPIC - vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); -#else vec3 accum = vec3(0.0); -#endif for (uint i = 0; i < params.light_count; i++) { vec3 light; @@ -390,38 +366,16 @@ void main() { light *= albedo.rgb; -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light; - } -#else if (length(normal) > 0.2) { accum += max(0.0, dot(normal, -light_dir)) * light; } else { //all directions accum += light; } -#endif } -#ifdef MODE_ANISOTROPIC - - for (uint i = 0; i < 6; i++) { - vec3 light = accum[i]; - if (length(normal) > 0.2) { - light += max(0.0, dot(accum_dirs[i], -normal)) * emission; - } else { - light += emission; - } - - outputs.data[cell_index * 6 + i] = vec4(light, 0.0); - } - -#else outputs.data[cell_index] = vec4(accum + emission, 0.0); -#endif - #endif //MODE_COMPUTE_LIGHT /////////////////SECOND BOUNCE/////////////////////////////// @@ -431,32 +385,8 @@ void main() { ivec3 ipos = ivec3(posu); vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); -#ifdef MODE_ANISOTROPIC - vec3 accum[6]; - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); - - /*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range; - vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb; - vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb; - accum[0]=src_col * src_aniso_pos.x; - accum[1]=src_col * src_aniso_neg.x; - accum[2]=src_col * src_aniso_pos.y; - accum[3]=src_col * src_aniso_neg.y; - accum[4]=src_col * src_aniso_pos.z; - accum[5]=src_col * src_aniso_neg.z;*/ - - accum[0] = outputs.data[cell_index * 6 + 0].rgb; - accum[1] = outputs.data[cell_index * 6 + 1].rgb; - accum[2] = outputs.data[cell_index * 6 + 2].rgb; - accum[3] = outputs.data[cell_index * 6 + 3].rgb; - accum[4] = outputs.data[cell_index * 6 + 4].rgb; - accum[5] = outputs.data[cell_index * 6 + 5].rgb; - -#else vec3 accum = outputs.data[cell_index].rgb; -#endif - if (length(normal.xyz) > 0.2) { vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); vec3 tangent = normalize(cross(v0, normal.xyz)); @@ -484,9 +414,6 @@ void main() { float max_distance = length(vec3(params.limits)); vec3 cell_size = 1.0 / vec3(params.limits); -#ifdef MODE_ANISOTROPIC - vec3 aniso_normal = mix(direction, normal.xyz, params.aniso_strength); -#endif while (dist < max_distance && color.a < 0.95) { float diameter = max(1.0, 2.0 * tan_half_angle * dist); vec3 uvw_pos = (pos + dist * direction) * cell_size; @@ -498,42 +425,18 @@ void main() { float log2_diameter = log2(diameter); vec4 scolor = textureLod(sampler3D(color_texture, texture_sampler), uvw_pos, log2_diameter); -#ifdef MODE_ANISOTROPIC - - vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture, texture_sampler), uvw_pos, log2_diameter).rgb; - vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture, texture_sampler), uvw_pos, log2_diameter).rgb; - - scolor.rgb *= dot(max(vec3(0.0), (aniso_normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-aniso_normal * aniso_neg)), vec3(1.0)); -#endif float a = (1.0 - color.a); color += a * scolor; dist += half_diameter; } } color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb; - } -#else accum += color.rgb; -#endif } } -#ifdef MODE_ANISOTROPIC - - outputs.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); - outputs.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); - outputs.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); - outputs.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); - outputs.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); - outputs.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); -#else outputs.data[cell_index] = vec4(accum, 0.0); -#endif - #endif // MODE_SECOND_BOUNCE /////////////////UPDATE MIPMAPS/////////////////////////////// @@ -541,45 +444,20 @@ void main() { #ifdef MODE_UPDATE_MIPMAPS { -#ifdef MODE_ANISOTROPIC - vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); -#else vec3 light_accum = vec3(0.0); -#endif float count = 0.0; for (uint i = 0; i < 8; i++) { uint child_index = cell_children.data[cell_index].children[i]; if (child_index == NO_CHILDREN) { continue; } -#ifdef MODE_ANISOTROPIC - light_accum[0] += outputs.data[child_index * 6 + 0].rgb; - light_accum[1] += outputs.data[child_index * 6 + 1].rgb; - light_accum[2] += outputs.data[child_index * 6 + 2].rgb; - light_accum[3] += outputs.data[child_index * 6 + 3].rgb; - light_accum[4] += outputs.data[child_index * 6 + 4].rgb; - light_accum[5] += outputs.data[child_index * 6 + 5].rgb; - -#else light_accum += outputs.data[child_index].rgb; -#endif - count += 1.0; } float divisor = mix(8.0, count, params.propagation); -#ifdef MODE_ANISOTROPIC - outputs.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); - outputs.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); - outputs.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); - outputs.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); - outputs.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); - outputs.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); - -#else outputs.data[cell_index] = vec4(light_accum / divisor, 0.0); -#endif } #endif @@ -587,40 +465,7 @@ void main() { #ifdef MODE_WRITE_TEXTURE { -#ifdef MODE_ANISOTROPIC - vec3 accum_total = vec3(0.0); - accum_total += outputs.data[cell_index * 6 + 0].rgb; - accum_total += outputs.data[cell_index * 6 + 1].rgb; - accum_total += outputs.data[cell_index * 6 + 2].rgb; - accum_total += outputs.data[cell_index * 6 + 3].rgb; - accum_total += outputs.data[cell_index * 6 + 4].rgb; - accum_total += outputs.data[cell_index * 6 + 5].rgb; - - float accum_total_energy = max(dot(accum_total, GREY_VEC), 0.00001); - vec3 iso_positive = vec3(dot(outputs.data[cell_index * 6 + 0].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 2].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 4].rgb, GREY_VEC)) / vec3(accum_total_energy); - vec3 iso_negative = vec3(dot(outputs.data[cell_index * 6 + 1].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 3].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 5].rgb, GREY_VEC)) / vec3(accum_total_energy); - - { - uint aniso_pos = uint(clamp(iso_positive.b * 31.0, 0.0, 31.0)); - aniso_pos |= uint(clamp(iso_positive.g * 63.0, 0.0, 63.0)) << 5; - aniso_pos |= uint(clamp(iso_positive.r * 31.0, 0.0, 31.0)) << 11; - imageStore(aniso_pos_tex, ivec3(posu), uvec4(aniso_pos)); - } - - { - uint aniso_neg = uint(clamp(iso_negative.b * 31.0, 0.0, 31.0)); - aniso_neg |= uint(clamp(iso_negative.g * 63.0, 0.0, 63.0)) << 5; - aniso_neg |= uint(clamp(iso_negative.r * 31.0, 0.0, 31.0)) << 11; - imageStore(aniso_neg_tex, ivec3(posu), uvec4(aniso_neg)); - } - - imageStore(color_tex, ivec3(posu), vec4(accum_total / params.dynamic_range, albedo.a)); - -#else - imageStore(color_tex, ivec3(posu), vec4(outputs.data[cell_index].rgb / params.dynamic_range, albedo.a)); - -#endif } #endif @@ -763,13 +608,6 @@ void main() { color.rgb /= params.dynamic_range; imageStore(color_texture, pos3d, color); //imageStore(color_texture,pos3d,vec4(1,1,1,1)); - -#ifdef MODE_ANISOTROPIC - //do not care about anisotropy for dynamic objects, just store full lit in all directions - imageStore(aniso_pos_texture, pos3d, uvec4(0xFFFF)); - imageStore(aniso_neg_texture, pos3d, uvec4(0xFFFF)); - -#endif // ANISOTROPIC } #endif // MODE_DYNAMIC_SHRINK_PLOT } diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl index 7d4d72967a..281c496df3 100644 --- a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl @@ -20,11 +20,6 @@ layout(set = 0, binding = 2) uniform texture3D color_tex; layout(set = 0, binding = 3) uniform sampler tex_sampler; -#ifdef USE_ANISOTROPY -layout(set = 0, binding = 4) uniform texture3D aniso_pos_tex; -layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex; -#endif - layout(push_constant, binding = 0, std430) uniform Params { mat4 projection; uint cell_offset; |