summaryrefslogtreecommitdiff
path: root/servers/rendering/rasterizer_rd/shaders/copy.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/rasterizer_rd/shaders/copy.glsl')
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl239
1 files changed, 186 insertions, 53 deletions
diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl
index 2b541f2660..2d7661f65f 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -1,87 +1,220 @@
/* clang-format off */
-[vertex]
+[compute]
#version 450
VERSION_DEFINES
-layout(location = 0) out vec2 uv_interp;
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
/* clang-format on */
-void main() {
+#define FLAG_HORIZONTAL (1 << 0)
+#define FLAG_USE_BLUR_SECTION (1 << 1)
+#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
+#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
+#define FLAG_GLOW_FIRST_PASS (1 << 4)
+#define FLAG_FLIP_Y (1 << 5)
+#define FLAG_FORCE_LUMINANCE (1 << 6)
+#define FLAG_COPY_ALL_SOURCE (1 << 7)
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec4 section;
+ ivec2 target;
+ uint flags;
+ uint pad;
+ // Glow.
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+ // DOF.
+ float camera_z_far;
+ float camera_z_near;
+ uint pad2[2];
+}
+params;
- vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- uv_interp = base_arr[gl_VertexIndex];
+layout(set = 0, binding = 0) uniform sampler2D source_color;
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
+#ifdef GLOW_USE_AUTO_EXPOSURE
+layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#endif
-/* clang-format off */
-[fragment]
+#if defined(MODE_LINEARIZE_DEPTH_COPY) || defined(MODE_SIMPLE_COPY_DEPTH)
+layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#elif defined(DST_IMAGE_8BIT)
+layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#else
+layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#endif
-#version 450
+void main() {
-VERSION_DEFINES
+ // Pixel being shaded
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThan(pos, params.section.zw))) { //too large, do nothing
+ return;
+ }
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
+#ifdef MODE_MIPMAP
-#ifdef MODE_CUBE_TO_DP
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ vec4 color = texelFetch(source_color, base_pos, 0);
+ color += texelFetch(source_color, base_pos + ivec2(0, 1), 0);
+ color += texelFetch(source_color, base_pos + ivec2(1, 0), 0);
+ color += texelFetch(source_color, base_pos + ivec2(1, 1), 0);
+ color /= 4.0;
-layout(set = 0, binding = 0) uniform samplerCube source_cube;
+ imageStore(dest_buffer, pos + params.target, color);
+#endif
-layout(push_constant, binding = 0, std430) uniform Params {
- float bias;
- float z_far;
- float z_near;
- bool z_flip;
-}
-params;
+#ifdef MODE_GAUSSIAN_BLUR
+
+ //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-layout(location = 0) out float depth_buffer;
+ if (bool(params.flags & FLAG_HORIZONTAL)) {
+
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.214607;
+ color += texelFetch(source_color, base_pos + ivec2(1, 0), 0) * 0.189879;
+ color += texelFetch(source_color, base_pos + ivec2(2, 0), 0) * 0.131514;
+ color += texelFetch(source_color, base_pos + ivec2(3, 0), 0) * 0.071303;
+ color += texelFetch(source_color, base_pos + ivec2(-1, 0), 0) * 0.189879;
+ color += texelFetch(source_color, base_pos + ivec2(-2, 0), 0) * 0.131514;
+ color += texelFetch(source_color, base_pos + ivec2(-3, 0), 0) * 0.071303;
+ imageStore(dest_buffer, pos + params.target, color);
+ } else {
+ ivec2 base_pos = (pos + params.section.xy);
+ vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.38774;
+ color += texelFetch(source_color, base_pos + ivec2(0, 1), 0) * 0.24477;
+ color += texelFetch(source_color, base_pos + ivec2(0, 2), 0) * 0.06136;
+ color += texelFetch(source_color, base_pos + ivec2(0, -1), 0) * 0.24477;
+ color += texelFetch(source_color, base_pos + ivec2(0, -2), 0) * 0.06136;
+ imageStore(dest_buffer, pos + params.target, color);
+ }
#endif
-void main() {
+#ifdef MODE_GAUSSIAN_GLOW
-#ifdef MODE_CUBE_TO_DP
+ //Glow uses larger sigma 1 for a more rounded blur effect
- vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+#define GLOW_ADD(m_ofs, m_mult) \
+ { \
+ ivec2 ofs = base_pos + m_ofs; \
+ if (all(greaterThanEqual(ofs, section_begin)) && all(lessThan(ofs, section_end))) { \
+ color += texelFetch(source_color, ofs, 0) * m_mult; \
+ } \
+ }
- normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
- normal = normalize(normal);
+ vec4 color = vec4(0.0);
- normal.y = -normal.y; //needs to be flipped to match projection matrix
- if (!params.z_flip) {
- normal.z = -normal.z;
+ if (bool(params.flags & FLAG_HORIZONTAL)) {
+
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ ivec2 section_begin = params.section.xy << 1;
+ ivec2 section_end = section_begin + (params.section.zw << 1);
+
+ GLOW_ADD(ivec2(0, 0), 0.174938);
+ GLOW_ADD(ivec2(1, 0), 0.165569);
+ GLOW_ADD(ivec2(2, 0), 0.140367);
+ GLOW_ADD(ivec2(3, 0), 0.106595);
+ GLOW_ADD(ivec2(-1, 0), 0.165569);
+ GLOW_ADD(ivec2(-2, 0), 0.140367);
+ GLOW_ADD(ivec2(-3, 0), 0.106595);
+ color *= params.glow_strength;
+ } else {
+
+ ivec2 base_pos = pos + params.section.xy;
+ ivec2 section_begin = params.section.xy;
+ ivec2 section_end = section_begin + params.section.zw;
+
+ GLOW_ADD(ivec2(0, 0), 0.288713);
+ GLOW_ADD(ivec2(0, 1), 0.233062);
+ GLOW_ADD(ivec2(0, 2), 0.122581);
+ GLOW_ADD(ivec2(0, -1), 0.233062);
+ GLOW_ADD(ivec2(0, -2), 0.122581);
+ color *= params.glow_strength;
}
- float depth = texture(source_cube, normal).r;
- depth_buffer = depth;
-
- // absolute values for direction cosines, bigger value equals closer to basis axis
- vec3 unorm = abs(normal);
-
- if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
- // x code
- unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
- } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
- // y code
- unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
- } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
- // z code
- unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+#undef GLOW_ADD
+
+ if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
+#ifdef GLOW_USE_AUTO_EXPOSURE
+
+ color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey;
+#endif
+ color *= params.glow_exposure;
+
+ float luminance = max(color.r, max(color.g, color.b));
+ float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom);
+
+ color = min(color * feedback, vec4(params.glow_luminance_cap));
+ }
+
+ imageStore(dest_buffer, pos + params.target, color);
+
+#endif
+
+#ifdef MODE_SIMPLE_COPY
+
+ vec4 color;
+ if (bool(params.flags & FLAG_COPY_ALL_SOURCE)) {
+ vec2 uv = vec2(pos) / vec2(params.section.zw);
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ uv.y = 1.0 - uv.y;
+ }
+ color = textureLod(source_color, uv, 0.0);
+
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+ imageStore(dest_buffer, pos + params.target, color);
+
} else {
- // oh-no we messed up code
- // has to be
- unorm = vec3(1.0, 0.0, 0.0);
+ color = texelFetch(source_color, pos + params.section.xy, 0);
+
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+
+ imageStore(dest_buffer, pos + params.target, color);
}
- float depth_fix = 1.0 / dot(normal, unorm);
+#endif
+
+#ifdef MODE_SIMPLE_COPY_DEPTH
+
+ vec4 color = texelFetch(source_color, pos + params.section.xy, 0);
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
- depth = 2.0 * depth - 1.0;
- float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
- depth_buffer = (linear_depth * depth_fix) / params.z_far;
+ imageStore(dest_buffer, pos + params.target, vec4(color.r));
+
+#endif
+
+#ifdef MODE_LINEARIZE_DEPTH_COPY
+
+ float depth = texelFetch(source_color, pos + params.section.xy, 0).r;
+ depth = depth * 2.0 - 1.0;
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ vec4 color = vec4(depth / params.camera_z_far);
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+ imageStore(dest_buffer, pos + params.target, color);
#endif
}