This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
2017-05-19 11:09:12 -04:00

210 lines
6.9 KiB
GLSL

/* amount of offset to move one pixel left-right.
* In second pass some dimensions are zero to control verical/horizontal convolution */
uniform vec2 invrendertargetdim;
// color buffer
uniform sampler2D colorbuffer;
//blurred color buffer for DOF effect
uniform sampler2D blurredcolorbuffer;
// slightly blurred buffer
uniform sampler2D mblurredcolorbuffer;
// depth buffer
uniform sampler2D depthbuffer;
// this includes focal distance in x and aperture size in y
uniform vec4 dof_params;
// viewvectors for reconstruction of world space
uniform vec4 viewvecs[3];
// coordinates on framebuffer in normalized (0.0-1.0) uv space
in vec4 uvcoordsvar;
/* color texture coordinates, offset by a small amount */
in vec2 color_uv1;
in vec2 color_uv2;
in vec2 depth_uv1;
in vec2 depth_uv2;
in vec2 depth_uv3;
in vec2 depth_uv4;
out vec4 FragColor;
float calculate_far_coc(in float zdepth)
{
float coc = dof_params.x * max(1.0 - dof_params.y / zdepth, 0.0);
/* multiply by 1.0 / sensor size to get the normalized size */
return coc * dof_params.z;
}
/* near coc only! when distance is nearer than focus plane first term is bigger than one */
vec4 calculate_near_coc(in vec4 zdepth)
{
vec4 coc = dof_params.x * max(vec4(dof_params.y) / zdepth - vec4(1.0), vec4(0.0));
/* multiply by 1.0 / sensor size to get the normalized size */
return coc * dof_params.z;
}
/* first pass blurs the color buffer heavily and gets the near coc only.
* There are many texture accesses here but they are done on a
* lower resolution image so overall bandwidth is not a concern */
void first_pass()
{
vec4 depth;
vec4 zdepth;
vec4 coc;
float final_coc;
/* amount to add to uvs so that they move one row further */
vec2 offset_row[3];
offset_row[0] = vec2(0.0, invrendertargetdim.y);
offset_row[1] = 2.0 * offset_row[0];
offset_row[2] = 3.0 * offset_row[0];
/* heavily blur the image */
vec4 color = texture(colorbuffer, color_uv1);
color += texture(colorbuffer, color_uv1 + offset_row[1]);
color += texture(colorbuffer, color_uv2);
color += texture(colorbuffer, color_uv2 + offset_row[1]);
color /= 4.0;
depth.r = texture(depthbuffer, depth_uv1).r;
depth.g = texture(depthbuffer, depth_uv2).r;
depth.b = texture(depthbuffer, depth_uv3).r;
depth.a = texture(depthbuffer, depth_uv4).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = calculate_near_coc(zdepth);
depth.r = texture(depthbuffer, depth_uv1 + offset_row[0]).r;
depth.g = texture(depthbuffer, depth_uv2 + offset_row[0]).r;
depth.b = texture(depthbuffer, depth_uv3 + offset_row[0]).r;
depth.a = texture(depthbuffer, depth_uv4 + offset_row[0]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
depth.r = texture(depthbuffer, depth_uv1 + offset_row[1]).r;
depth.g = texture(depthbuffer, depth_uv2 + offset_row[1]).r;
depth.b = texture(depthbuffer, depth_uv3 + offset_row[1]).r;
depth.a = texture(depthbuffer, depth_uv4 + offset_row[1]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
depth.r = texture(depthbuffer, depth_uv1 + offset_row[2]).r;
depth.g = texture(depthbuffer, depth_uv2 + offset_row[2]).r;
depth.b = texture(depthbuffer, depth_uv3 + offset_row[2]).r;
depth.a = texture(depthbuffer, depth_uv4 + offset_row[2]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w));
FragColor = vec4(color.rgb, final_coc);
}
/* second pass, gaussian blur the downsampled image */
void second_pass()
{
vec4 depth = vec4(texture(depthbuffer, uvcoordsvar.xy).r);
/* clever sampling to sample 2 pixels at once. Of course it's not real gaussian sampling this way */
vec4 color = texture(colorbuffer, uvcoordsvar.xy) * 0.3125;
color += texture(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
color += texture(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
color += texture(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
color += texture(colorbuffer, uvcoordsvar.xy - invrendertargetdim) * 0.234375;
color += texture(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375;
color += texture(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625;
FragColor = color;
}
/* third pass, calculate the final coc from blurred and unblurred images */
void third_pass()
{
vec4 color = texture(colorbuffer, uvcoordsvar.xy);
vec4 color_blurred = texture(blurredcolorbuffer, uvcoordsvar.xy);
float coc = 2.0 * max(color_blurred.a, color.a); -color.a;
FragColor = vec4(color.rgb, coc);
}
/* fourth pass, blur the final coc once to get rid of discontinuities */
void fourth_pass()
{
vec4 color = texture(colorbuffer, uvcoordsvar.xz);
color += texture(colorbuffer, uvcoordsvar.yz);
color += texture(colorbuffer, uvcoordsvar.xw);
color += texture(colorbuffer, uvcoordsvar.yw);
FragColor = color / 4.0;
}
vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
{
float weight = 1.0 / 17.0;
vec4 result = weight * color;
weight *= 4.0;
result += weight * texture(colorbuffer, uv + color_uv1.xy);
result += weight * texture(colorbuffer, uv - color_uv1.xy);
result += weight * texture(colorbuffer, uv + color_uv1.yx);
result += weight * texture(colorbuffer, uv - color_uv1.yx);
return result;
}
/* fourth pass, just visualize the third pass contents */
void fifth_pass()
{
vec4 factors;
vec4 color_orig = texture(colorbuffer, uvcoordsvar.xy);
vec4 highblurred = texture(blurredcolorbuffer, uvcoordsvar.xy);
vec4 mediumblurred = texture(mblurredcolorbuffer, uvcoordsvar.xy);
vec4 smallblurred = small_sample_blur(colorbuffer, uvcoordsvar.xy, color_orig);
float depth = texture(depthbuffer, uvcoordsvar.xy).r;
float zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)).r;
float coc_far = clamp(calculate_far_coc(zdepth), 0.0, 1.0);
/* calculate final coc here */
float coc = max(max(coc_far, mediumblurred.a), 0.0);
float width = 2.5;
float radius = 0.2;
factors.x = 1.0 - clamp(width * coc, 0.0, 1.0);
factors.y = 1.0 - clamp(abs(width * (coc - 2.0 * radius)), 0.0, 1.0);
factors.z = 1.0 - clamp(abs(width * (coc - 3.0 * radius)), 0.0, 1.0);
factors.w = 1.0 - clamp(abs(width * (coc - 4.0 * radius)), 0.0, 1.0);
/* blend! */
vec4 color = factors.x * color_orig + factors.y * smallblurred + factors.z * mediumblurred + factors.w * highblurred;
color /= dot(factors, vec4(1.0));
/* using original color is not correct, but use that for now because alpha of
* blurred buffers uses CoC instead */
FragColor = vec4(color.rgb, color_orig.a);
}
void main()
{
#ifdef FIRST_PASS
first_pass();
#elif defined(SECOND_PASS)
second_pass();
#elif defined(THIRD_PASS)
third_pass();
#elif defined(FOURTH_PASS)
fourth_pass();
#elif defined(FIFTH_PASS)
fifth_pass();
#endif
}