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.glsl294
-rw-r--r--servers/rendering/rasterizer_rd/shaders/blur_inc.glsl35
-rw-r--r--servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas.glsl19
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl11
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl258
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl99
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl69
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl4
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl7
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe.glsl22
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl83
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl12
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl20
-rw-r--r--servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl7
-rw-r--r--servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl1105
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl143
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl14
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl14
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl13
-rw-r--r--servers/rendering/rasterizer_rd/shaders/sky.glsl27
-rw-r--r--servers/rendering/rasterizer_rd/shaders/specular_merge.glsl14
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao.glsl7
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl13
-rw-r--r--servers/rendering/rasterizer_rd/shaders/tonemap.glsl69
31 files changed, 1595 insertions, 814 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 87c20ebaef..0000000000
--- a/servers/rendering/rasterizer_rd/shaders/blur.glsl
+++ /dev/null
@@ -1,294 +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_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/bokeh_dof.glsl b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
index 7153fe6b17..63f086a83d 100644
--- a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
#ifdef MODE_GEN_BLUR_SIZE
layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image;
@@ -69,7 +67,6 @@ float get_depth_at_pos(vec2 uv) {
}
float get_blur_size(float depth) {
-
if (params.blur_near_active && depth < params.blur_near_begin) {
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
}
@@ -95,7 +92,6 @@ float hash12n(vec2 p) {
#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL)
vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
-
dir *= pixel_size;
vec4 color = texture(color_texture, uv);
@@ -109,7 +105,6 @@ vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
}
for (int i = -params.blur_steps; i <= params.blur_steps; i++) {
-
if (i == 0) {
continue;
}
@@ -141,7 +136,6 @@ vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
#endif
void main() {
-
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThan(pos, params.size))) { //too large, do nothing
@@ -218,7 +212,6 @@ void main() {
float radius = params.blur_scale;
for (float ang = 0.0; radius < params.blur_size; ang += GOLDEN_ANGLE) {
-
vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius;
vec4 sample_color = texture(color_texture, suv);
float sample_size = abs(sample_color.a);
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
index 28135fce31..e33b3face9 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -7,7 +6,6 @@ VERSION_DEFINES
#ifdef USE_ATTRIBUTES
layout(location = 0) in vec2 vertex_attrib;
-/* clang-format on */
layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
@@ -40,7 +38,6 @@ VERTEX_SHADER_GLOBALS
/* clang-format on */
void main() {
-
vec4 instance_custom = vec4(0.0);
#ifdef USE_PRIMITIVE
@@ -88,7 +85,6 @@ void main() {
#if 0
if (draw_data.flags & FLAGS_INSTANCING_ENABLED) {
-
uint offset = draw_data.flags & FLAGS_INSTANCING_STRIDE_MASK;
offset *= gl_InstanceIndex;
mat4 instance_xform = mat4(
@@ -149,7 +145,6 @@ VERTEX_SHADER_CODE
color_interp = color;
if (bool(draw_data.flags & FLAGS_USE_PIXEL_SNAP)) {
-
vertex = floor(vertex + 0.5);
// precision issue on some hardware creates artifacts within texture
// offset uv by a small amount to avoid
@@ -160,7 +155,6 @@ VERTEX_SHADER_CODE
#if 0
if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
//skeleton transform
-
ivec4 bone_indicesi = ivec4(bone_indices);
uvec2 tex_ofs = bone_indicesi.x * 2;
@@ -211,8 +205,7 @@ VERTEX_SHADER_CODE
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -221,7 +214,6 @@ VERSION_DEFINES
#include "canvas_uniforms_inc.glsl"
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(location = 1) in vec4 color_interp;
layout(location = 2) in vec2 vertex_interp;
@@ -258,7 +250,6 @@ vec4 light_compute(
vec2 screen_uv,
vec2 uv,
vec4 color) {
-
vec4 light = vec4(0.0);
/* clang-format off */
LIGHT_SHADER_CODE
@@ -271,7 +262,6 @@ LIGHT_SHADER_CODE
#ifdef USE_NINEPATCH
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) {
-
float tex_size = 1.0 / tex_pixel_size;
if (pixel < margin_begin) {
@@ -313,7 +303,6 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
#endif
void main() {
-
vec4 color = color_interp;
vec2 uv = uv_interp;
vec2 vertex = vertex_interp;
@@ -335,7 +324,6 @@ void main() {
#endif
if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) {
-
uv = clamp(uv, draw_data.src_rect.xy, draw_data.src_rect.xy + abs(draw_data.src_rect.zw));
}
@@ -348,7 +336,6 @@ void main() {
vec3 normal;
#if defined(NORMAL_USED)
-
bool normal_used = true;
#else
bool normal_used = false;
@@ -458,7 +445,6 @@ FRAGMENT_SHADER_CODE
light_color.rgb *= light_base_color.rgb * light_base_color.a;
if (normal_used) {
-
vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
vec3 pos = light_vertex;
vec3 light_vec = normalize(light_pos - pos);
@@ -490,7 +476,6 @@ FRAGMENT_SHADER_CODE
}
if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
-
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
vec2 pos_norm = normalize(shadow_pos);
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
index 7b30cc8fe9..99e70a1976 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
@@ -1,13 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
layout(location = 0) in highp vec3 vertex;
-/* clang-format on */
layout(push_constant, binding = 0, std430) uniform Constants {
-
mat4 projection;
mat2x4 modelview;
vec2 direction;
@@ -18,23 +15,19 @@ constants;
layout(location = 0) out highp float depth;
void main() {
-
highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
depth = dot(constants.direction, vtx.xy);
gl_Position = constants.projection * vtx;
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
layout(location = 0) in highp float depth;
-/* clang-format on */
layout(location = 0) out highp float distance_buf;
void main() {
-
distance_buf = depth;
}
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 cbb9b546a3..eb39c28fa9 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -1,86 +1,240 @@
-/* clang-format off */
-[vertex]
+#[compute]
#version 450
VERSION_DEFINES
-layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+#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;
+
+#ifdef MODE_CUBEMAP_ARRAY_TO_PANORAMA
+layout(set = 0, binding = 0) uniform samplerCubeArray source_color;
+#elif defined(MODE_CUBEMAP_TO_PANORAMA)
+layout(set = 0, binding = 0) uniform samplerCube source_color;
+#else
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+#endif
+
+#ifdef GLOW_USE_AUTO_EXPOSURE
+layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#endif
+
+#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
void main() {
+ // Pixel being shaded
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThanEqual(pos, params.section.zw))) { //too large, do nothing
+ return;
+ }
- 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];
+#ifdef MODE_MIPMAP
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
+ 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;
-/* clang-format off */
-[fragment]
+ imageStore(dest_buffer, pos + params.target, color);
+#endif
-#version 450
+#ifdef MODE_GAUSSIAN_BLUR
-VERSION_DEFINES
+ //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
+ 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
-#ifdef MODE_CUBE_TO_DP
+#ifdef MODE_GAUSSIAN_GLOW
-layout(set = 0, binding = 0) uniform samplerCube source_cube;
+ //Glow uses larger sigma 1 for a more rounded blur effect
-layout(push_constant, binding = 0, std430) uniform Params {
- float bias;
- float z_far;
- float z_near;
- bool z_flip;
-}
-params;
+#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; \
+ } \
+ }
+
+ vec4 color = vec4(0.0);
+
+ 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;
+ }
+
+#undef GLOW_ADD
-layout(location = 0) out float depth_buffer;
+ 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;
-void main() {
+ 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);
-#ifdef MODE_CUBE_TO_DP
+ color = min(color * feedback, vec4(params.glow_luminance_cap));
+ }
- vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+ imageStore(dest_buffer, pos + params.target, color);
- normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
- normal = normalize(normal);
+#endif
- normal.y = -normal.y; //needs to be flipped to match projection matrix
- if (!params.z_flip) {
- normal.z = -normal.z;
- }
+#ifdef MODE_SIMPLE_COPY
- float depth = texture(source_cube, normal).r;
+ 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);
- // absolute values for direction cosines, bigger value equals closer to basis axis
- vec3 unorm = abs(normal);
+ 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);
- 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);
+ 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);
- 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.bias) / params.z_far;
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+
+ 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
+
+#if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA)
+
+ const float PI = 3.14159265359;
+ vec2 uv = vec2(pos) / vec2(params.section.zw);
+ uv.y = 1.0 - uv.y;
+ float phi = uv.x * 2.0 * PI;
+ float theta = uv.y * PI;
+
+ vec3 normal;
+ normal.x = sin(phi) * sin(theta) * -1.0;
+ normal.y = cos(theta);
+ normal.z = cos(phi) * sin(theta) * -1.0;
+
+#ifdef MODE_CUBEMAP_TO_PANORAMA
+ vec4 color = textureLod(source_color, normal, params.camera_z_far); //the biggest the lod the least the acne
+#else
+ vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne
+#endif
+ 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..b1cfe1e91e
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
@@ -0,0 +1,99 @@
+#[vertex]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) out vec2 uv_interp;
+
+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;
+ }
+}
+
+#[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;
+
+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..54d67db6c6
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
@@ -0,0 +1,69 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+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/cubemap_downsampler.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
index 9f3ecf6053..7f269b7af3 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
@@ -18,8 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -28,7 +27,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
@@ -46,26 +44,31 @@ void get_dir_0(out vec3 dir, in float u, in float v) {
dir[1] = v;
dir[2] = -u;
}
+
void get_dir_1(out vec3 dir, in float u, in float v) {
dir[0] = -1.0;
dir[1] = v;
dir[2] = u;
}
+
void get_dir_2(out vec3 dir, in float u, in float v) {
dir[0] = u;
dir[1] = 1.0;
dir[2] = -v;
}
+
void get_dir_3(out vec3 dir, in float u, in float v) {
dir[0] = u;
dir[1] = -1.0;
dir[2] = v;
}
+
void get_dir_4(out vec3 dir, in float u, in float v) {
dir[0] = u;
dir[1] = v;
dir[2] = 1.0;
}
+
void get_dir_5(out vec3 dir, in float u, in float v) {
dir[0] = -u;
dir[1] = v;
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
index 193d0a8a3c..987545fb76 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
@@ -18,8 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -28,7 +27,6 @@ VERSION_DEFINES
#define GROUP_SIZE 64
layout(local_size_x = GROUP_SIZE, local_size_y = 1, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly imageCube dest_cubemap0;
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
index e85996fa1a..5cbb00baa4 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define GROUP_SIZE 8
layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cube;
@@ -119,10 +117,8 @@ void main() {
//vec4 color = color_interp;
if (params.use_direct_write) {
-
imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0));
} else {
-
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) {
@@ -135,7 +131,6 @@ void main() {
float ndotl = clamp(dot(N, L), 0.0, 1.0);
if (ndotl > 0.0) {
-
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
sum.a += ndotl;
}
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
index fd09f96a57..ea4237a45e 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -10,7 +9,6 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#else
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#endif
-/* clang-format on */
#ifndef MODE_DYNAMIC
@@ -47,7 +45,6 @@ cell_data;
#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
struct Light {
-
uint type;
float energy;
float radius;
@@ -191,7 +188,6 @@ layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_n
#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
-
vec3 cell_size = 1.0 / vec3(params.limits);
float occlusion = 1.0;
while (distance > 0.5) { //use this to avoid precision errors
@@ -213,14 +209,11 @@ float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
}
bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) {
-
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
-
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
attenuation = 1.0;
} else {
-
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
if (distance >= lights.data[light].radius) {
@@ -230,7 +223,6 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
-
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel, lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
@@ -246,7 +238,6 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
}
float get_normal_advance(vec3 p_normal) {
-
vec3 normal = p_normal;
vec3 unorm = abs(normal);
@@ -269,7 +260,6 @@ float get_normal_advance(vec3 p_normal) {
}
void clip_segment(vec4 plane, vec3 begin, inout vec3 end) {
-
vec3 segment = begin - end;
float den = dot(plane.xyz, segment);
@@ -302,7 +292,6 @@ bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, i
}
if (lights.data[index].has_shadow) {
-
float distance_adv = get_normal_advance(light_dir);
vec3 to = pos;
@@ -352,7 +341,6 @@ bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, i
#endif // MODE COMPUTE LIGHT
void main() {
-
#ifndef MODE_DYNAMIC
uint cell_index = gl_GlobalInvocationID.x;
@@ -383,7 +371,6 @@ void main() {
#endif
for (uint i = 0; i < params.light_count; i++) {
-
vec3 light;
vec3 light_dir;
if (!compute_light_at_pos(i, pos, normal.xyz, light, light_dir)) {
@@ -394,7 +381,6 @@ void main() {
#ifdef MODE_ANISOTROPIC
for (uint j = 0; j < 6; j++) {
-
accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light;
}
#else
@@ -461,7 +447,6 @@ void main() {
#endif
if (length(normal.xyz) > 0.2) {
-
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, normal.xyz));
vec3 bitangent = normalize(cross(tangent, normal.xyz));
@@ -481,11 +466,9 @@ void main() {
float tan_half_angle = 0.577;
for (int i = 0; i < MAX_CONE_DIRS; i++) {
-
vec3 direction = normal_mat * cone_dirs[i];
vec4 color = vec4(0.0);
{
-
float dist = 1.5;
float max_distance = length(vec3(params.limits));
vec3 cell_size = 1.0 / vec3(params.limits);
@@ -519,7 +502,6 @@ void main() {
color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range
#ifdef MODE_ANISOTROPIC
for (uint j = 0; j < 6; j++) {
-
accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb;
}
#else
@@ -594,7 +576,6 @@ void main() {
#ifdef MODE_WRITE_TEXTURE
{
-
#ifdef MODE_ANISOTROPIC
vec3 accum_total = vec3(0.0);
accum_total += outputs.data[cell_index * 6 + 0].rgb;
@@ -665,7 +646,6 @@ void main() {
vec3 accum = vec3(0.0);
for (uint i = 0; i < params.light_count; i++) {
-
vec3 light;
vec3 light_dir;
if (!compute_light_at_pos(i, vec3(pos) * params.pos_multiplier, normal, light, light_dir)) {
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
index b1784e7eee..515cc35507 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -11,7 +10,6 @@ struct CellData {
uint emission; //rgb normalized with e as multiplier
uint normal; //RGB normal encoded
};
-/* clang-format on */
layout(set = 0, binding = 1, std140) buffer CellDataBuffer {
CellData data[];
@@ -28,7 +26,6 @@ layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex;
#endif
layout(push_constant, binding = 0, std430) uniform Params {
-
mat4 projection;
uint cell_offset;
float dynamic_range;
@@ -42,7 +39,6 @@ params;
layout(location = 0) out vec4 color_interp;
void main() {
-
const vec3 cube_triangles[36] = vec3[](
vec3(-1.0f, -1.0f, -1.0f),
vec3(-1.0f, -1.0f, 1.0f),
@@ -130,12 +126,24 @@ void main() {
float strength = 0.0;
switch (side) {
- case POS_X: strength = aniso_pos.x; break;
- case POS_Y: strength = aniso_pos.y; break;
- case POS_Z: strength = aniso_pos.z; break;
- case NEG_X: strength = aniso_neg.x; break;
- case NEG_Y: strength = aniso_neg.y; break;
- case NEG_Z: strength = aniso_neg.z; break;
+ case POS_X:
+ strength = aniso_pos.x;
+ break;
+ case POS_Y:
+ strength = aniso_pos.y;
+ break;
+ case POS_Z:
+ strength = aniso_pos.z;
+ break;
+ case NEG_X:
+ strength = aniso_neg.x;
+ break;
+ case NEG_Y:
+ strength = aniso_neg.y;
+ break;
+ case NEG_Z:
+ strength = aniso_neg.z;
+ break;
}
color_interp.xyz *= strength;
@@ -160,19 +168,16 @@ void main() {
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec4 color_interp;
-/* clang-format on */
layout(location = 0) out vec4 frag_color;
void main() {
-
frag_color = color_interp;
#ifdef MODE_DEBUG_LIGHT_FULL
@@ -184,22 +189,38 @@ void main() {
int index = x + y * 4;
float limit = 0.0;
if (x < 8) {
- if (index == 0) limit = 0.0625;
- if (index == 1) limit = 0.5625;
- if (index == 2) limit = 0.1875;
- if (index == 3) limit = 0.6875;
- if (index == 4) limit = 0.8125;
- if (index == 5) limit = 0.3125;
- if (index == 6) limit = 0.9375;
- if (index == 7) limit = 0.4375;
- if (index == 8) limit = 0.25;
- if (index == 9) limit = 0.75;
- if (index == 10) limit = 0.125;
- if (index == 11) limit = 0.625;
- if (index == 12) limit = 1.0;
- if (index == 13) limit = 0.5;
- if (index == 14) limit = 0.875;
- if (index == 15) limit = 0.375;
+ if (index == 0)
+ limit = 0.0625;
+ if (index == 1)
+ limit = 0.5625;
+ if (index == 2)
+ limit = 0.1875;
+ if (index == 3)
+ limit = 0.6875;
+ if (index == 4)
+ limit = 0.8125;
+ if (index == 5)
+ limit = 0.3125;
+ if (index == 6)
+ limit = 0.9375;
+ if (index == 7)
+ limit = 0.4375;
+ if (index == 8)
+ limit = 0.25;
+ if (index == 9)
+ limit = 0.75;
+ if (index == 10)
+ limit = 0.125;
+ if (index == 11)
+ limit = 0.625;
+ if (index == 12)
+ limit = 1.0;
+ if (index == 13)
+ limit = 0.5;
+ if (index == 14)
+ limit = 0.875;
+ if (index == 15)
+ limit = 0.375;
}
if (frag_color.a < limit) {
discard;
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
index d089236723..5b3dec0ee7 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
-/* clang-format on */
#define MAX_DISTANCE 100000
@@ -45,7 +43,6 @@ layout(push_constant, binding = 0, std430) uniform Params {
params;
void main() {
-
vec3 pos = vec3(gl_GlobalInvocationID);
float closest_dist = 100000.0;
@@ -71,19 +68,17 @@ void main() {
#if 0
layout(push_constant, binding = 0, std430) uniform Params {
-
ivec3 limits;
uint stack_size;
-} params;
+}
+params;
float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) {
-
vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1)))));
return length(delta);
}
void main() {
-
ivec3 pos = ivec3(gl_GlobalInvocationID);
uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -107,7 +102,6 @@ void main() {
int stack_pos = 0;
while (true) {
-
uint index = stack_indices[stack_pos] >> 24;
if (index == 8) {
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
index c832223b1e..9c794f1bcc 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
-/* clang-format on */
#define NO_CHILDREN 0xFFFFFFFF
#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
@@ -84,24 +82,20 @@ output;
#ifdef MODE_COMPUTE_LIGHT
uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
-
uint result = NO_CHILDREN;
ivec3 size = ivec3(max(max(params.limits.x, params.limits.y), params.limits.z));
while (distance > -distance_adv) { //use this to avoid precision errors
-
uint cell = 0;
ivec3 pos = ivec3(from);
if (all(greaterThanEqual(pos, ivec3(0))) && all(lessThan(pos, size))) {
-
ivec3 ofs = ivec3(0);
ivec3 half_size = size / 2;
for (int i = 0; i < params.stack_size - 1; i++) {
-
bvec3 greater = greaterThanEqual(pos, ofs + half_size);
ofs += mix(ivec3(0), half_size, greater);
@@ -118,8 +112,9 @@ uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
}
cell = cell_children.data[cell].children[child];
- if (cell == NO_CHILDREN)
+ if (cell == NO_CHILDREN) {
break;
+ }
half_size >>= ivec3(1);
}
@@ -137,14 +132,10 @@ uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
}
bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation, out vec3 light_pos) {
-
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
-
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
attenuation = 1.0;
-
} else {
-
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
if (distance >= lights.data[light].radius) {
@@ -154,7 +145,6 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation
attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
-
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel, lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
@@ -170,7 +160,6 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation
}
float get_normal_advance(vec3 p_normal) {
-
vec3 normal = p_normal;
vec3 unorm = abs(normal);
@@ -195,7 +184,6 @@ float get_normal_advance(vec3 p_normal) {
#endif
void main() {
-
uint cell_index = gl_GlobalInvocationID.x;
if (cell_index >= params.cell_count) {
return;
@@ -220,7 +208,6 @@ void main() {
#endif
for (uint i = 0; i < params.light_count; i++) {
-
float attenuation;
vec3 light_pos;
@@ -237,7 +224,6 @@ void main() {
}
if (lights.data[i].has_shadow) {
-
float distance_adv = get_normal_advance(light_dir);
distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
diff --git a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
index 4bf5b7e7f1..8a11c35b78 100644
--- a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
shared float tmp_data[BLOCK_SIZE * BLOCK_SIZE];
@@ -40,12 +38,10 @@ layout(push_constant, binding = 1, std430) uniform Params {
params;
void main() {
-
uint t = gl_LocalInvocationID.y * BLOCK_SIZE + gl_LocalInvocationID.x;
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(lessThan(pos, params.source_size))) {
-
#ifdef READ_TEXTURE
vec3 v = texelFetch(source_texture, pos, 0).rgb;
tmp_data[t] = max(v.r, max(v.g, v.b));
@@ -69,7 +65,6 @@ void main() {
barrier();
size >>= 1;
-
} while (size >= 1);
if (t == 0) {
diff --git a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
index 3637b1abb2..464895928a 100644
--- a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[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 sampler2D source_normal;
layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness;
@@ -21,7 +19,6 @@ params;
#define HALF_PI 1.5707963267948966
void main() {
-
// Pixel being shaded
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
@@ -53,14 +50,14 @@ void main() {
float kappa = (3.0f * r - r * r2) / (1.0f - r2);
float variance = 0.25f / kappa;
limit = sqrt(min(2.0f * variance, threshold * threshold));
-//*/
+ */
/*
//Formula based on probability distribution graph
float width = acos(max(0.0,r)); // convert to angle (width)
float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness
limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold
-//*/
+ */
limit = min(sqrt(pow(acos(max(0.0, r)) / HALF_PI, params.curve)), threshold); //convert to perceptual roughness and apply threshold
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 955ae2e588..9f42b0f814 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -10,7 +9,6 @@ VERSION_DEFINES
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
-/* clang-format on */
layout(location = 1) in vec3 normal_attrib;
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
layout(location = 2) in vec4 tangent_attrib;
@@ -20,11 +18,9 @@ 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)
+#if defined(UV2_USED) || defined(USE_LIGHTMAP) || defined(MODE_RENDER_MATERIAL)
layout(location = 5) in vec2 uv2_attrib;
#endif
@@ -39,9 +35,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;
@@ -53,7 +47,7 @@ layout(location = 6) out vec3 binormal_interp;
#endif
#ifdef USE_MATERIAL_UNIFORMS
-layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
+layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -66,8 +60,6 @@ VERTEX_SHADER_GLOBALS
/* clang-format on */
-// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now.
-// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
invariant gl_Position;
layout(location = 7) flat out uint instance_index;
@@ -79,7 +71,6 @@ layout(location = 8) out float dp_clip;
#endif
void main() {
-
instance_index = draw_call.instance_index;
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
@@ -157,9 +148,7 @@ void main() {
#endif
}
-#if defined(UV_USED)
uv_interp = uv_attrib;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
uv2_interp = uv2_attrib;
@@ -244,19 +233,13 @@ VERTEX_SHADER_CODE
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
- vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
+ vec3 vtx = vertex_interp;
float distance = length(vtx);
vtx = normalize(vtx);
vtx.xy /= 1.0 - vtx.z;
vtx.z = (distance / scene_data.z_far);
vtx.z = vtx.z * 2.0 - 1.0;
-
vertex_interp = vtx;
-#else
-
- float z_ofs = scene_data.z_offset;
- z_ofs += max(0.0, 1.0 - abs(normalize(normal_interp).z)) * scene_data.z_slope_scale;
- vertex_interp.z -= z_ofs;
#endif
@@ -267,10 +250,25 @@ VERTEX_SHADER_CODE
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
+
+#ifdef MODE_RENDER_DEPTH
+ if (scene_data.pancake_shadows) {
+ if (gl_Position.z <= 0.00001) {
+ gl_Position.z = 0.00001;
+ }
+ }
+#endif
+
+#ifdef MODE_RENDER_MATERIAL
+ if (scene_data.material_uv2_mode) {
+ gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0;
+ gl_Position.z = 0.00001;
+ gl_Position.w = 1.0;
+ }
+#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -281,16 +279,13 @@ VERSION_DEFINES
/* Varyings */
layout(location = 0) in vec3 vertex_interp;
-/* clang-format on */
layout(location = 1) in vec3 normal_interp;
#if defined(COLOR_USED)
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;
@@ -315,8 +310,13 @@ layout(location = 8) in float dp_clip;
#define world_normal_matrix instances.data[instance_index].normal_transform
#define projection_matrix scene_data.projection_matrix
+#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
+//both required for transmittance to be enabled
+#define LIGHT_TRANSMITTANCE_USED
+#endif
+
#ifdef USE_MATERIAL_UNIFORMS
-layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
+layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -421,7 +421,8 @@ float SchlickFresnel(float u) {
}
float GTR1(float NdotH, float a) {
- if (a >= 1.0) return 1.0 / M_PI;
+ if (a >= 1.0)
+ return 1.0 / M_PI;
float a2 = a * a;
float t = 1.0 + (a2 - 1.0) * NdotH * NdotH;
return (a2 - 1.0) / (M_PI * log(a2) * t);
@@ -434,9 +435,16 @@ 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, vec3 attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- vec3 transmission,
+void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 shadow_attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
+ float transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -467,7 +475,7 @@ LIGHT_SHADER_CODE
/* clang-format on */
#else
- float NdotL = dot(N, L);
+ float NdotL = min(A + dot(N, L), 1.0);
float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V);
float cNdotV = max(NdotV, 0.0);
@@ -477,11 +485,11 @@ LIGHT_SHADER_CODE
#endif
#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
- float cNdotH = max(dot(N, H), 0.0);
+ float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
#endif
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
- float cLdotH = max(dot(L, H), 0.0);
+ float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
#endif
if (metallic < 1.0) {
@@ -538,16 +546,48 @@ LIGHT_SHADER_CODE
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
- diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
+ diffuse_light += light_color * diffuse_color * shadow_attenuation * diffuse_brdf_NL * attenuation;
-#if defined(LIGHT_TRANSMISSION_USED)
- diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
+#if defined(LIGHT_BACKLIGHT_USED)
+ diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
#endif
#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
#endif
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+
+#ifdef SSS_MODE_SKIN
+
+ {
+ float scale = 8.25 / transmittance_depth;
+ float d = scale * abs(transmittance_z);
+ float dd = -d * d;
+ vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
+ vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
+ vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
+ vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
+ vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
+ vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
+
+ diffuse_light += profile * transmittance_color.a * diffuse_color * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI) * attenuation;
+ }
+#else
+
+ if (transmittance_depth > 0.0) {
+ float fade = clamp(abs(transmittance_z / transmittance_depth), 0.0, 1.0);
+
+ fade = pow(max(0.0, 1.0 - fade), transmittance_curve);
+ fade *= clamp(transmittance_boost - NdotL, 0.0, 1.0);
+
+ diffuse_light += diffuse_color * transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade * attenuation;
+ }
+
+#endif //SSS_MODE_SKIN
+
+#endif //LIGHT_TRANSMITTANCE_USED
}
if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
@@ -562,18 +602,18 @@ LIGHT_SHADER_CODE
blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
float intensity = blinn;
- specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+ specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L, N));
- float cRdotV = max(0.0, dot(R, V));
+ float cRdotV = clamp(A + dot(R, V), 0.0, 1.0);
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));
float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
- specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+ specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_TOON)
@@ -582,7 +622,7 @@ LIGHT_SHADER_CODE
float mid = 1.0 - roughness;
mid *= mid;
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
- diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
+ diffuse_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
#elif defined(SPECULAR_DISABLED)
// none..
@@ -613,7 +653,7 @@ LIGHT_SHADER_CODE
vec3 specular_brdf_NL = cNdotL * D * F * G;
- specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+ specular_light += specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
#endif
#if defined(LIGHT_CLEARCOAT_USED)
@@ -627,12 +667,12 @@ LIGHT_SHADER_CODE
float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
- specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+ specular_light += clearcoat_specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
#endif
}
#ifdef USE_SHADOW_TO_OPACITY
- alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0));
+ alpha = min(alpha, clamp(1.0 - length(shadow_attenuation * attenuation), 0.0, 1.0));
#endif
#endif //defined(USE_LIGHT_SHADER_CODE)
@@ -640,53 +680,116 @@ LIGHT_SHADER_CODE
#ifndef USE_NO_SHADOWS
-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;
+
+ //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));
+ }
- //todo optimize
+ 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;
-#ifdef SHADOW_MODE_PCF_13
+ //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));
+ }
- float avg = textureProj(shadow, 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);
-#endif
+ 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));
+ }
-#ifdef SHADOW_MODE_PCF_5
+ float avg = 0.0;
- 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);
+ 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));
+ }
-#endif
+ return avg * (1.0 / float(scene_data.soft_shadow_samples));
+}
+
+float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) {
+ //find blocker
+ float blocker_count = 0.0;
+ float blocker_average = 0.0;
-#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
+ 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));
+ }
- return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ 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;
+ blocker_count += 1.0;
+ }
+ }
-#endif
+ if (blocker_count > 0.0) {
+ //blockers found, do soft shadow
+ blocker_average /= blocker_count;
+ float penumbra = (pssm_coord.z - blocker_average) / blocker_average;
+ tex_scale *= penumbra;
+
+ float s = 0.0;
+ 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.directional_penumbra_shadow_samples);
+
+ } else {
+ //no blockers found, so no shadow
+ return 1.0;
+ }
}
#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,
-#ifdef LIGHT_TRANSMISSION_USED
- vec3 transmission,
+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
+#ifdef LIGHT_TRANSMITTANCE_USED
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -707,45 +810,249 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float normalized_distance = light_length * lights.data[idx].inv_radius;
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
- vec3 light_attenuation = vec3(omni_attenuation);
+ float light_attenuation = omni_attenuation;
+ vec3 shadow_attenuation = vec3(1.0);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb *= attenuation_energy.y;
+ float size_A = 0.0;
+
+ if (lights.data[idx].size > 0.0) {
+ float t = lights.data[idx].size / max(0.001, light_length);
+ size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ }
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth; //no transmittance by default
+#endif
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
// there is a shadowmap
- vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
- float shadow_len = length(splane);
- splane = normalize(splane);
- vec4 clamp_rect = lights.data[idx].atlas_rect;
+ vec4 v = vec4(vertex, 1.0);
+
+ vec4 splane = (lights.data[idx].shadow_matrix * v);
+ float shadow_len = length(splane.xyz); //need to remember shadow len from here
+
+ {
+ vec3 nofs = normal_interp * lights.data[idx].shadow_normal_bias / lights.data[idx].inv_radius;
+ nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp))));
+ v.xyz += nofs;
+ splane = (lights.data[idx].shadow_matrix * v);
+ }
+
+ float shadow;
+
+ if (lights.data[idx].soft_shadow_size > 0.0) {
+ //soft shadow
+
+ //find blocker
+
+ float blocker_count = 0.0;
+ float blocker_average = 0.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));
+ }
+
+ vec3 normal = normalize(splane.xyz);
+ vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, normal));
+ vec3 bitangent = normalize(cross(tangent, normal));
+ float z_norm = shadow_len * lights.data[idx].inv_radius;
+
+ tangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
+ bitangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
+
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+
+ vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
+
+ pos = normalize(pos);
+ vec4 uv_rect = lights.data[idx].atlas_rect;
+
+ if (pos.z >= 0.0) {
+ pos.z += 1.0;
+ uv_rect.y += uv_rect.w;
+ } else {
+ pos.z = 1.0 - pos.z;
+ }
+
+ pos.xy /= pos.z;
+
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+
+ float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), pos.xy, 0.0).r;
+ if (d < z_norm) {
+ blocker_average += d;
+ blocker_count += 1.0;
+ }
+ }
+
+ if (blocker_count > 0.0) {
+ //blockers found, do soft shadow
+ blocker_average /= blocker_count;
+ float penumbra = (z_norm - blocker_average) / blocker_average;
+ tangent *= penumbra;
+ bitangent *= penumbra;
+
+ z_norm -= lights.data[idx].inv_radius * lights.data[idx].shadow_bias;
+
+ shadow = 0.0;
+ 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;
- if (splane.z >= 0.0) {
+ pos = normalize(pos);
+ vec4 uv_rect = lights.data[idx].atlas_rect;
- splane.z += 1.0;
+ if (pos.z >= 0.0) {
+ pos.z += 1.0;
+ uv_rect.y += uv_rect.w;
+ } else {
+ pos.z = 1.0 - pos.z;
+ }
+
+ pos.xy /= pos.z;
+
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+ shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
+ }
- clamp_rect.y += clamp_rect.w;
+ shadow /= float(scene_data.penumbra_shadow_samples);
+ } else {
+ //no blockers found, so no shadow
+ shadow = 1.0;
+ }
} else {
+ splane.xyz = normalize(splane.xyz);
+ vec4 clamp_rect = lights.data[idx].atlas_rect;
+
+ if (splane.z >= 0.0) {
+ splane.z += 1.0;
+
+ clamp_rect.y += clamp_rect.w;
+
+ } else {
+ splane.z = 1.0 - splane.z;
+ }
+
+ splane.xy /= splane.z;
+
+ splane.xy = splane.xy * 0.5 + 0.5;
+ 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_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;
- splane.z = 1.0 - splane.z;
+ //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.xyz);
+ splane = normalize(splane.xyz);
+
+ if (splane.z >= 0.0) {
+ splane.z += 1.0;
+
+ } else {
+ splane.z = 1.0 - splane.z;
+ }
+
+ splane.xy /= splane.z;
+ splane.xy = splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * 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
+
+ float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
+ transmittance_z = (splane.z - shadow_z) / lights.data[idx].inv_radius;
}
+#endif
+
+ 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;
- splane.xy /= splane.z;
- splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = shadow_len * 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
- float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
+ vec3 local_v_ddy = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
+ local_v_ddy = normalize(local_v_ddy);
- light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ 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
- light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
@@ -763,9 +1070,15 @@ 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,
-#ifdef LIGHT_TRANSMISSION_USED
- vec3 transmission,
+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
+#ifdef LIGHT_TRANSMITTANCE_USED
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -792,31 +1105,157 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
- vec3 light_attenuation = vec3(spot_attenuation);
+ float light_attenuation = spot_attenuation;
+ vec3 shadow_attenuation = vec3(1.0);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb *= attenuation_energy.y;
+ float size_A = 0.0;
+
+ if (lights.data[idx].size > 0.0) {
+ float t = lights.data[idx].size / max(0.001, light_length);
+ size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ }
/*
if (lights.data[idx].atlas_rect!=vec4(0.0)) {
//use projector texture
}
*/
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth;
+#endif
+
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
//there is a shadowmap
- vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+
+ v.xyz -= spot_dir * lights.data[idx].shadow_bias;
+
+ float z_norm = dot(spot_dir, -light_rel_vec) * lights.data[idx].inv_radius;
+
+ float depth_bias_scale = 1.0 / (max(0.0001, z_norm)); //the closer to the light origin, the more you have to offset to reach 1px in the map
+ vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * lights.data[idx].shadow_normal_bias * depth_bias_scale;
+ normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z
+ v.xyz += normal_bias;
+
+ //adjust with bias
+ z_norm = dot(spot_dir, v.xyz - lights.data[idx].position) * lights.data[idx].inv_radius;
+
+ float shadow;
+
+ vec4 splane = (lights.data[idx].shadow_matrix * v);
splane /= splane.w;
- float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
- light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ if (lights.data[idx].soft_shadow_size > 0.0) {
+ //soft shadow
+
+ //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 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 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;
+ blocker_count += 1.0;
+ }
+ }
+
+ if (blocker_count > 0.0) {
+ //blockers found, do soft shadow
+ blocker_average /= blocker_count;
+ float penumbra = (z_norm - blocker_average) / blocker_average;
+ uv_size *= penumbra;
+
+ shadow = 0.0;
+ 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.penumbra_shadow_samples);
+
+ } else {
+ //no blockers found, so no shadow
+ shadow = 1.0;
+ }
+
+ } else {
+ //hard shadow
+ 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);
+ }
+
+ 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
+ {
+ 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
+ shadow_z / lights.data[idx].inv_radius;
+ //distance to light plane
+ float z = dot(spot_dir, -light_rel_vec);
+ transmittance_z = z - shadow_z;
+ }
+#endif //LIGHT_TRANSMITTANCE_USED
}
#endif //USE_NO_SHADOWS
- light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim * spot_attenuation, rim_tint,
@@ -834,7 +1273,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
}
void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
-
vec3 box_extents = reflections.data[ref_index].box_extents;
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
@@ -901,7 +1339,6 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
ambient_out.rgb *= ambient_out.a;
ambient_accum += ambient_out;
} else {
-
vec4 ambient_out;
ambient_out.a = blend;
ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
@@ -918,7 +1355,6 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
//standard voxel cone trace
vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
@@ -945,7 +1381,6 @@ vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction,
#ifdef GI_PROBE_USE_ANISOTROPY
vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
float radius = max(0.5, tan_half_angle * dist);
@@ -977,7 +1412,6 @@ vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_po
#else
vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
float radius = max(0.5, tan_half_angle * dist);
@@ -1009,7 +1443,6 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3
//standard voxel cone trace
vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
@@ -1040,7 +1473,6 @@ vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3
#endif
void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
-
position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
@@ -1101,7 +1533,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
vec3 light = vec3(0.0);
for (int i = 0; i < MAX_CONE_DIRS; i++) {
-
vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
#if defined(GI_PROBE_HIGH_QUALITY) || defined(GI_PROBE_LOW_QUALITY)
@@ -1133,7 +1564,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
light *= gi_probes.data[index].dynamic_range;
if (gi_probes.data[index].ambient_occlusion > 0.001) {
-
float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0;
float taps, blend;
@@ -1174,7 +1604,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
void main() {
-
#ifdef MODE_DUAL_PARABOLOID
if (dp_clip > 0.0)
@@ -1185,7 +1614,11 @@ void main() {
vec3 vertex = vertex_interp;
vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
- vec3 transmission = vec3(0.0);
+ vec3 backlight = vec3(0.0);
+ vec4 transmittance_color = vec4(0.0);
+ float transmittance_depth = 0.0;
+ float transmittance_curve = 1.0;
+ float transmittance_boost = 0.0;
float metallic = 0.0;
float specular = 0.5;
vec3 emission = vec3(0.0);
@@ -1223,9 +1656,7 @@ void main() {
}
#endif
-#if defined(UV_USED)
vec2 uv = uv_interp;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
vec2 uv2 = uv2_interp;
@@ -1254,6 +1685,14 @@ FRAGMENT_SHADER_CODE
/* clang-format on */
}
+#if defined(LIGHT_TRANSMITTANCE_USED)
+#ifdef SSS_MODE_SKIN
+ transmittance_color.a = sss_strength;
+#else
+ transmittance_color.a *= sss_strength;
+#endif
+#endif
+
#if !defined(USE_SHADOW_TO_OPACITY)
#if defined(ALPHA_SCISSOR_USED)
@@ -1299,7 +1738,78 @@ 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
@@ -1316,7 +1826,6 @@ FRAGMENT_SHADER_CODE
}
if (scene_data.use_reflection_cubemap) {
-
vec3 ref_vec = reflect(-view, normal);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
@@ -1336,7 +1845,6 @@ FRAGMENT_SHADER_CODE
#ifndef USE_LIGHTMAP
//lightmap overrides everything
if (scene_data.use_ambient_light) {
-
ambient_light = scene_data.ambient_light_color_energy.rgb;
if (scene_data.use_ambient_cubemap) {
@@ -1365,47 +1873,98 @@ FRAGMENT_SHADER_CODE
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
//gi probes
+#ifdef USE_LIGHTMAP
+
//lightmap
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
+ uint index = instances.data[instance_index].gi_offset;
+
+ vec3 wnormal = mat3(scene_data.camera_matrix) * normal;
+ const float c1 = 0.429043;
+ const float c2 = 0.511664;
+ const float c3 = 0.743125;
+ const float c4 = 0.886227;
+ const float c5 = 0.247708;
+ ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+
+ } else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
+ bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
+ uint ofs = instances.data[instance_index].gi_offset & 0xFFF;
+ vec3 uvw;
+ uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy;
+ uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF);
+
+ if (uses_sh) {
+ uvw.z *= 4.0; //SH textures use 4 times more data
+ vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
+ vec3 lm_light_l1n1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb;
+ vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
+ vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
+
+ uint idx = instances.data[instance_index].gi_offset >> 20;
+ vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
+
+ ambient_light += lm_light_l0 * 0.282095f;
+ ambient_light += lm_light_l1n1 * 0.32573 * n.y;
+ ambient_light += lm_light_l1_0 * 0.32573 * n.z;
+ ambient_light += lm_light_l1p1 * 0.32573 * n.x;
+ if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
+ vec3 r = reflect(normalize(-vertex), normal);
+ specular_light += lm_light_l1n1 * 0.32573 * r.y;
+ specular_light += lm_light_l1_0 * 0.32573 * r.z;
+ specular_light += lm_light_l1p1 * 0.32573 * r.x;
+ }
+ } else {
+ ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
+ }
+ }
+#endif
//lightmap capture
#ifdef USE_VOXEL_CONE_TRACING
- { // process giprobes
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- if (index1 != 0xFFFF) {
- vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
- //find arbitrary tangent and bitangent, then build a matrix
- vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
- vec3 tangent = normalize(cross(v0, normal));
- vec3 bitangent = normalize(cross(tangent, normal));
- mat3 normal_mat = mat3(tangent, bitangent, normal);
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- vec4 amb_accum = vec4(0.0);
- vec4 spec_accum = vec4(0.0);
- gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
+ vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
+ //find arbitrary tangent and bitangent, then build a matrix
+ vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, normal));
+ vec3 bitangent = normalize(cross(tangent, normal));
+ mat3 normal_mat = mat3(tangent, bitangent, normal);
- uint index2 = instances.data[instance_index].gi_offset >> 16;
+ vec4 amb_accum = vec4(0.0);
+ vec4 spec_accum = vec4(0.0);
+ gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- if (index2 != 0xFFFF) {
- gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- }
+ uint index2 = instances.data[instance_index].gi_offset >> 16;
- if (amb_accum.a > 0.0) {
- amb_accum.rgb /= amb_accum.a;
- }
+ if (index2 != 0xFFFF) {
+ gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ }
- if (spec_accum.a > 0.0) {
- spec_accum.rgb /= spec_accum.a;
- }
+ if (amb_accum.a > 0.0) {
+ amb_accum.rgb /= amb_accum.a;
+ }
- specular_light = spec_accum.rgb;
- ambient_light = amb_accum.rgb;
+ if (spec_accum.a > 0.0) {
+ spec_accum.rgb /= spec_accum.a;
}
+
+ specular_light = spec_accum.rgb;
+ ambient_light = amb_accum.rgb;
}
#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);
@@ -1415,7 +1974,6 @@ FRAGMENT_SHADER_CODE
uint reflection_probe_pointer = cluster_cell.z & CLUSTER_POINTER_MASK;
for (uint i = 0; i < reflection_probe_count; i++) {
-
uint ref_index = cluster_data.indices[reflection_probe_pointer + i];
reflection_process(ref_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
@@ -1432,7 +1990,6 @@ FRAGMENT_SHADER_CODE
}
{
-
#if defined(DIFFUSE_TOON)
//simplify for toon, as
specular_light *= specular * metallic * albedo * 2.0;
@@ -1457,63 +2014,250 @@ FRAGMENT_SHADER_CODE
{ //directional light
for (uint i = 0; i < scene_data.directional_light_count; i++) {
-
if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
- vec3 light_attenuation = vec3(1.0);
+ vec3 shadow_attenuation = vec3(1.0);
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth;
+#endif
if (directional_lights.data[i].shadow_enabled) {
float depth_z = -vertex.z;
vec4 pssm_coord;
+ 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]; \
+ vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \
+ normal_bias -= light_dir * dot(light_dir, normal_bias); \
+ m_var.xyz += normal_bias;
+
+ float shadow = 0.0;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 0)
+
+ 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);
+ }
+
+ shadow_color = directional_lights.data[i].shadow_color1.rgb;
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+ 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;
+ 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_color2.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 2)
+
+ 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;
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+
} else {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
- }
+ vec4 v = vec4(vertex, 1.0);
- pssm_coord /= pssm_coord.w;
+ BIAS_FUNC(v, 3)
- float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].blend_splits) {
+ 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);
+ }
+
+ shadow_color = directional_lights.data[i].shadow_color4.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+ }
+
+ 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) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+ 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);
+ }
+
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) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+ BIAS_FUNC(v, 2)
+ 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;
+ 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);
+
+ shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
+ 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);
+ } 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.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_coord /= pssm_coord.w;
+ pssm_blend = sqrt(pssm_blend);
- float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
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
- light_attenuation = mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
+ shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
+
+#undef BIAS_FUNC
}
- light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, light_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].size, directional_lights.data[i].color * directional_lights.data[i].energy, 1.0, shadow_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim, rim_tint,
@@ -1538,16 +2282,21 @@ FRAGMENT_SHADER_CODE
uint omni_light_pointer = cluster_cell.x & CLUSTER_POINTER_MASK;
for (uint i = 0; i < omni_light_count; i++) {
-
uint light_index = cluster_data.indices[omni_light_pointer + i];
if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
- light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ 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
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,
@@ -1571,16 +2320,21 @@ FRAGMENT_SHADER_CODE
uint spot_light_pointer = cluster_cell.y & CLUSTER_POINTER_MASK;
for (uint i = 0; i < spot_light_count; i++) {
-
uint light_index = cluster_data.indices[spot_light_pointer + i];
if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
- light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ 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
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,
@@ -1670,7 +2424,6 @@ FRAGMENT_SHADER_CODE
ao_light_affect = mix(1.0, ao, ao_light_affect);
specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect);
diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect);
-
#else
if (scene_data.ssao_enabled) {
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 baef1e060f..1cac12406a 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
@@ -3,7 +3,8 @@
layout(push_constant, binding = 0, std430) uniform DrawCall {
uint instance_index;
- uint pad[3]; //16 bits minimum size
+ uint pad; //16 bits minimum size
+ vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise
}
draw_call;
@@ -27,7 +28,6 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
layout(set = 0, binding = 3, std140) uniform SceneData {
-
mat4 projection_matrix;
mat4 inv_projection_matrix;
@@ -37,13 +37,23 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
vec2 viewport_size;
vec2 screen_pixel_size;
- //used for shadow mapping only
- float z_offset;
- float z_slope_scale;
-
float time;
float reflection_multiplier; // one normally, zero when rendering reflections
+ bool pancake_shadows;
+ 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 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;
@@ -67,6 +77,10 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
bool roughness_limiter_enabled;
vec4 ao_color;
+ bool material_uv2_mode;
+ uint pad_material0;
+ uint pad_material1;
+ uint pad_material2;
#if 0
vec4 ambient_light_color;
@@ -103,13 +117,13 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
float fog_height_curve;
#endif
}
-scene_data;
-#define INSTANCE_FLAGS_FORWARD_MASK 0x7
-#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
-#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
-#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
+scene_data;
+#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
+#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
+#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
+#define INSTANCE_FLAGS_USE_GIPROBE (1 << 11)
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
@@ -124,36 +138,44 @@ struct InstanceData {
mat4 transform;
mat4 normal_transform;
uint flags;
- uint instance_ofs; //instance_offset in instancing/skeleton buffer
- uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
+ uint instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
uint layer_mask;
+ vec4 lightmap_uv_scale;
};
-layout(set = 0, binding = 4, std430) buffer Instances {
+layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
InstanceData data[];
}
instances;
-struct LightData { //this structure needs to be 128 bits
+struct LightData { //this structure needs to be as packed as possible
vec3 position;
float inv_radius;
vec3 direction;
+ float size;
uint attenuation_energy; //attenuation
uint color_specular; //rgb color, a specular (8 bit unorm)
uint cone_attenuation_angle; // attenuation and angle, (16bit float)
- uint mask;
uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
- vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on 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[2];
+ vec4 projector_rect; //projector rect in srgb decal atlas
};
-layout(set = 0, binding = 5, std140) uniform Lights {
- LightData data[MAX_LIGHT_DATA_STRUCTS];
+layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
+ LightData data[];
}
lights;
struct ReflectionData {
-
vec3 box_extents;
float index;
vec3 box_offset;
@@ -173,18 +195,33 @@ struct DirectionalLightData {
vec3 direction;
float energy;
vec3 color;
+ float size;
float specular;
- vec3 shadow_color;
uint mask;
+ float softshadow_angle;
+ float soft_shadow_scale;
bool blend_splits;
bool shadow_enabled;
float fade_from;
float fade_to;
+ vec4 shadow_bias;
+ vec4 shadow_normal_bias;
+ vec4 shadow_transmittance_bias;
+ vec4 shadow_transmittance_z_scale;
+ vec4 shadow_range_begin;
vec4 shadow_split_offsets;
mat4 shadow_matrix1;
mat4 shadow_matrix2;
mat4 shadow_matrix3;
mat4 shadow_matrix4;
+ vec4 shadow_color1;
+ vec4 shadow_color2;
+ vec4 shadow_color3;
+ vec4 shadow_color4;
+ vec2 uv_scale1;
+ vec2 uv_scale2;
+ vec2 uv_scale3;
+ vec2 uv_scale4;
};
layout(set = 0, binding = 7, std140) uniform DirectionalLights {
@@ -215,18 +252,72 @@ gi_probes;
layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
+#define LIGHTMAP_FLAG_USE_DIRECTION 1
+#define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2
+
+struct Lightmap {
+ mat3 normal_xform;
+};
+
+layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps {
+ Lightmap data[];
+}
+lightmaps;
+
+layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+
+struct LightmapCapture {
+ vec4 sh[9];
+};
+
+layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures {
+ LightmapCapture data[];
+}
+lightmap_captures;
+
#define CLUSTER_COUNTER_SHIFT 20
#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 = 13) uniform texture2D decal_atlas;
+layout(set = 0, binding = 14) 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 = 15, std430) restrict readonly buffer Decals {
+ DecalData data[];
+}
+decals;
+
+layout(set = 0, binding = 16) uniform utexture3D cluster_texture;
-layout(set = 0, binding = 11, std430) buffer ClusterData {
+layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData {
uint indices[];
}
cluster_data;
-layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas;
+layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas;
+
+layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
+}
+global_variables;
// decal atlas
@@ -248,7 +339,7 @@ layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas;
layout(set = 2, binding = 1) uniform texture2D shadow_atlas;
-/* Set 1, Render Buffers */
+/* Set 3, Render Buffers */
layout(set = 3, binding = 0) uniform texture2D depth_buffer;
layout(set = 3, binding = 1) uniform texture2D color_buffer;
@@ -258,7 +349,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/screen_space_reflection.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
index e3c26c9b72..084f28d932 100644
--- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
@@ -1,16 +1,11 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
-
-
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
-
layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D source_diffuse;
layout(r32f, set = 0, binding = 1) uniform restrict readonly image2D source_depth;
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D ssr_image;
@@ -24,7 +19,6 @@ layout(set = 3, binding = 1) uniform sampler2D source_roughness;
#endif
layout(push_constant, binding = 2, std430) uniform Params {
-
vec4 proj_info;
ivec2 screen_size;
@@ -64,11 +58,10 @@ vec3 reconstructCSPosition(vec2 S, float z) {
}
void main() {
-
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
@@ -156,7 +149,6 @@ void main() {
float steps_taken = 0.0;
for (int i = 0; i < params.num_steps; i++) {
-
pos += line_advance;
z += z_advance;
w += w_advance;
@@ -187,7 +179,6 @@ void main() {
}
if (found) {
-
float margin_blend = 1.0;
vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.5 * 0.05); // make a uniform margin
@@ -220,7 +211,6 @@ void main() {
float roughness = texelFetch(source_roughness, ssC << 1, 0).r;
if (roughness > 0.001) {
-
float cone_angle = min(roughness, 0.999) * M_PI * 0.5;
float cone_len = length(final_pos - line_begin);
float op_len = 2.0 * tan(cone_angle) * cone_len; // opposite side of iso triangle
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
index 1a5dd5ab55..a5afe74cb2 100644
--- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
@@ -1,16 +1,11 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
-
-
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
-
layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D source_ssr;
layout(r8, set = 0, binding = 1) uniform restrict readonly image2D source_radius;
layout(rgba8, set = 1, binding = 0) uniform restrict readonly image2D source_normal;
@@ -22,7 +17,6 @@ layout(r8, set = 2, binding = 1) uniform restrict writeonly image2D dest_radius;
layout(r32f, set = 3, binding = 0) uniform restrict readonly image2D source_depth;
layout(push_constant, binding = 2, std430) uniform Params {
-
vec4 proj_info;
bool orthogonal;
@@ -58,7 +52,6 @@ const float gauss_table[GAUSS_TABLE_SIZE + 1] = float[](
);
float gauss_weight(float p_val) {
-
float idxf;
float c = modf(max(0.0, p_val * float(GAUSS_TABLE_SIZE)), idxf);
int idx = int(idxf);
@@ -80,7 +73,6 @@ vec3 reconstructCSPosition(vec2 S, float z) {
}
void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) {
-
for (int i = 1; i < params.steps; i++) {
float d = float(i * params.increment);
ivec2 tc = texcoord + increment * i;
@@ -104,7 +96,6 @@ void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor,
}
if (d < radius) {
-
float w = gauss_weight(d / radius);
accum += imageLoad(source_ssr, tc) * w;
#ifndef VERTICAL_PASS
@@ -116,11 +107,10 @@ void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor,
}
void main() {
-
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
index cec6c14c76..218605a962 100644
--- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
@@ -1,15 +1,11 @@
-/* clang-format off */
-[compute]
+#[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 sampler2D source_ssr;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
layout(set = 1, binding = 1) uniform sampler2D source_normal;
@@ -18,7 +14,6 @@ layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_depth
layout(rgba8, set = 3, binding = 1) uniform restrict writeonly image2D dest_normal;
layout(push_constant, binding = 1, std430) uniform Params {
-
ivec2 screen_size;
float camera_z_near;
float camera_z_far;
@@ -30,11 +25,10 @@ layout(push_constant, binding = 1, std430) uniform Params {
params;
void main() {
-
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
//do not filter, SSR will generate arctifacts if this is done
@@ -45,13 +39,11 @@ void main() {
vec3 normal;
if (params.filtered) {
-
color = vec4(0.0);
depth = 0.0;
normal = vec3(0.0);
for (int i = 0; i < 4; i++) {
-
ivec2 ofs = ssC << 1;
if (bool(i & 1)) {
ofs.x += 1;
@@ -75,7 +67,6 @@ void main() {
color /= 4.0;
depth /= 4.0;
normal = normalize(normal / 4.0) * 0.5 + 0.5;
-
} else {
color = texelFetch(source_ssr, ssC << 1, 0);
depth = texelFetch(source_depth, ssC << 1, 0).r;
diff --git a/servers/rendering/rasterizer_rd/shaders/sky.glsl b/servers/rendering/rasterizer_rd/shaders/sky.glsl
index 469925839a..9c59be6841 100644
--- a/servers/rendering/rasterizer_rd/shaders/sky.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/sky.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
@@ -17,14 +15,12 @@ layout(push_constant, binding = 1, std430) uniform Params {
params;
void main() {
-
vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0));
uv_interp = base_arr[gl_VertexIndex];
gl_Position = vec4(uv_interp, 1.0, 1.0);
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -33,7 +29,6 @@ VERSION_DEFINES
#define M_PI 3.14159265359
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
@@ -58,6 +53,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,15 +96,15 @@ 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;
};
layout(set = 3, binding = 0, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
+
directional_lights;
/* clang-format off */
@@ -116,7 +116,6 @@ FRAGMENT_SHADER_GLOBALS
layout(location = 0) out vec4 frag_color;
void main() {
-
vec3 cube_normal;
cube_normal.z = -1.0;
cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y;
@@ -178,4 +177,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..0b8f406213 100644
--- a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
@@ -1,30 +1,25 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
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]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D specular;
@@ -43,13 +38,12 @@ layout(set = 2, binding = 0) uniform sampler2D diffuse;
layout(location = 0) out vec4 frag_color;
void main() {
-
frag_color.rgb = texture(specular, uv_interp).rgb;
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/ssao.glsl b/servers/rendering/rasterizer_rd/shaders/ssao.glsl
index c9d7134610..346338181a 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
#define TWO_PI 6.283185307179586476925286766559
@@ -49,7 +47,6 @@ const int ROTATIONS[] = int[](
29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
19, 27, 21, 25, 39, 29, 17, 21, 27);
-/* clang-format on */
//#define NUM_SPIRAL_TURNS (7)
const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1];
@@ -212,7 +209,7 @@ float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in f
void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
index e90c788e08..3e63e3cb59 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[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 sampler2D source_ssao;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
@@ -46,10 +44,9 @@ const float gaussian[R + 1] =
//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
void main() {
-
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
@@ -122,7 +119,6 @@ void main() {
// We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
// so the IF statement has no runtime cost
if (r != 0) {
-
ivec2 ppos = ssC + params.axis * (r * params.filter_scale);
float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r;
ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit);
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
index 8728154347..263fca386f 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
vec2 pixel_size;
@@ -26,7 +24,6 @@ layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_imag
layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
void main() {
-
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThan(pos, params.source_size >> 1))) { //too large, do nothing
diff --git a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
index 41f8fde3ca..88a953562f 100644
--- a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
@@ -1,16 +1,11 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
-
-
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
-
#ifdef USE_25_SAMPLES
const int kernel_size = 13;
@@ -93,7 +88,6 @@ const vec4 skin_kernel[kernel_size] = vec4[](
#endif //USE_11_SAMPLES
layout(push_constant, binding = 1, std430) uniform Params {
-
ivec2 screen_size;
float camera_z_far;
float camera_z_near;
@@ -113,7 +107,6 @@ layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D dest_im
layout(set = 2, binding = 0) uniform sampler2D source_depth;
void do_filter(inout vec3 color_accum, inout vec3 divisor, vec2 uv, vec2 step, bool p_skin) {
-
// Accumulate the other samples:
for (int i = 1; i < kernel_size; i++) {
// Fetch color and depth for current sample:
@@ -138,11 +131,10 @@ void do_filter(inout vec3 color_accum, inout vec3 divisor, vec2 uv, vec2 step, b
}
void main() {
-
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
@@ -153,7 +145,6 @@ void main() {
float strength = abs(base_color.a);
if (strength > 0.0) {
-
vec2 dir = params.vertical ? vec2(0.0, 1.0) : vec2(1.0, 0.0);
// Fetch linear depth of current pixel:
diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
index 524ca5e2ea..b7c46a7d0e 100644
--- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
@@ -1,29 +1,24 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
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]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
@@ -48,6 +43,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,25 +254,74 @@ 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
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
-
vec3 glow = gather_glow(source_glow, uv_interp);
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
@@ -281,7 +329,6 @@ void main() {
// Glow
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
-
vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity;
// high dynamic range -> SRGB