diff options
Diffstat (limited to 'servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl')
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl b/servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl new file mode 100644 index 0000000000..7042b72d2a --- /dev/null +++ b/servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl @@ -0,0 +1,141 @@ +/* clang-format off */ +[compute] +/* clang-format on */ +#version 450 + +VERSION_DEFINES + +#define BLOCK_SIZE 8 + +layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; + + +#ifdef MODE_GEN_BLUR_SIZE +layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image; +layout(set = 1, binding = 0) uniform sampler2D source_depth; +#endif + +#ifdef MODE_GEN_BOKEH +layout(set = 2, binding = 0) uniform sampler2D color_texture; +layout(set = 1, binding = 0) uniform sampler2D source_depth; +layout(rgba16f, set = 0, binding = 0) uniform restrict writeonly image2D bokeh_image; +#endif + +#ifdef MODE_COMPOSITE_BOKEH +layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image; +layout(set = 1, binding = 0) uniform sampler2D source_bokeh; +#endif + + + + +layout(push_constant, binding = 1, std430) uniform Params { + ivec2 size; + float z_far; + float z_near; + + bool orthogonal; + float blur_size; + float blur_scale; + uint pad; + + bool blur_near_active; + float blur_near_begin; + float blur_near_end; + bool blur_far_active; + float blur_far_begin; + float blur_far_end; + uint pad2[2]; + +} params; + +#ifndef MODE_COMPOSITE_BOKEH + +float get_depth_at_pos(vec2 uv) { + float depth = textureLod(source_depth,uv,0.0).x; + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } + return depth; +} + +float get_blur_size(float depth) { + + if (params.blur_near_active && depth < params.blur_near_begin) { + return smoothstep(params.blur_near_end,params.blur_near_begin,depth) * params.blur_size; + } + + if (params.blur_far_active && depth > params.blur_far_begin) { + return smoothstep(params.blur_far_begin,params.blur_far_end,depth) * params.blur_size; + } + + return 0.0; +} + +#endif + +const float GOLDEN_ANGLE = 2.39996323; + +void main() { + + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + if (any(greaterThan(pos,params.size))) { //too large, do nothing + return; + } + + vec2 uv = vec2(pos) / vec2(params.size); + +#ifdef MODE_GEN_BLUR_SIZE + //precompute size in alpha channel + float depth = get_depth_at_pos(uv); + float size = get_blur_size(depth); + + vec4 color = imageLoad(color_image,pos); + color.a = size; + imageStore(color_image,pos,color); +#endif + +#ifdef MODE_GEN_BOKEH + + float depth = get_depth_at_pos(uv); + float size = get_blur_size(depth); + vec4 color = texture(color_texture,uv); + float accum = 1.0; + float radius = params.blur_scale; + vec2 pixel_size = 1.0/vec2(params.size); + + 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_depth = get_depth_at_pos(suv); + if (sample_depth > depth) { + sample_color.a = clamp(sample_color.a, 0.0, size*2.0); + } + + float m = smoothstep(radius-0.5, radius+0.5, sample_color.a); + color += mix(color/accum, sample_color, m); + accum += 1.0; + radius += params.blur_size/radius; + } + + color /= accum; + + imageStore(bokeh_image,pos,color); +#endif + +#ifdef MODE_COMPOSITE_BOKEH + + vec4 color = imageLoad(color_image,pos); + vec4 bokeh = texture(source_bokeh,uv); + if (max(color.a,bokeh.a) > 0.5) { //there is some blur in this pixel, so use bokeh + color = bokeh; + } + color.a=0; //reset alpha + imageStore(color_image,pos,color); +#endif + +} |