diff options
Diffstat (limited to 'servers/rendering/renderer_rd/shaders')
13 files changed, 662 insertions, 335 deletions
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/blur_raster.glsl new file mode 100644 index 0000000000..b1d1c2365e --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/blur_raster.glsl @@ -0,0 +1,228 @@ +/* clang-format off */ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +#include "blur_raster_inc.glsl" + +layout(location = 0) out vec2 uv_interp; +/* clang-format on */ + +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_interp = base_arr[gl_VertexIndex]; + + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); +} + +/* clang-format off */ +#[fragment] + +#version 450 + +#VERSION_DEFINES + +#include "blur_raster_inc.glsl" + +layout(location = 0) in vec2 uv_interp; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform sampler2D source_color; + +#ifdef GLOW_USE_AUTO_EXPOSURE +layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; +#endif + +layout(location = 0) out vec4 frag_color; + +//DOF +#ifdef MODE_DOF_BLUR + +layout(set = 1, binding = 0) uniform sampler2D dof_source_depth; + +#ifdef DOF_QUALITY_LOW +const int dof_kernel_size = 5; +const int dof_kernel_from = 2; +const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388); +#endif + +#ifdef DOF_QUALITY_MEDIUM +const int dof_kernel_size = 11; +const int dof_kernel_from = 5; +const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037); + +#endif + +#ifdef DOF_QUALITY_HIGH +const int dof_kernel_size = 21; +const int dof_kernel_from = 10; +const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174); +#endif + +#endif + +void main() { +#ifdef MODE_MIPMAP + + vec2 pix_size = blur.pixel_size; + vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size); + frag_color = color / 4.0; + +#endif + +#ifdef MODE_GAUSSIAN_BLUR + + //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect + + if (bool(blur.flags & FLAG_HORIZONTAL)) { + vec2 pix_size = blur.pixel_size; + pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607; + color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879; + color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514; + color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303; + color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879; + color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514; + color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303; + frag_color = color; + } else { + vec2 pix_size = blur.pixel_size; + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774; + color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477; + color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136; + color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477; + color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136; + frag_color = color; + } +#endif + +#ifdef MODE_GAUSSIAN_GLOW + + //Glow uses larger sigma 1 for a more rounded blur effect + +#define GLOW_ADD(m_ofs, m_mult) \ + { \ + vec2 ofs = uv_interp + m_ofs * pix_size; \ + vec4 c = texture(source_color, ofs) * m_mult; \ + if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \ + c *= 0.0; \ + } \ + color += c; \ + } + + if (bool(blur.flags & FLAG_HORIZONTAL)) { + vec2 pix_size = blur.pixel_size; + pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938; + GLOW_ADD(vec2(1.0, 0.0), 0.165569); + GLOW_ADD(vec2(2.0, 0.0), 0.140367); + GLOW_ADD(vec2(3.0, 0.0), 0.106595); + GLOW_ADD(vec2(-1.0, 0.0), 0.165569); + GLOW_ADD(vec2(-2.0, 0.0), 0.140367); + GLOW_ADD(vec2(-3.0, 0.0), 0.106595); + color *= blur.glow_strength; + frag_color = color; + } else { + vec2 pix_size = blur.pixel_size; + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713; + GLOW_ADD(vec2(0.0, 1.0), 0.233062); + GLOW_ADD(vec2(0.0, 2.0), 0.122581); + GLOW_ADD(vec2(0.0, -1.0), 0.233062); + GLOW_ADD(vec2(0.0, -2.0), 0.122581); + color *= blur.glow_strength; + frag_color = color; + } + +#undef GLOW_ADD + + if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) { +#ifdef GLOW_USE_AUTO_EXPOSURE + + frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey; +#endif + frag_color *= blur.glow_exposure; + + float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); + float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom); + + frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)); + } + +#endif + +#ifdef MODE_DOF_BLUR + + vec4 color_accum = vec4(0.0); + + float depth = texture(dof_source_depth, uv_interp, 0.0).r; + depth = depth * 2.0 - 1.0; + + if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { + depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; + } else { + depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near)); + } + + // mix near and far blur amount + float amount = 1.0; + if (bool(blur.flags & FLAG_DOF_FAR)) { + amount *= 1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, depth); + } + if (bool(blur.flags & FLAG_DOF_NEAR)) { + amount *= smoothstep(blur.dof_near_end, blur.dof_near_begin, depth); + } + amount = 1.0 - amount; + + if (amount > 0.0) { + float k_accum = 0.0; + + for (int i = 0; i < dof_kernel_size; i++) { + int int_ofs = i - dof_kernel_from; + vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius; + + float tap_k = dof_kernel[i]; + + float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r; + tap_depth = tap_depth * 2.0 - 1.0; + + if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { + tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; + } else { + tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near)); + } + + // mix near and far blur amount + float tap_amount = 1.0; + if (bool(blur.flags & FLAG_DOF_FAR)) { + tap_amount *= mix(1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, tap_depth), 0.0, int_ofs == 0); + } + if (bool(blur.flags & FLAG_DOF_NEAR)) { + tap_amount *= mix(smoothstep(blur.dof_near_end, blur.dof_near_begin, tap_depth), 0.0, int_ofs == 0); + } + tap_amount = 1.0 - tap_amount; + + tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect + + vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k; + + k_accum += tap_k * tap_amount; + color_accum += tap_color * tap_amount; + } + + if (k_accum > 0.0) { + color_accum /= k_accum; + } + + frag_color = color_accum; ///k_accum; + } else { + // we are in focus, don't waste time + frag_color = texture(source_color, uv_interp, 0.0); + } + +#endif +} diff --git a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl new file mode 100644 index 0000000000..6ea968e595 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl @@ -0,0 +1,36 @@ +#define FLAG_HORIZONTAL (1 << 0) +#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1) +#define FLAG_GLOW_FIRST_PASS (1 << 2) +#define FLAG_DOF_FAR (1 << 3) +#define FLAG_DOF_NEAR (1 << 4) + +layout(push_constant, binding = 1, std430) uniform Blur { + vec2 pixel_size; + uint flags; + uint pad; + + // Glow. + float glow_strength; + float glow_bloom; + float glow_hdr_threshold; + float glow_hdr_scale; + + float glow_exposure; + float glow_white; + float glow_luminance_cap; + float glow_auto_exposure_grey; + + // DOF. + float dof_far_begin; + float dof_far_end; + float dof_near_begin; + float dof_near_end; + + float dof_radius; + float dof_pad[3]; + + vec2 dof_dir; + float camera_z_far; + float camera_z_near; +} +blur; diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl new file mode 100644 index 0000000000..29ebd74a90 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl @@ -0,0 +1,74 @@ +/* clang-format off */ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +#include "luminance_reduce_raster_inc.glsl" + +layout(location = 0) out vec2 uv_interp; +/* clang-format on */ + +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_interp = base_arr[gl_VertexIndex]; + + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); +} + +/* clang-format off */ +#[fragment] + +#version 450 + +#VERSION_DEFINES + +#include "luminance_reduce_raster_inc.glsl" + +layout(location = 0) in vec2 uv_interp; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform sampler2D source_exposure; + +#ifdef FINAL_PASS +layout(set = 1, binding = 0) uniform sampler2D prev_luminance; +#endif + +layout(location = 0) out highp float luminance; + +void main() { + ivec2 dest_pos = ivec2(uv_interp * settings.dest_size); + ivec2 src_pos = ivec2(uv_interp * settings.source_size); + + ivec2 next_pos = (dest_pos + ivec2(1)) * settings.source_size / settings.dest_size; + next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel + + highp vec3 source_color = vec3(0.0); + for (int i = src_pos.x; i < next_pos.x; i++) { + for (int j = src_pos.y; j < next_pos.y; j++) { + source_color += texelFetch(source_exposure, ivec2(i, j), 0).rgb; + } + } + + source_color /= float((next_pos.x - src_pos.x) * (next_pos.y - src_pos.y)); + +#ifdef FIRST_PASS + luminance = max(source_color.r, max(source_color.g, source_color.b)); + + // This formula should be more "accurate" but gave an overexposed result when testing. + // Leaving it here so we can revisit it if we want. + // luminance = source_color.r * 0.21 + source_color.g * 0.71 + source_color.b * 0.07; +#else + luminance = source_color.r; +#endif + +#ifdef FINAL_PASS + // Obtain our target luminance + luminance = clamp(luminance, settings.min_luminance, settings.max_luminance); + + // Now smooth to our transition + highp float prev_lum = texelFetch(prev_luminance, ivec2(0, 0), 0).r; //1 pixel previous luminance + luminance = prev_lum + (luminance - prev_lum) * clamp(settings.exposure_adjust, 0.0, 1.0); +#endif +} diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl new file mode 100644 index 0000000000..ed389ffe56 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl @@ -0,0 +1,11 @@ + +layout(push_constant, binding = 1, std430) uniform PushConstant { + ivec2 source_size; + ivec2 dest_size; + + float exposure_adjust; + float min_luminance; + float max_luminance; + float pad; +} +settings; diff --git a/servers/rendering/renderer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl index 4dceeea995..e88e68b511 100644 --- a/servers/rendering/renderer_rd/shaders/particles_copy.glsl +++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl @@ -138,7 +138,7 @@ void main() { if (bool(particles.data[particle].flags & PARTICLE_FLAG_ACTIVE) || bool(particles.data[particle].flags & PARTICLE_FLAG_TRAILED)) { txform = particles.data[particle].xform; if (params.trail_size > 1) { - // since the steps dont fit precisely in the history frames, must do a tiny bit of + // Since the steps don't fit precisely in the history frames, must do a tiny bit of // interpolation to get them close to their intended location. uint part_ofs = particle % params.trail_size; float natural_ofs = fract((float(part_ofs) / float(params.trail_size)) * float(params.trail_total)) * params.frame_delta; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 74d5af5cb6..b3a349c948 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -356,6 +356,24 @@ void main() { #VERSION_DEFINES +/* Specialization Constants (Toggles) */ + +layout(constant_id = 0) const bool sc_use_forward_gi = false; +layout(constant_id = 1) const bool sc_use_light_projector = false; +layout(constant_id = 2) const bool sc_use_light_soft_shadows = false; +layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false; + +/* Specialization Constants (Values) */ + +layout(constant_id = 6) const uint sc_soft_shadow_samples = 4; +layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4; + +layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4; +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; + #include "scene_forward_clustered_inc.glsl" /* Varyings */ @@ -450,12 +468,8 @@ layout(location = 0) out vec4 frag_color; #include "scene_forward_lights_inc.glsl" -#ifdef USE_FORWARD_GI - #include "scene_forward_gi_inc.glsl" -#endif //USE_FORWARD_GI - #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) #ifndef MODE_RENDER_DEPTH @@ -793,25 +807,35 @@ void main() { continue; //out of decal } - //we need ddx/ddy for mipmaps, so simulate them - vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz; - vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz; - float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade); if (decals.data[decal_index].normal_fade > 0.0) { fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5); } + //we need ddx/ddy for mipmaps, so simulate them + vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz; + vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz; + if (decals.data[decal_index].albedo_rect != vec4(0.0)) { //has albedo - vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw); + vec4 decal_albedo; + if (sc_decal_use_mipmaps) { + decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw); + } else { + decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0); + } decal_albedo *= decals.data[decal_index].modulate; decal_albedo.a *= fade; albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix); if (decals.data[decal_index].normal_rect != vec4(0.0)) { - vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz; + vec3 decal_normal; + if (sc_decal_use_mipmaps) { + decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz; + } else { + decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz; + } decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy))); //convert to view space, use xzy because y is up @@ -821,7 +845,12 @@ void main() { } if (decals.data[decal_index].orm_rect != vec4(0.0)) { - vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz; + vec3 decal_orm; + if (sc_decal_use_mipmaps) { + decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz; + } else { + decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz; + } ao = mix(ao, decal_orm.r, decal_albedo.a); roughness = mix(roughness, decal_orm.g, decal_albedo.a); metallic = mix(metallic, decal_orm.b, decal_albedo.a); @@ -830,7 +859,11 @@ void main() { if (decals.data[decal_index].emission_rect != vec4(0.0)) { //emission is additive, so its independent from albedo - emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + if (sc_decal_use_mipmaps) { + emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + } else { + emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade; + } } } } @@ -963,9 +996,9 @@ void main() { ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb; } } -#elif defined(USE_FORWARD_GI) +#else - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture + if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture //make vertex orientation the world one, but still align to camera vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex; @@ -1037,7 +1070,7 @@ void main() { } } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances + if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); @@ -1068,9 +1101,8 @@ void main() { specular_light = spec_accum.rgb; ambient_light = amb_accum.rgb; } -#else - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers + if (!sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers vec2 coord; @@ -1101,7 +1133,7 @@ void main() { ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a); specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a); } -#endif +#endif // !USE_LIGHTMAP if (scene_data.ssao_enabled) { float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; @@ -1182,7 +1214,7 @@ void main() { specular_light *= specular * metallic * albedo * 2.0; #else - // scales the specular reflections, needs to be be computed before lighting happens, + // scales the specular reflections, needs to be computed before lighting happens, // but after environment, GI, and reflection probes are added // Environment brdf approximation (Lazarov 2013) // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile @@ -1228,14 +1260,13 @@ void main() { float shadow = 1.0; -#ifdef USE_SOFT_SHADOWS //version with soft shadows, more expensive if (directional_lights.data[i].shadow_enabled) { - float depth_z = -vertex.z; + if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) { + float depth_z = -vertex.z; - vec4 pssm_coord; - vec3 shadow_color = vec3(0.0); - vec3 light_dir = directional_lights.data[i].direction; + vec3 shadow_color = vec3(0.0); + vec3 light_dir = directional_lights.data[i].direction; #define BIAS_FUNC(m_var, m_idx) \ m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \ @@ -1243,168 +1274,105 @@ void main() { normal_bias -= light_dir * dot(light_dir, normal_bias); \ m_var.xyz += normal_bias; - if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { - vec4 v = vec4(vertex, 1.0); + uint blend_index = 0; - BIAS_FUNC(v, 0) + if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + vec4 v = vec4(vertex, 1.0); - pssm_coord = (directional_lights.data[i].shadow_matrix1 * v); - pssm_coord /= pssm_coord.w; + BIAS_FUNC(v, 0) + + vec4 pssm_coord = (directional_lights.data[i].shadow_matrix1 * v); + pssm_coord /= pssm_coord.w; - if (directional_lights.data[i].softshadow_angle > 0) { float range_pos = dot(directional_lights.data[i].direction, v.xyz); float range_begin = directional_lights.data[i].shadow_range_begin.x; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius; shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + blend_index++; } - shadow_color = directional_lights.data[i].shadow_color1.rgb; - - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { - vec4 v = vec4(vertex, 1.0); + if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.y) { + vec4 v = vec4(vertex, 1.0); - BIAS_FUNC(v, 1) + BIAS_FUNC(v, 1) - pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); - pssm_coord /= pssm_coord.w; + vec4 pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); + pssm_coord /= pssm_coord.w; - if (directional_lights.data[i].softshadow_angle > 0) { float range_pos = dot(directional_lights.data[i].direction, v.xyz); float range_begin = directional_lights.data[i].shadow_range_begin.y; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + + if (blend_index == 0) { + shadow = s; + } else { + //blend + float blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); + shadow = mix(shadow, s, blend); + } + + blend_index++; } - shadow_color = directional_lights.data[i].shadow_color2.rgb; - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { - vec4 v = vec4(vertex, 1.0); + if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.z) { + vec4 v = vec4(vertex, 1.0); - BIAS_FUNC(v, 2) + BIAS_FUNC(v, 2) - pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); - pssm_coord /= pssm_coord.w; + vec4 pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); + pssm_coord /= pssm_coord.w; - if (directional_lights.data[i].softshadow_angle > 0) { float range_pos = dot(directional_lights.data[i].direction, v.xyz); float range_begin = directional_lights.data[i].shadow_range_begin.z; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); - } - - shadow_color = directional_lights.data[i].shadow_color3.rgb; + float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - } else { - vec4 v = vec4(vertex, 1.0); - - BIAS_FUNC(v, 3) - - pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); - pssm_coord /= pssm_coord.w; + if (blend_index == 0) { + shadow = s; + } else { + //blend + float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); + shadow = mix(shadow, s, blend); + } - if (directional_lights.data[i].softshadow_angle > 0) { - float range_pos = dot(directional_lights.data[i].direction, v.xyz); - float range_begin = directional_lights.data[i].shadow_range_begin.w; - float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; - vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + blend_index++; } - shadow_color = directional_lights.data[i].shadow_color4.rgb; - } - - if (directional_lights.data[i].blend_splits) { - vec3 shadow_color_blend = vec3(0.0); - float pssm_blend; - float shadow2; - - if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + if (blend_index < 2) { vec4 v = vec4(vertex, 1.0); - BIAS_FUNC(v, 1) - pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); - pssm_coord /= pssm_coord.w; - if (directional_lights.data[i].softshadow_angle > 0) { - float range_pos = dot(directional_lights.data[i].direction, v.xyz); - float range_begin = directional_lights.data[i].shadow_range_begin.y; - float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; - vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - } else { - shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); - } + BIAS_FUNC(v, 3) - pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); - shadow_color_blend = directional_lights.data[i].shadow_color2.rgb; - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { - vec4 v = vec4(vertex, 1.0); - BIAS_FUNC(v, 2) - pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); + vec4 pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); pssm_coord /= pssm_coord.w; - if (directional_lights.data[i].softshadow_angle > 0) { - float range_pos = dot(directional_lights.data[i].direction, v.xyz); - float range_begin = directional_lights.data[i].shadow_range_begin.z; - float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; - vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - } else { - shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); - } - - pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); + float range_pos = dot(directional_lights.data[i].direction, v.xyz); + float range_begin = directional_lights.data[i].shadow_range_begin.w; + float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; + vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; + float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - shadow_color_blend = directional_lights.data[i].shadow_color3.rgb; - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { - vec4 v = vec4(vertex, 1.0); - BIAS_FUNC(v, 3) - pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); - pssm_coord /= pssm_coord.w; - if (directional_lights.data[i].softshadow_angle > 0) { - float range_pos = dot(directional_lights.data[i].direction, v.xyz); - float range_begin = directional_lights.data[i].shadow_range_begin.w; - float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; - vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + if (blend_index == 0) { + shadow = s; } else { - shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + //blend + float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); + shadow = mix(shadow, s, blend); } - - pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); - shadow_color_blend = directional_lights.data[i].shadow_color4.rgb; - } else { - pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached) } - pssm_blend = sqrt(pssm_blend); - - shadow = mix(shadow, shadow2, pssm_blend); - shadow_color = mix(shadow_color, shadow_color_blend, pssm_blend); - } - - shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance - #undef BIAS_FUNC - } -#else - // Soft shadow disabled version + } else { //no soft shadows - if (directional_lights.data[i].shadow_enabled) { - float depth_z = -vertex.z; + float depth_z = -vertex.z; - vec4 pssm_coord; - vec3 light_dir = directional_lights.data[i].direction; - vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))); + vec4 pssm_coord; + vec3 light_dir = directional_lights.data[i].direction; + vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))); #define BIAS_FUNC(m_var, m_idx) \ m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \ @@ -1412,70 +1380,70 @@ void main() { normal_bias -= light_dir * dot(light_dir, normal_bias); \ m_var.xyz += normal_bias; - if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { - vec4 v = vec4(vertex, 1.0); - - BIAS_FUNC(v, 0) - - pssm_coord = (directional_lights.data[i].shadow_matrix1 * v); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { - vec4 v = vec4(vertex, 1.0); - - BIAS_FUNC(v, 1) - - pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { - vec4 v = vec4(vertex, 1.0); - - BIAS_FUNC(v, 2) - - pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); - - } else { - vec4 v = vec4(vertex, 1.0); - - BIAS_FUNC(v, 3) - - pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); - } - - pssm_coord /= pssm_coord.w; - - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + vec4 v = vec4(vertex, 1.0); - if (directional_lights.data[i].blend_splits) { - float pssm_blend; + BIAS_FUNC(v, 0) - if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + pssm_coord = (directional_lights.data[i].shadow_matrix1 * v); + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { vec4 v = vec4(vertex, 1.0); + BIAS_FUNC(v, 1) + pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); - pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { vec4 v = vec4(vertex, 1.0); + BIAS_FUNC(v, 2) + pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); - pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { + + } else { vec4 v = vec4(vertex, 1.0); + BIAS_FUNC(v, 3) + pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); - pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); - } else { - pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached) } pssm_coord /= pssm_coord.w; - float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); - shadow = mix(shadow, shadow2, pssm_blend); - } + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + + if (directional_lights.data[i].blend_splits) { + float pssm_blend; + + if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + vec4 v = vec4(vertex, 1.0); + BIAS_FUNC(v, 1) + pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); + pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { + vec4 v = vec4(vertex, 1.0); + BIAS_FUNC(v, 2) + pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); + pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { + vec4 v = vec4(vertex, 1.0); + BIAS_FUNC(v, 3) + pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); + pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); + } else { + pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached) + } - shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance + pssm_coord /= pssm_coord.w; + + float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow = mix(shadow, shadow2, pssm_blend); + } + + shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance #undef BIAS_FUNC - } -#endif + } + } // shadows if (i < 4) { shadow0 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << (i * 8); @@ -1554,7 +1522,9 @@ void main() { blur_shadow(shadow); - light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, + float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0; + + light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1573,9 +1543,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SOFT_SHADOW - directional_lights.data[i].size, -#endif #ifdef USE_SHADOW_TO_OPACITY alpha, #endif diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index 6599a42bab..b53bf6a6d4 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -52,6 +52,10 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12]; layout(set = 0, binding = 2) uniform sampler shadow_sampler; +layout(set = 0, binding = 3) uniform sampler decal_sampler; + +layout(set = 0, binding = 4) uniform sampler light_projector_sampler; + #define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5) #define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6) #define INSTANCE_FLAGS_USE_SDFGI (1 << 7) @@ -67,22 +71,22 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; //3 bits of stride #define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF -layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights { +layout(set = 0, binding = 5, std430) restrict readonly buffer OmniLights { LightData data[]; } omni_lights; -layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights { +layout(set = 0, binding = 6, std430) restrict readonly buffer SpotLights { LightData data[]; } spot_lights; -layout(set = 0, binding = 5, std430) restrict readonly buffer ReflectionProbeData { +layout(set = 0, binding = 7, std430) restrict readonly buffer ReflectionProbeData { ReflectionData data[]; } reflections; -layout(set = 0, binding = 6, std140) uniform DirectionalLights { +layout(set = 0, binding = 8, std140) uniform DirectionalLights { DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; } directional_lights; @@ -94,7 +98,7 @@ struct Lightmap { mat3 normal_xform; }; -layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps { +layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps { Lightmap data[]; } lightmaps; @@ -103,20 +107,20 @@ struct LightmapCapture { vec4 sh[9]; }; -layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures { +layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures { LightmapCapture data[]; } lightmap_captures; -layout(set = 0, binding = 9) uniform texture2D decal_atlas; -layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb; +layout(set = 0, binding = 11) uniform texture2D decal_atlas; +layout(set = 0, binding = 12) uniform texture2D decal_atlas_srgb; -layout(set = 0, binding = 11, std430) restrict readonly buffer Decals { +layout(set = 0, binding = 13, std430) restrict readonly buffer Decals { DecalData data[]; } decals; -layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData { vec4 data[]; } global_variables; @@ -128,7 +132,7 @@ struct SDFVoxelGICascadeData { float to_cell; // 1/bounds * grid_size }; -layout(set = 0, binding = 13, std140) uniform SDFGI { +layout(set = 0, binding = 15, std140) uniform SDFGI { vec3 grid_size; uint max_cascades; @@ -173,17 +177,12 @@ layout(set = 1, binding = 0, std140) uniform SceneData { uint cluster_type_size; uint max_cluster_element_count_div_32; - //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted + // 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]; - uint directional_penumbra_shadow_samples; - uint directional_soft_shadow_samples; - uint penumbra_shadow_samples; - uint soft_shadow_samples; - vec4 ambient_light_color_energy; float ambient_color_sky_mix; 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 b6e89acb46..7039ea2942 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -73,7 +73,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) { return mix(vec3(dielectric), albedo, vec3(metallic)); } -void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, +void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -92,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, #ifdef LIGHT_ANISOTROPY_USED vec3 B, vec3 T, float anisotropy, #endif -#ifdef USE_SOFT_SHADOWS - float A, -#endif #ifdef USE_SHADOW_TO_OPACITY inout float alpha, #endif @@ -111,11 +108,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, #else -#ifdef USE_SOFT_SHADOWS float NdotL = min(A + dot(N, L), 1.0); -#else - float NdotL = dot(N, L); -#endif float cNdotL = max(NdotL, 0.0); // clamped NdotL float NdotV = dot(N, V); float cNdotV = max(NdotV, 0.0); @@ -125,19 +118,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, #endif #if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) -#ifdef USE_SOFT_SHADOWS float cNdotH = clamp(A + dot(N, H), 0.0, 1.0); -#else - float cNdotH = clamp(dot(N, H), 0.0, 1.0); -#endif #endif #if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) -#ifdef USE_SOFT_SHADOWS float cLdotH = clamp(A + dot(L, H), 0.0, 1.0); -#else - float cLdotH = clamp(dot(L, H), 0.0, 1.0); -#endif #endif float metallic = unpackUnorm4x8(orms).z; @@ -232,11 +217,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, #elif defined(SPECULAR_PHONG) vec3 R = normalize(-reflect(L, N)); -#ifdef USE_SOFT_SHADOWS float cRdotV = clamp(A + dot(R, V), 0.0, 1.0); -#else - float cRdotV = clamp(dot(R, V), 0.0, 1.0); -#endif float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float phong = pow(cRdotV, shininess); phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); @@ -320,7 +301,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve float depth = coord.z; //if only one sample is taken, take it from the center - if (scene_data.directional_soft_shadow_samples == 1) { + if (sc_directional_soft_shadow_samples == 1) { return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); } @@ -334,11 +315,11 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve float avg = 0.0; - for (uint i = 0; i < scene_data.directional_soft_shadow_samples; i++) { + for (uint i = 0; i < sc_directional_soft_shadow_samples; i++) { avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0)); } - return avg * (1.0 / float(scene_data.directional_soft_shadow_samples)); + return avg * (1.0 / float(sc_directional_soft_shadow_samples)); } float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { @@ -346,7 +327,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { float depth = coord.z; //if only one sample is taken, take it from the center - if (scene_data.soft_shadow_samples == 1) { + if (sc_soft_shadow_samples == 1) { return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); } @@ -360,11 +341,11 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { float avg = 0.0; - for (uint i = 0; i < scene_data.soft_shadow_samples; i++) { + for (uint i = 0; i < sc_soft_shadow_samples; i++) { avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0)); } - return avg * (1.0 / float(scene_data.soft_shadow_samples)); + return avg * (1.0 / float(sc_soft_shadow_samples)); } float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) { @@ -380,7 +361,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); } - for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) { + for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) { vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r; if (d < pssm_coord.z) { @@ -396,12 +377,12 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex tex_scale *= penumbra; float s = 0.0; - for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) { + for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) { vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0)); } - return s / float(scene_data.directional_penumbra_shadow_samples); + return s / float(sc_directional_penumbra_shadow_samples); } else { //no blockers found, so no shadow @@ -442,8 +423,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { float shadow; -#ifdef USE_SOFT_SHADOWS - if (omni_lights.data[idx].soft_shadow_size > 0.0) { + if (sc_use_light_soft_shadows && omni_lights.data[idx].soft_shadow_size > 0.0) { //soft shadow //find blocker @@ -468,7 +448,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { tangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale; bitangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale; - for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { + 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; @@ -505,7 +485,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { z_norm -= omni_lights.data[idx].inv_radius * omni_lights.data[idx].shadow_bias; shadow = 0.0; - for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { + 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; @@ -526,14 +506,13 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0)); } - shadow /= float(scene_data.penumbra_shadow_samples); + shadow /= float(sc_penumbra_shadow_samples); } else { //no blockers found, so no shadow shadow = 1.0; } } else { -#endif splane.xyz = normalize(splane.xyz); vec4 clamp_rect = omni_lights.data[idx].atlas_rect; @@ -553,9 +532,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { 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); -#ifdef USE_SOFT_SHADOWS } -#endif return shadow; } @@ -592,14 +569,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float light_attenuation = omni_attenuation; vec3 color = omni_lights.data[idx].color; -#ifdef USE_SOFT_SHADOWS float size_A = 0.0; - if (omni_lights.data[idx].size > 0.0) { + if (sc_use_light_soft_shadows && omni_lights.data[idx].size > 0.0) { float t = omni_lights.data[idx].size / max(0.001, light_length); size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); } -#endif #ifdef LIGHT_TRANSMITTANCE_USED float transmittance_z = transmittance_depth; //no transmittance by default @@ -633,9 +608,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v } #endif -#if 0 - - if (omni_lights.data[idx].projector_rect != vec4(0.0)) { + if (sc_use_light_projector && omni_lights.data[idx].projector_rect != vec4(0.0)) { vec3 local_v = (omni_lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz; local_v = normalize(local_v); @@ -653,46 +626,50 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v local_v.xy = local_v.xy * 0.5 + 0.5; vec2 proj_uv = local_v.xy * atlas_rect.zw; - vec2 proj_uv_ddx; - vec2 proj_uv_ddy; - { - vec3 local_v_ddx = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)).xyz; - local_v_ddx = normalize(local_v_ddx); + if (sc_projector_use_mipmaps) { + vec2 proj_uv_ddx; + vec2 proj_uv_ddy; + { + vec3 local_v_ddx = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)).xyz; + local_v_ddx = normalize(local_v_ddx); - if (local_v_ddx.z >= 0.0) { - local_v_ddx.z += 1.0; - } else { - local_v_ddx.z = 1.0 - local_v_ddx.z; - } + if (local_v_ddx.z >= 0.0) { + local_v_ddx.z += 1.0; + } else { + local_v_ddx.z = 1.0 - local_v_ddx.z; + } - local_v_ddx.xy /= local_v_ddx.z; - local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5; + local_v_ddx.xy /= local_v_ddx.z; + local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5; - proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv; + proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv; - vec3 local_v_ddy = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz; - local_v_ddy = normalize(local_v_ddy); + vec3 local_v_ddy = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz; + local_v_ddy = normalize(local_v_ddy); - if (local_v_ddy.z >= 0.0) { - local_v_ddy.z += 1.0; - } else { - local_v_ddy.z = 1.0 - local_v_ddy.z; - } + if (local_v_ddy.z >= 0.0) { + local_v_ddy.z += 1.0; + } else { + local_v_ddy.z = 1.0 - local_v_ddy.z; + } - local_v_ddy.xy /= local_v_ddy.z; - local_v_ddy.xy = local_v_ddy.xy * 0.5 + 0.5; + local_v_ddy.xy /= local_v_ddy.z; + local_v_ddy.xy = local_v_ddy.xy * 0.5 + 0.5; - proj_uv_ddy = local_v_ddy.xy * atlas_rect.zw - proj_uv; - } + proj_uv_ddy = local_v_ddy.xy * atlas_rect.zw - proj_uv; + } - vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy); - no_shadow = mix(no_shadow, proj.rgb, proj.a); + vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy); + color *= proj.rgb * proj.a; + } else { + vec4 proj = textureLod(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + atlas_rect.xy, 0.0); + color *= proj.rgb * proj.a; + } } -#endif light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -711,9 +688,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SOFT_SHADOWS - size_A, -#endif #ifdef USE_SHADOW_TO_OPACITY alpha, #endif @@ -747,8 +721,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { vec4 splane = (spot_lights.data[idx].shadow_matrix * v); splane /= splane.w; -#ifdef USE_SOFT_SHADOWS - if (spot_lights.data[idx].soft_shadow_size > 0.0) { + if (sc_use_light_soft_shadows && spot_lights.data[idx].soft_shadow_size > 0.0) { //soft shadow //find blocker @@ -768,11 +741,11 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { float uv_size = spot_lights.data[idx].soft_shadow_size * z_norm * spot_lights.data[idx].soft_shadow_scale; vec2 clamp_max = spot_lights.data[idx].atlas_rect.xy + spot_lights.data[idx].atlas_rect.zw; - for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { + for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size; suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max); float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r; - if (d < z_norm) { + if (d < splane.z) { blocker_average += d; blocker_count += 1.0; } @@ -785,13 +758,13 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { uv_size *= penumbra; shadow = 0.0; - for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) { + for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size; suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max); - shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0)); + shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0)); } - shadow /= float(scene_data.penumbra_shadow_samples); + shadow /= float(sc_penumbra_shadow_samples); } else { //no blockers found, so no shadow @@ -799,14 +772,11 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { } } else { -#endif //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); shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv); -#ifdef USE_SOFT_SHADOWS } -#endif return shadow; } @@ -816,6 +786,18 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { return 1.0; } +vec2 normal_to_panorama(vec3 n) { + n = normalize(n); + vec2 panorama_coords = vec2(atan(n.x, n.z), acos(-n.y)); + + if (panorama_coords.x < 0.0) { + panorama_coords.x += M_PI * 2.0; + } + + panorama_coords /= vec2(M_PI * 2.0, M_PI); + return panorama_coords; +} + void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, @@ -850,20 +832,12 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v vec3 color = spot_lights.data[idx].color; float specular_amount = spot_lights.data[idx].specular_amount; -#ifdef USE_SOFT_SHADOWS float size_A = 0.0; - if (spot_lights.data[idx].size > 0.0) { + if (sc_use_light_soft_shadows && spot_lights.data[idx].size > 0.0) { float t = spot_lights.data[idx].size / max(0.001, light_length); size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); } -#endif - - /* - if (spot_lights.data[idx].atlas_rect!=vec4(0.0)) { - //use projector texture - } - */ #ifdef LIGHT_TRANSMITTANCE_USED float transmittance_z = transmittance_depth; @@ -886,9 +860,32 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v } #endif //LIGHT_TRANSMITTANCE_USED + if (sc_use_light_projector && spot_lights.data[idx].projector_rect != vec4(0.0)) { + vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex, 1.0)); + splane /= splane.w; + + vec2 proj_uv = normal_to_panorama(splane.xyz) * spot_lights.data[idx].projector_rect.zw; + + if (sc_projector_use_mipmaps) { + //ensure we have proper mipmaps + vec4 splane_ddx = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)); + splane_ddx /= splane_ddx.w; + vec2 proj_uv_ddx = normal_to_panorama(splane_ddx.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv; + + vec4 splane_ddy = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)); + splane_ddy /= splane_ddy.w; + vec2 proj_uv_ddy = normal_to_panorama(splane_ddy.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv; + + vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + spot_lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy); + color *= proj.rgb * proj.a; + } else { + vec4 proj = textureLod(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + spot_lights.data[idx].projector_rect.xy, 0.0); + color *= proj.rgb * proj.a; + } + } light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -907,9 +904,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SOFT_SHADOW - size_A, -#endif #ifdef USE_SHADOW_TO_OPACITY alpha, #endif diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 1bc17e140f..70900a847c 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -370,6 +370,26 @@ void main() { #VERSION_DEFINES +/* Specialization Constants */ + +/* Specialization Constants (Toggles) */ + +layout(constant_id = 0) const bool sc_use_forward_gi = false; +layout(constant_id = 1) const bool sc_use_light_projector = false; +layout(constant_id = 2) const bool sc_use_light_soft_shadows = false; +layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false; + +/* Specialization Constants (Values) */ + +layout(constant_id = 6) const uint sc_soft_shadow_samples = 4; +layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4; + +layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4; +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; + /* Include our forward mobile UBOs definitions etc. */ #include "scene_forward_mobile_inc.glsl" @@ -961,7 +981,7 @@ void main() { specular_light *= specular * metallic * albedo * 2.0; #else - // scales the specular reflections, needs to be be computed before lighting happens, + // scales the specular reflections, needs to be computed before lighting happens, // but after environment, GI, and reflection probes are added // Environment brdf approximation (Lazarov 2013) // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile @@ -1284,7 +1304,7 @@ void main() { blur_shadow(shadow); - light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, + light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif 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 d4ebcbeec4..d9682d7b23 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -51,6 +51,9 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12]; layout(set = 0, binding = 2) uniform sampler shadow_sampler; +layout(set = 0, binding = 3) uniform sampler decal_sampler; +layout(set = 0, binding = 4) uniform sampler light_projector_sampler; + #define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5) #define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6) #define INSTANCE_FLAGS_USE_SDFGI (1 << 7) @@ -66,22 +69,22 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; //3 bits of stride #define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF -layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights { +layout(set = 0, binding = 5, std430) restrict readonly buffer OmniLights { LightData data[]; } omni_lights; -layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights { +layout(set = 0, binding = 6, std430) restrict readonly buffer SpotLights { LightData data[]; } spot_lights; -layout(set = 0, binding = 5, std430) restrict readonly buffer ReflectionProbeData { +layout(set = 0, binding = 7, std430) restrict readonly buffer ReflectionProbeData { ReflectionData data[]; } reflections; -layout(set = 0, binding = 6, std140) uniform DirectionalLights { +layout(set = 0, binding = 8, std140) uniform DirectionalLights { DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; } directional_lights; @@ -93,7 +96,7 @@ struct Lightmap { mat3 normal_xform; }; -layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps { +layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps { Lightmap data[]; } lightmaps; @@ -102,20 +105,20 @@ struct LightmapCapture { vec4 sh[9]; }; -layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures { +layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures { LightmapCapture data[]; } lightmap_captures; -layout(set = 0, binding = 9) uniform texture2D decal_atlas; -layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb; +layout(set = 0, binding = 11) uniform texture2D decal_atlas; +layout(set = 0, binding = 12) uniform texture2D decal_atlas_srgb; -layout(set = 0, binding = 11, std430) restrict readonly buffer Decals { +layout(set = 0, binding = 13, std430) restrict readonly buffer Decals { DecalData data[]; } decals; -layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData { vec4 data[]; } global_variables; @@ -135,17 +138,12 @@ layout(set = 1, binding = 0, std140) uniform SceneData { vec2 viewport_size; vec2 screen_pixel_size; - //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted + // 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]; - uint directional_penumbra_shadow_samples; - uint directional_soft_shadow_samples; - uint penumbra_shadow_samples; - uint soft_shadow_samples; - vec4 ambient_light_color_energy; float ambient_color_sky_mix; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl index 99db35bb34..d6e5c6a92e 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl @@ -20,10 +20,10 @@ layout(set = 0, binding = 3, std430) restrict readonly buffer DispatchData { dispatch_data; struct ProcessVoxel { - uint position; //xyz 7 bit packed, extra 11 bits for neigbours - uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours - uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours - uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours + uint position; // xyz 7 bit packed, extra 11 bits for neighbors. + uint albedo; // rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors. + uint light; // rgbe8985 encoded total saved light, extra 2 bits for neighbors. + uint light_aniso; // 55555 light anisotropy, extra 2 bits for neighbors. //total neighbours: 26 }; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl index bc376e9522..eedd28959c 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl @@ -266,9 +266,9 @@ void main() { } else if (params.sky_mode == SKY_MODE_SKY) { #ifdef USE_CUBEMAP_ARRAY - light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates + light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates. #else - light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates + light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates. #endif light.rgb *= params.sky_energy; light.a = 0.0; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl index aa4ded146f..4d9fa85a74 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl @@ -101,7 +101,7 @@ layout(set = 0, binding = 10, std430) restrict buffer DispatchData { dispatch_data; struct ProcessVoxel { - uint position; //xyz 7 bit packed, extra 11 bits for neigbours + uint position; // xyz 7 bit packed, extra 11 bits for neighbors. uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours @@ -134,7 +134,7 @@ layout(set = 0, binding = 5, std430) restrict buffer readonly DispatchData { dispatch_data; struct ProcessVoxel { - uint position; //xyz 7 bit packed, extra 11 bits for neigbours + uint position; // xyz 7 bit packed, extra 11 bits for neighbors. uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours @@ -183,7 +183,7 @@ void main() { ivec3 write_pos = read_pos + params.scroll; if (any(lessThan(write_pos, ivec3(0))) || any(greaterThanEqual(write_pos, ivec3(params.grid_size)))) { - return; //fits outside the 3D texture, dont do anything + return; // Fits outside the 3D texture, don't do anything. } uint albedo = ((src_process_voxels.data[index].albedo & 0x7FFF) << 1) | 1; //add solid bit |