summaryrefslogtreecommitdiff
path: root/servers/rendering/rasterizer_rd/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/rasterizer_rd/shaders')
-rw-r--r--servers/rendering/rasterizer_rd/shaders/SCsub5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/blur.glsl301
-rw-r--r--servers/rendering/rasterizer_rd/shaders/blur_inc.glsl35
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl239
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl104
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl72
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl399
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl73
-rw-r--r--servers/rendering/rasterizer_rd/shaders/sky.glsl16
-rw-r--r--servers/rendering/rasterizer_rd/shaders/specular_merge.glsl4
-rw-r--r--servers/rendering/rasterizer_rd/shaders/tonemap.glsl58
12 files changed, 773 insertions, 538 deletions
diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/rasterizer_rd/shaders/SCsub
index 04a43e3251..a454d144aa 100644
--- a/servers/rendering/rasterizer_rd/shaders/SCsub
+++ b/servers/rendering/rasterizer_rd/shaders/SCsub
@@ -5,14 +5,15 @@ Import("env")
if "RD_GLSL" in env["BUILDERS"]:
env.RD_GLSL("canvas.glsl")
env.RD_GLSL("canvas_occlusion.glsl")
- env.RD_GLSL("blur.glsl")
+ env.RD_GLSL("copy.glsl")
+ env.RD_GLSL("copy_to_fb.glsl")
env.RD_GLSL("cubemap_roughness.glsl")
env.RD_GLSL("cubemap_downsampler.glsl")
env.RD_GLSL("cubemap_filter.glsl")
env.RD_GLSL("scene_high_end.glsl")
env.RD_GLSL("sky.glsl")
env.RD_GLSL("tonemap.glsl")
- env.RD_GLSL("copy.glsl")
+ env.RD_GLSL("cube_to_dp.glsl")
env.RD_GLSL("giprobe.glsl")
env.RD_GLSL("giprobe_debug.glsl")
env.RD_GLSL("giprobe_sdf.glsl")
diff --git a/servers/rendering/rasterizer_rd/shaders/blur.glsl b/servers/rendering/rasterizer_rd/shaders/blur.glsl
deleted file mode 100644
index 5dfdc614a4..0000000000
--- a/servers/rendering/rasterizer_rd/shaders/blur.glsl
+++ /dev/null
@@ -1,301 +0,0 @@
-/* clang-format off */
-[vertex]
-
-#version 450
-
-VERSION_DEFINES
-
-#include "blur_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];
-
- if (bool(blur.flags & FLAG_USE_BLUR_SECTION)) {
- uv_interp = blur.section.xy + uv_interp * blur.section.zw;
- }
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-
- if (bool(blur.flags & FLAG_FLIP_Y)) {
- uv_interp.y = 1.0 - uv_interp.y;
- }
-}
-
-/* clang-format off */
-[fragment]
-
-#version 450
-
-VERSION_DEFINES
-
-#include "blur_inc.glsl"
-
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
-
-layout(set = 0, binding = 0) uniform sampler2D source_color;
-
-#ifdef MODE_SSAO_MERGE
-layout(set = 1, binding = 0) uniform sampler2D source_ssao;
-#endif
-
-#ifdef GLOW_USE_AUTO_EXPOSURE
-layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
-#endif
-
-layout(location = 0) out vec4 frag_color;
-
-//DOF
-#if defined(MODE_DOF_FAR_BLUR) || defined(MODE_DOF_NEAR_BLUR)
-
-layout(set = 1, binding = 0) uniform sampler2D dof_source_depth;
-
-#ifdef DOF_NEAR_BLUR_MERGE
-layout(set = 2, binding = 0) uniform sampler2D source_dof_original;
-#endif
-
-#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_FAR_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));
- }
-
- float amount = smoothstep(blur.dof_begin, blur.dof_end, depth);
- 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));
- }
-
- float tap_amount = mix(smoothstep(blur.dof_begin, blur.dof_end, tap_depth), 1.0, int_ofs == 0);
- 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;
-
-#endif
-
-#ifdef MODE_DOF_NEAR_BLUR
-
- vec4 color_accum = vec4(0.0);
-
- float max_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) * blur.dof_radius;
- float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from));
-
- float tap_k = dof_kernel[i];
-
- vec4 tap_color = texture(source_color, tap_uv, 0.0);
-
- 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));
- }
- float tap_amount = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
- tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
-
- if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
- tap_color.a = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
- }
-
- max_accum = max(max_accum, tap_amount * ofs_influence);
-
- color_accum += tap_color * tap_k;
- }
-
- color_accum.a = max(color_accum.a, sqrt(max_accum));
-
-#ifdef DOF_NEAR_BLUR_MERGE
- {
- vec4 original = texture(source_dof_original, uv_interp, 0.0);
- color_accum = mix(original, color_accum, color_accum.a);
- }
-#endif
-
- if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
- frag_color = color_accum;
- }
-#endif
-
-#ifdef MODE_SIMPLE_COPY
- vec4 color = texture(source_color, uv_interp, 0.0);
- if (bool(blur.flags & FLAG_COPY_FORCE_LUMINANCE)) {
- color.rgb = vec3(max(max(color.r, color.g), color.b));
- }
- frag_color = color;
-#endif
-
-#ifdef MODE_LINEARIZE_DEPTH_COPY
- float depth = texture(source_color, uv_interp, 0.0).r;
- depth = depth * 2.0 - 1.0;
- 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));
- frag_color = vec4(depth / blur.camera_z_far);
-#endif
-
-#ifdef MODE_SSAO_MERGE
- vec4 color = texture(source_color, uv_interp, 0.0);
- float ssao = texture(source_ssao, uv_interp, 0.0).r;
- frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0);
-
-#endif
-}
diff --git a/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl b/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl
deleted file mode 100644
index 33ba9de7bb..0000000000
--- a/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl
+++ /dev/null
@@ -1,35 +0,0 @@
-#define FLAG_HORIZONTAL (1 << 0)
-#define FLAG_USE_BLUR_SECTION (1 << 1)
-#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
-#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
-#define FLAG_GLOW_FIRST_PASS (1 << 4)
-#define FLAG_FLIP_Y (1 << 5)
-#define FLAG_COPY_FORCE_LUMINANCE (1 << 6)
-
-layout(push_constant, binding = 1, std430) uniform Blur {
- vec4 section;
- 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_begin;
- float dof_end;
- float dof_radius;
- float dof_pad;
-
- vec2 dof_dir;
- float camera_z_far;
- float camera_z_near;
-
- vec4 ssao_color;
-}
-blur;
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
index 1ac43480cd..a39866004b 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
@@ -132,6 +132,11 @@ layout(set = 2, binding = 6) uniform sampler shadow_sampler;
#endif
+layout(set = 2, binding = 7, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
+}
+global_variables;
+
/* SET3: Render Target Data */
#ifdef SCREEN_TEXTURE_USED
diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl
index 2b541f2660..2d7661f65f 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -1,87 +1,220 @@
/* clang-format off */
-[vertex]
+[compute]
#version 450
VERSION_DEFINES
-layout(location = 0) out vec2 uv_interp;
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
/* clang-format on */
-void main() {
+#define FLAG_HORIZONTAL (1 << 0)
+#define FLAG_USE_BLUR_SECTION (1 << 1)
+#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
+#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
+#define FLAG_GLOW_FIRST_PASS (1 << 4)
+#define FLAG_FLIP_Y (1 << 5)
+#define FLAG_FORCE_LUMINANCE (1 << 6)
+#define FLAG_COPY_ALL_SOURCE (1 << 7)
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec4 section;
+ ivec2 target;
+ 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 camera_z_far;
+ float camera_z_near;
+ uint pad2[2];
+}
+params;
- 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];
+layout(set = 0, binding = 0) uniform sampler2D source_color;
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
+#ifdef GLOW_USE_AUTO_EXPOSURE
+layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#endif
-/* clang-format off */
-[fragment]
+#if defined(MODE_LINEARIZE_DEPTH_COPY) || defined(MODE_SIMPLE_COPY_DEPTH)
+layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#elif defined(DST_IMAGE_8BIT)
+layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#else
+layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#endif
-#version 450
+void main() {
-VERSION_DEFINES
+ // Pixel being shaded
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThan(pos, params.section.zw))) { //too large, do nothing
+ return;
+ }
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
+#ifdef MODE_MIPMAP
-#ifdef MODE_CUBE_TO_DP
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ vec4 color = texelFetch(source_color, base_pos, 0);
+ color += texelFetch(source_color, base_pos + ivec2(0, 1), 0);
+ color += texelFetch(source_color, base_pos + ivec2(1, 0), 0);
+ color += texelFetch(source_color, base_pos + ivec2(1, 1), 0);
+ color /= 4.0;
-layout(set = 0, binding = 0) uniform samplerCube source_cube;
+ imageStore(dest_buffer, pos + params.target, color);
+#endif
-layout(push_constant, binding = 0, std430) uniform Params {
- float bias;
- float z_far;
- float z_near;
- bool z_flip;
-}
-params;
+#ifdef MODE_GAUSSIAN_BLUR
+
+ //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-layout(location = 0) out float depth_buffer;
+ if (bool(params.flags & FLAG_HORIZONTAL)) {
+
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.214607;
+ color += texelFetch(source_color, base_pos + ivec2(1, 0), 0) * 0.189879;
+ color += texelFetch(source_color, base_pos + ivec2(2, 0), 0) * 0.131514;
+ color += texelFetch(source_color, base_pos + ivec2(3, 0), 0) * 0.071303;
+ color += texelFetch(source_color, base_pos + ivec2(-1, 0), 0) * 0.189879;
+ color += texelFetch(source_color, base_pos + ivec2(-2, 0), 0) * 0.131514;
+ color += texelFetch(source_color, base_pos + ivec2(-3, 0), 0) * 0.071303;
+ imageStore(dest_buffer, pos + params.target, color);
+ } else {
+ ivec2 base_pos = (pos + params.section.xy);
+ vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.38774;
+ color += texelFetch(source_color, base_pos + ivec2(0, 1), 0) * 0.24477;
+ color += texelFetch(source_color, base_pos + ivec2(0, 2), 0) * 0.06136;
+ color += texelFetch(source_color, base_pos + ivec2(0, -1), 0) * 0.24477;
+ color += texelFetch(source_color, base_pos + ivec2(0, -2), 0) * 0.06136;
+ imageStore(dest_buffer, pos + params.target, color);
+ }
#endif
-void main() {
+#ifdef MODE_GAUSSIAN_GLOW
-#ifdef MODE_CUBE_TO_DP
+ //Glow uses larger sigma 1 for a more rounded blur effect
- vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+#define GLOW_ADD(m_ofs, m_mult) \
+ { \
+ ivec2 ofs = base_pos + m_ofs; \
+ if (all(greaterThanEqual(ofs, section_begin)) && all(lessThan(ofs, section_end))) { \
+ color += texelFetch(source_color, ofs, 0) * m_mult; \
+ } \
+ }
- normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
- normal = normalize(normal);
+ vec4 color = vec4(0.0);
- normal.y = -normal.y; //needs to be flipped to match projection matrix
- if (!params.z_flip) {
- normal.z = -normal.z;
+ if (bool(params.flags & FLAG_HORIZONTAL)) {
+
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ ivec2 section_begin = params.section.xy << 1;
+ ivec2 section_end = section_begin + (params.section.zw << 1);
+
+ GLOW_ADD(ivec2(0, 0), 0.174938);
+ GLOW_ADD(ivec2(1, 0), 0.165569);
+ GLOW_ADD(ivec2(2, 0), 0.140367);
+ GLOW_ADD(ivec2(3, 0), 0.106595);
+ GLOW_ADD(ivec2(-1, 0), 0.165569);
+ GLOW_ADD(ivec2(-2, 0), 0.140367);
+ GLOW_ADD(ivec2(-3, 0), 0.106595);
+ color *= params.glow_strength;
+ } else {
+
+ ivec2 base_pos = pos + params.section.xy;
+ ivec2 section_begin = params.section.xy;
+ ivec2 section_end = section_begin + params.section.zw;
+
+ GLOW_ADD(ivec2(0, 0), 0.288713);
+ GLOW_ADD(ivec2(0, 1), 0.233062);
+ GLOW_ADD(ivec2(0, 2), 0.122581);
+ GLOW_ADD(ivec2(0, -1), 0.233062);
+ GLOW_ADD(ivec2(0, -2), 0.122581);
+ color *= params.glow_strength;
}
- float depth = texture(source_cube, normal).r;
- depth_buffer = depth;
-
- // absolute values for direction cosines, bigger value equals closer to basis axis
- vec3 unorm = abs(normal);
-
- if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
- // x code
- unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
- } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
- // y code
- unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
- } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
- // z code
- unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+#undef GLOW_ADD
+
+ if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
+#ifdef GLOW_USE_AUTO_EXPOSURE
+
+ color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey;
+#endif
+ color *= params.glow_exposure;
+
+ float luminance = max(color.r, max(color.g, color.b));
+ float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom);
+
+ color = min(color * feedback, vec4(params.glow_luminance_cap));
+ }
+
+ imageStore(dest_buffer, pos + params.target, color);
+
+#endif
+
+#ifdef MODE_SIMPLE_COPY
+
+ vec4 color;
+ if (bool(params.flags & FLAG_COPY_ALL_SOURCE)) {
+ vec2 uv = vec2(pos) / vec2(params.section.zw);
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ uv.y = 1.0 - uv.y;
+ }
+ color = textureLod(source_color, uv, 0.0);
+
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+ imageStore(dest_buffer, pos + params.target, color);
+
} else {
- // oh-no we messed up code
- // has to be
- unorm = vec3(1.0, 0.0, 0.0);
+ color = texelFetch(source_color, pos + params.section.xy, 0);
+
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+
+ imageStore(dest_buffer, pos + params.target, color);
}
- float depth_fix = 1.0 / dot(normal, unorm);
+#endif
+
+#ifdef MODE_SIMPLE_COPY_DEPTH
+
+ vec4 color = texelFetch(source_color, pos + params.section.xy, 0);
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
- depth = 2.0 * depth - 1.0;
- float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
- depth_buffer = (linear_depth * depth_fix) / params.z_far;
+ imageStore(dest_buffer, pos + params.target, vec4(color.r));
+
+#endif
+
+#ifdef MODE_LINEARIZE_DEPTH_COPY
+
+ float depth = texelFetch(source_color, pos + params.section.xy, 0).r;
+ depth = depth * 2.0 - 1.0;
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ vec4 color = vec4(depth / params.camera_z_far);
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+ imageStore(dest_buffer, pos + params.target, color);
#endif
}
diff --git a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
new file mode 100644
index 0000000000..07f8d09743
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
@@ -0,0 +1,104 @@
+/* clang-format off */
+[vertex]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ vec4 section;
+ vec2 pixel_size;
+ bool flip_y;
+ bool use_section;
+
+ bool force_luminance;
+ uint pad[3];
+}
+params;
+
+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];
+
+ vec2 vpos = uv_interp;
+ if (params.use_section) {
+ vpos = params.section.xy + vpos * params.section.zw;
+ }
+
+ gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0);
+
+ if (params.flip_y) {
+ uv_interp.y = 1.0 - uv_interp.y;
+ }
+}
+
+/* clang-format off */
+[fragment]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ vec4 section;
+ vec2 pixel_size;
+ bool flip_y;
+ bool use_section;
+
+ bool force_luminance;
+ bool alpha_to_zero;
+ uint pad[2];
+} params;
+
+
+layout(location = 0) in vec2 uv_interp;
+/* clang-format on */
+
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+
+ vec2 uv = uv_interp;
+
+#ifdef MODE_PANORAMA_TO_DP
+
+ //obtain normal from dual paraboloid uv
+#define M_PI 3.14159265359
+
+ float side;
+ uv.y = modf(uv.y * 2.0, side);
+ side = side * 2.0 - 1.0;
+ vec3 normal = vec3(uv * 2.0 - 1.0, 0.0);
+ normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+ normal *= -side;
+ normal = normalize(normal);
+
+ //now convert normal to panorama uv
+
+ vec2 st = vec2(atan(normal.x, normal.z), acos(normal.y));
+
+ if (st.x < 0.0)
+ st.x += M_PI * 2.0;
+
+ uv = st / vec2(M_PI * 2.0, M_PI);
+
+ if (side < 0.0) {
+ //uv.y = 1.0 - uv.y;
+ uv = 1.0 - uv;
+ }
+#endif
+ vec4 color = textureLod(source_color, uv, 0.0);
+ if (params.force_luminance) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+ if (params.alpha_to_zero) {
+ color.rgb *= color.a;
+ }
+ frag_color = color;
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl b/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
new file mode 100644
index 0000000000..02ebe1a53b
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
@@ -0,0 +1,72 @@
+/* clang-format off */
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+/* clang-format on */
+
+layout(set = 0, binding = 0) uniform samplerCube source_cube;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec2 screen_size;
+ ivec2 offset;
+ float bias;
+ float z_far;
+ float z_near;
+ bool z_flip;
+}
+params;
+
+layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D depth_buffer;
+
+void main() {
+
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
+ return;
+ }
+
+ vec2 pixel_size = 1.0 / vec2(params.screen_size);
+ vec2 uv = (vec2(pos) + 0.5) * pixel_size;
+
+ vec3 normal = vec3(uv * 2.0 - 1.0, 0.0);
+
+ normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+ normal = normalize(normal);
+
+ normal.y = -normal.y; //needs to be flipped to match projection matrix
+ if (!params.z_flip) {
+ normal.z = -normal.z;
+ }
+
+ float depth = texture(source_cube, normal).r;
+
+ // absolute values for direction cosines, bigger value equals closer to basis axis
+ vec3 unorm = abs(normal);
+
+ if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
+ // x code
+ unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
+ } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
+ // y code
+ unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
+ } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
+ // z code
+ unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+ } else {
+ // oh-no we messed up code
+ // has to be
+ unorm = vec3(1.0, 0.0, 0.0);
+ }
+
+ float depth_fix = 1.0 / dot(normal, unorm);
+
+ depth = 2.0 * depth - 1.0;
+ float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ depth = (linear_depth * depth_fix) / params.z_far;
+
+ imageStore(depth_buffer, pos + params.offset, vec4(depth));
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 70ce8d61e4..ec47887036 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -20,9 +20,7 @@ layout(location = 2) in vec4 tangent_attrib;
layout(location = 3) in vec4 color_attrib;
#endif
-#if defined(UV_USED)
layout(location = 4) in vec2 uv_attrib;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
layout(location = 5) in vec2 uv2_attrib;
@@ -39,9 +37,7 @@ layout(location = 1) out vec3 normal_interp;
layout(location = 2) out vec4 color_interp;
#endif
-#if defined(UV_USED)
layout(location = 3) out vec2 uv_interp;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
layout(location = 4) out vec2 uv2_interp;
@@ -157,9 +153,7 @@ void main() {
#endif
}
-#if defined(UV_USED)
uv_interp = uv_attrib;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
uv2_interp = uv2_attrib;
@@ -290,9 +284,7 @@ layout(location = 1) in vec3 normal_interp;
layout(location = 2) in vec4 color_interp;
#endif
-#if defined(UV_USED)
layout(location = 3) in vec2 uv_interp;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
layout(location = 4) in vec2 uv2_interp;
@@ -686,61 +678,63 @@ LIGHT_SHADER_CODE
#ifndef USE_NO_SHADOWS
-const vec2 shadow_poisson_disk[16] = vec2[](
- vec2(-0.94201624, -0.39906216),
- vec2(0.94558609, -0.76890725),
- vec2(-0.094184101, -0.92938870),
- vec2(0.34495938, 0.29387760),
- vec2(-0.91588581, 0.45771432),
- vec2(-0.81544232, -0.87912464),
- vec2(-0.38277543, 0.27676845),
- vec2(0.97484398, 0.75648379),
- vec2(0.44323325, -0.97511554),
- vec2(0.53742981, -0.47373420),
- vec2(-0.26496911, -0.41893023),
- vec2(0.79197514, 0.19090188),
- vec2(-0.24188840, 0.99706507),
- vec2(-0.81409955, 0.91437590),
- vec2(0.19984126, 0.78641367),
- vec2(0.14383161, -0.14100790));
-
-float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
+// Produces cheap but low-quality white noise, nothing special
+float quick_hash(vec2 pos) {
+ return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237);
+}
+
+float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
vec2 pos = coord.xy;
float depth = coord.z;
- switch (scene_data.shadow_filter_mode) {
- case SHADOW_MODE_NO_FILTER: {
- return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
- };
- case SHADOW_MODE_PCF5: {
- float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
- return avg * (1.0 / 5.0);
- };
- case SHADOW_MODE_PCF13: {
-
- float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
- return avg * (1.0 / 13.0);
- };
+ //if only one sample is taken, take it from the center
+ if (scene_data.directional_soft_shadow_samples == 1) {
+ return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ }
+
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ float avg = 0.0;
+
+ for (uint i = 0; i < scene_data.directional_soft_shadow_samples; i++) {
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
+ }
+
+ return avg * (1.0 / float(scene_data.directional_soft_shadow_samples));
+}
+
+float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
+
+ vec2 pos = coord.xy;
+ float depth = coord.z;
+
+ //if only one sample is taken, take it from the center
+ if (scene_data.soft_shadow_samples == 1) {
+ return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ }
+
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ float avg = 0.0;
+
+ for (uint i = 0; i < scene_data.soft_shadow_samples; i++) {
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0));
}
- return 0;
+ return avg * (1.0 / float(scene_data.soft_shadow_samples));
}
float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) {
@@ -749,17 +743,17 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
float blocker_count = 0.0;
float blocker_average = 0.0;
- mat2 poisson_rotate;
-
+ mat2 disk_rotation;
{
- float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
float sr = sin(r);
float cr = cos(r);
- poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * tex_scale;
+ for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < pssm_coord.z) {
blocker_average += d;
@@ -775,12 +769,12 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
tex_scale *= penumbra;
float s = 0.0;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * tex_scale;
+ for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
}
- return s / float(scene_data.shadow_blocker_count);
+ return s / float(scene_data.directional_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -790,7 +784,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
#endif //USE_NO_SHADOWS
-void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -862,13 +856,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float blocker_count = 0.0;
float blocker_average = 0.0;
- mat2 poisson_rotate;
-
+ mat2 disk_rotation;
{
- float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
float sr = sin(r);
float cr = cos(r);
- poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
vec3 normal = normalize(splane.xyz);
@@ -877,12 +870,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
vec3 bitangent = normalize(cross(tangent, normal));
float z_norm = shadow_len * lights.data[idx].inv_radius;
- tangent *= lights.data[idx].soft_shadow_size;
- bitangent *= lights.data[idx].soft_shadow_size;
+ tangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
+ bitangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]);
- vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.y;
+ for (uint i = 0; i < scene_data.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;
pos = normalize(pos);
vec4 uv_rect = lights.data[idx].atlas_rect;
@@ -919,10 +914,10 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
z_norm -= lights.data[idx].inv_radius * lights.data[idx].shadow_bias;
shadow = 0.0;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
- vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]);
- vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.y;
+ vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+ vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
pos = normalize(pos);
vec4 uv_rect = lights.data[idx].atlas_rect;
@@ -943,7 +938,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
}
- shadow /= float(scene_data.shadow_blocker_count);
+ shadow /= float(scene_data.penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -970,17 +965,19 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
splane.z = (shadow_len - lights.data[idx].shadow_bias) * lights.data[idx].inv_radius;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
splane.w = 1.0; //needed? i think it should be 1 already
- shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
+ shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
}
#ifdef LIGHT_TRANSMITTANCE_USED
{
+ vec4 clamp_rect = lights.data[idx].atlas_rect;
+
//redo shadowmapping, but shrink the model a bit to avoid arctifacts
splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
- shadow_len = length(splane);
- splane = normalize(splane);
+ shadow_len = length(splane.xyz);
+ splane = normalize(splane.xyz);
if (splane.z >= 0.0) {
@@ -1002,7 +999,70 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
}
#endif
- shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ vec3 no_shadow = vec3(1.0);
+
+ if (lights.data[idx].projector_rect != vec4(0.0)) {
+
+ vec3 local_v = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
+ local_v = normalize(local_v);
+
+ vec4 atlas_rect = 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.xy /= local_v.z;
+ 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 = (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;
+ }
+
+ 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;
+
+ vec3 local_v_ddy = (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;
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+
+ shadow_attenuation = mix(shadow_color_enabled.rgb, no_shadow, shadow);
}
#endif //USE_NO_SHADOWS
@@ -1033,7 +1093,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
specular_light);
}
-void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -1117,22 +1177,25 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
//find blocker
+ vec2 shadow_uv = splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy;
+
float blocker_count = 0.0;
float blocker_average = 0.0;
- mat2 poisson_rotate;
-
+ mat2 disk_rotation;
{
- float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
float sr = sin(r);
float cr = cos(r);
- poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
- float uv_size = lights.data[idx].soft_shadow_size * z_norm;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size;
- suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw);
+ float uv_size = lights.data[idx].soft_shadow_size * z_norm * lights.data[idx].soft_shadow_scale;
+ vec2 clamp_max = lights.data[idx].atlas_rect.xy + lights.data[idx].atlas_rect.zw;
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+
+ vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
+ suv = clamp(suv, 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) {
blocker_average += d;
@@ -1148,13 +1211,13 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
uv_size *= penumbra;
shadow = 0.0;
- for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
- vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size;
- suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw);
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
+ suv = clamp(suv, lights.data[idx].atlas_rect.xy, clamp_max);
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0));
}
- shadow /= float(scene_data.shadow_blocker_count);
+ shadow /= float(scene_data.penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -1163,17 +1226,41 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
} else {
//hard shadow
- splane.z = z_norm;
- shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
+ vec4 shadow_uv = vec4(splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy, z_norm, 1.0);
+
+ shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv);
}
- shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ vec3 no_shadow = vec3(1.0);
+
+ if (lights.data[idx].projector_rect != vec4(0.0)) {
+
+ splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+ splane /= splane.w;
+
+ vec2 proj_uv = splane.xy * lights.data[idx].projector_rect.zw;
+
+ //ensure we have proper mipmaps
+ vec4 splane_ddx = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0));
+ splane_ddx /= splane_ddx.w;
+ vec2 proj_uv_ddx = splane_ddx.xy * lights.data[idx].projector_rect.zw - proj_uv;
+
+ vec4 splane_ddy = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0));
+ splane_ddy /= splane_ddy.w;
+ vec2 proj_uv_ddy = splane_ddy.xy * lights.data[idx].projector_rect.zw - proj_uv;
+
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ no_shadow = mix(no_shadow, proj.rgb, proj.a);
+ }
+
+ shadow_attenuation = mix(shadow_color_enabled.rgb, no_shadow, shadow);
#ifdef LIGHT_TRANSMITTANCE_USED
{
- vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
+ splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
splane /= splane.w;
+ splane.xy = splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy;
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
//reconstruct depth
@@ -1607,9 +1694,7 @@ void main() {
}
#endif
-#if defined(UV_USED)
vec2 uv = uv_interp;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
vec2 uv2 = uv2_interp;
@@ -1691,7 +1776,81 @@ FRAGMENT_SHADER_CODE
discard;
}
#endif
+ /////////////////////// DECALS ////////////////////////////////
+
+#ifndef MODE_RENDER_DEPTH
+
+ uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)));
+ //used for interpolating anything cluster related
+ vec3 vertex_ddx = dFdx(vertex);
+ vec3 vertex_ddy = dFdy(vertex);
+
+ { // process decals
+
+ uint decal_count = cluster_cell.w >> CLUSTER_COUNTER_SHIFT;
+ uint decal_pointer = cluster_cell.w & CLUSTER_POINTER_MASK;
+
+ //do outside for performance and avoiding arctifacts
+
+ for (uint i = 0; i < decal_count; i++) {
+
+ uint decal_index = cluster_data.indices[decal_pointer + i];
+ if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) {
+ continue; //not masked
+ }
+
+ vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
+ if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
+ 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);
+ }
+
+ 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);
+ 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;
+ 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
+ decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
+
+ normal = normalize(mix(normal, decal_normal, decal_albedo.a));
+ }
+
+ 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;
+#if defined(AO_USED)
+ ao = mix(ao, decal_orm.r, decal_albedo.a);
+#endif
+ roughness = mix(roughness, decal_orm.g, decal_albedo.a);
+ metallic = mix(metallic, decal_orm.b, decal_albedo.a);
+ }
+ }
+ 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;
+ }
+ }
+ }
+
+#endif //not render depth
/////////////////////// LIGHTING //////////////////////////////
//apply energy conservation
@@ -1796,8 +1955,6 @@ FRAGMENT_SHADER_CODE
}
#endif
- uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)));
-
{ // process reflections
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
@@ -1888,9 +2045,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.x;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color1.rgb;
@@ -1922,9 +2079,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.y;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color2.rgb;
@@ -1955,9 +2112,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.z;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color3.rgb;
@@ -1989,9 +2146,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.w;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
shadow_color = directional_lights.data[i].shadow_color4.rgb;
@@ -2028,9 +2185,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.y;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
@@ -2046,9 +2203,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.z;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
@@ -2064,9 +2221,9 @@ FRAGMENT_SHADER_CODE
float range_begin = directional_lights.data[i].shadow_range_begin.w;
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
} else {
- shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
}
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
@@ -2129,7 +2286,7 @@ FRAGMENT_SHADER_CODE
continue; //not masked
}
- light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, albedo, roughness, metallic, specular, specular_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -2168,7 +2325,7 @@ FRAGMENT_SHADER_CODE
continue; //not masked
}
- light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, albedo, roughness, metallic, specular, specular_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
index 59f326bc9b..ce4fabf9f2 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
@@ -22,10 +22,6 @@ draw_call;
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
-#define SHADOW_MODE_NO_FILTER 0
-#define SHADOW_MODE_PCF5 1
-#define SHADOW_MODE_PCF13 2
-
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
@@ -45,12 +41,18 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
- uint shadow_filter_mode;
+ uint pad;
+
+ //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
+ vec4 directional_penumbra_shadow_kernel[32];
+ vec4 directional_soft_shadow_kernel[32];
+ vec4 penumbra_shadow_kernel[32];
+ vec4 soft_shadow_kernel[32];
- uint shadow_blocker_count;
- uint shadow_pad0;
- uint shadow_pad1;
- uint shadow_pad2;
+ uint directional_penumbra_shadow_samples;
+ uint directional_soft_shadow_samples;
+ uint penumbra_shadow_samples;
+ uint soft_shadow_samples;
vec4 ambient_light_color_energy;
@@ -132,12 +134,12 @@ struct InstanceData {
mat4 transform;
mat4 normal_transform;
uint flags;
- uint instance_ofs; //instance_offset in instancing/skeleton buffer
+ uint instance_uniforms_ofs; //base offset in global buffer for instance variables
uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
uint layer_mask;
};
-layout(set = 0, binding = 4, std430) buffer Instances {
+layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
InstanceData data[];
}
instances;
@@ -151,17 +153,19 @@ struct LightData { //this structure needs to be as packed as possible
uint color_specular; //rgb color, a specular (8 bit unorm)
uint cone_attenuation_angle; // attenuation and angle, (16bit float)
uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
- vec4 atlas_rect; // used for spot
+ vec4 atlas_rect; // rect in the shadow atlas
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
uint mask;
- uint pad[3];
+ uint pad[2];
+ vec4 projector_rect; //projector rect in srgb decal atlas
};
-layout(set = 0, binding = 5, std430) buffer Lights {
+layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
LightData data[];
}
lights;
@@ -191,7 +195,7 @@ struct DirectionalLightData {
float specular;
uint mask;
float softshadow_angle;
- uint pad1;
+ float soft_shadow_scale;
bool blend_splits;
bool shadow_enabled;
float fade_from;
@@ -248,14 +252,45 @@ layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TE
#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1)
#define CLUSTER_COUNTER_MASK 0xfff
-layout(set = 0, binding = 10) uniform utexture3D cluster_texture;
+layout(set = 0, binding = 10) uniform texture2D decal_atlas;
+layout(set = 0, binding = 11) uniform texture2D decal_atlas_srgb;
+
+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;
+ uint mask;
+ float upper_fade;
+ float lower_fade;
+ mat3x4 normal_xform;
+ vec3 normal;
+ float normal_fade;
+};
+
+layout(set = 0, binding = 12, std430) restrict readonly buffer Decals {
+ DecalData data[];
+}
+decals;
+
+layout(set = 0, binding = 13) uniform utexture3D cluster_texture;
-layout(set = 0, binding = 11, std430) buffer ClusterData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer ClusterData {
uint indices[];
}
cluster_data;
-layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas;
+layout(set = 0, binding = 15) uniform texture2D directional_shadow_atlas;
+
+layout(set = 0, binding = 16, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
+}
+global_variables;
// decal atlas
@@ -287,7 +322,7 @@ layout(set = 3, binding = 4) uniform texture2D ao_buffer;
/* Set 4 Skeleton & Instancing (Multimesh) */
-layout(set = 4, binding = 0, std430) buffer Transforms {
+layout(set = 4, binding = 0, std430) restrict readonly buffer Transforms {
vec4 data[];
}
transforms;
diff --git a/servers/rendering/rasterizer_rd/shaders/sky.glsl b/servers/rendering/rasterizer_rd/shaders/sky.glsl
index 469925839a..536077980d 100644
--- a/servers/rendering/rasterizer_rd/shaders/sky.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/sky.glsl
@@ -58,6 +58,11 @@ params;
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
+layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
+}
+global_variables;
+
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
@@ -96,9 +101,8 @@ layout(set = 2, binding = 2) uniform texture2D quarter_res;
#endif
struct DirectionalLightData {
- vec3 direction;
- float energy;
- vec3 color;
+ vec4 direction_energy;
+ vec4 color_size;
bool enabled;
};
@@ -178,4 +182,10 @@ FRAGMENT_SHADER_CODE
frag_color.rgb = color * params.position_multiplier.w;
frag_color.a = alpha;
+
+ // Blending is disabled for Sky, so alpha doesn't blend
+ // alpha is used for subsurface scattering so make sure it doesn't get applied to Sky
+ if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
+ frag_color.a = 0.0;
+ }
}
diff --git a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
index b28250318e..b24f7dccc7 100644
--- a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
@@ -48,8 +48,8 @@ void main() {
frag_color.a = 0.0;
#ifdef MODE_SSR
- vec4 ssr = texture(ssr, uv_interp);
- frag_color.rgb = mix(frag_color.rgb, ssr.rgb, ssr.a);
+ vec4 ssr_color = texture(ssr, uv_interp);
+ frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
#endif
#ifdef MODE_MERGE
diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
index 524ca5e2ea..a142d263e2 100644
--- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
@@ -48,6 +48,10 @@ layout(push_constant, binding = 1, std430) uniform Params {
float exposure;
float white;
float auto_exposure_grey;
+
+ vec2 pixel_size;
+ bool use_fxaa;
+ uint pad;
}
params;
@@ -255,16 +259,63 @@ vec3 apply_color_correction(vec3 color, sampler3D correction_tex) {
return texture(correction_tex, color).rgb;
}
+vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
+
+ const float FXAA_REDUCE_MIN = (1.0 / 128.0);
+ const float FXAA_REDUCE_MUL = (1.0 / 8.0);
+ const float FXAA_SPAN_MAX = 8.0;
+
+ vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbM = color;
+ vec3 luma = vec3(0.299, 0.587, 0.114);
+ float lumaNW = dot(rgbNW, luma);
+ float lumaNE = dot(rgbNE, luma);
+ float lumaSW = dot(rgbSW, luma);
+ float lumaSE = dot(rgbSE, luma);
+ float lumaM = dot(rgbM, luma);
+ float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+ float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+ vec2 dir;
+ dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+ dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+ float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
+ (0.25 * FXAA_REDUCE_MUL),
+ FXAA_REDUCE_MIN);
+
+ float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
+ dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
+ max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
+ dir * rcpDirMin)) *
+ params.pixel_size;
+
+ vec3 rgbA = 0.5 * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz * exposure + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz) * exposure;
+ vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz * exposure +
+ textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz * exposure);
+
+ float lumaB = dot(rgbB, luma);
+ if ((lumaB < lumaMin) || (lumaB > lumaMax))
+ return rgbA;
+ else
+ return rgbB;
+}
+
void main() {
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
// Exposure
+ float exposure = params.exposure;
+
if (params.use_auto_exposure) {
- color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey;
+ exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey);
}
- color *= params.exposure;
+ color *= exposure;
// Early Tonemap & SRGB Conversion
@@ -274,6 +325,9 @@ void main() {
color.rgb = mix(color.rgb, glow, params.glow_intensity);
}
+ if (params.use_fxaa) {
+ color = do_fxaa(color, exposure, uv_interp);
+ }
color = apply_tonemapping(color, params.white);
color = linear_to_srgb(color); // regular linear -> SRGB conversion