diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 8f79a02c0b1..bb96aec5178 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -723,6 +723,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p //print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale)); state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5); + state_buffer.shadow_pixel_size = 1.0f / (float)(state.shadow_texture_size); state_buffer.flags = use_linear_colors ? CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0; @@ -1923,11 +1924,9 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render); RD::SamplerState shadow_sampler_state; - shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; shadow_sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; //shadow wrap around - shadow_sampler_state.compare_op = RD::COMPARE_OP_GREATER; - shadow_sampler_state.enable_compare = true; state.shadow_sampler = RD::get_singleton()->sampler_create(shadow_sampler_state); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 23b293767c8..aa0bfe3cc1d 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -550,8 +550,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t directional_light_count; float tex_to_sdf; + float shadow_pixel_size; uint32_t flags; - uint32_t pad2; }; DataBuffer canvas_instance_data_buffers[BATCH_DATA_BUFFER_COUNT]; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index 2cd52c0b938..acaabaa358b 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -286,6 +286,17 @@ vec2 sdf_to_screen_uv(vec2 p_sdf) { return p_sdf * canvas_data.sdf_to_screen; } +// Emulate textureProjLod by doing it manually because the source texture is not an actual depth texture that can be used for this operation. +// Since the sampler is configured to nearest use one textureGather tap to emulate bilinear. +float texture_shadow(vec4 p) { + // Manually round p to the nearest texel because textureGather uses strange rounding rules. + vec2 unit_p = floor(p.xy / canvas_data.shadow_pixel_size) * canvas_data.shadow_pixel_size; + float depth = p.z; + float fx = fract(p.x / canvas_data.shadow_pixel_size); + vec2 tap = textureGather(sampler2D(shadow_atlas_texture, shadow_sampler), unit_p.xy).zw; + return mix(step(tap.y, depth), step(tap.x, depth), fx); +} + #GLOBALS #ifdef LIGHT_CODE_USED @@ -396,32 +407,32 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK; if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) { - shadow = textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x; + shadow = texture_shadow(shadow_uv); } else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) { vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); shadow = 0.0; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x; + shadow += texture_shadow(shadow_uv - shadow_pixel_size * 2.0); + shadow += texture_shadow(shadow_uv - shadow_pixel_size); + shadow += texture_shadow(shadow_uv); + shadow += texture_shadow(shadow_uv + shadow_pixel_size); + shadow += texture_shadow(shadow_uv + shadow_pixel_size * 2.0); shadow /= 5.0; } else { //PCF13 vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); shadow = 0.0; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 6.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 5.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 4.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 3.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 3.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 4.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 5.0, 0.0).x; - shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 6.0, 0.0).x; + shadow += texture_shadow(shadow_uv - shadow_pixel_size * 6.0); + shadow += texture_shadow(shadow_uv - shadow_pixel_size * 5.0); + shadow += texture_shadow(shadow_uv - shadow_pixel_size * 4.0); + shadow += texture_shadow(shadow_uv - shadow_pixel_size * 3.0); + shadow += texture_shadow(shadow_uv - shadow_pixel_size * 2.0); + shadow += texture_shadow(shadow_uv - shadow_pixel_size); + shadow += texture_shadow(shadow_uv); + shadow += texture_shadow(shadow_uv + shadow_pixel_size); + shadow += texture_shadow(shadow_uv + shadow_pixel_size * 2.0); + shadow += texture_shadow(shadow_uv + shadow_pixel_size * 3.0); + shadow += texture_shadow(shadow_uv + shadow_pixel_size * 4.0); + shadow += texture_shadow(shadow_uv + shadow_pixel_size * 5.0); + shadow += texture_shadow(shadow_uv + shadow_pixel_size * 6.0); shadow /= 13.0; } diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index ba228f04328..32180e8c2a5 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -109,8 +109,8 @@ layout(set = 0, binding = 1, std140) uniform CanvasData { uint directional_light_count; float tex_to_sdf; + float shadow_pixel_size; uint flags; - uint pad2; } canvas_data;