// // Inspired by blog post: http://tuxedolabs.blogspot.fr/2018/05/bokeh-depth-of-field-in-single-pass.html // Original scene: https://www.shadertoy.com/view/MsG3Dz // // There is still lots of flickering, I'm guessing this is because of the original scene's lighting. // Using PBR would probably fix the crazy specular values we get sometimes // As a quick way to remove flickering, we can use AA // #define DISPLAY_GAMMA 1.8 #define GOLDEN_ANGLE 2.39996323 #define MAX_BLUR_SIZE 20.0 // Smaller = nicer blur, larger = faster #define RAD_SCALE 0.5 #define uFar 10.0 float getBlurSize(float depth, float focusPoint, float focusScale) { float coc = clamp((1.0 / focusPoint - 1.0 / depth)*focusScale, -1.0, 1.0); return abs(coc) * MAX_BLUR_SIZE; } vec3 depthOfField(vec2 texCoord, float focusPoint, float focusScale) { vec4 Input = texture(iChannel0, texCoord).rgba; float centerDepth = Input.a * uFar; float centerSize = getBlurSize(centerDepth, focusPoint, focusScale); vec3 color = Input.rgb; float tot = 1.0; vec2 texelSize = 1.0 / iResolution.xy; float radius = RAD_SCALE; for (float ang = 0.0; radius < MAX_BLUR_SIZE; ang += GOLDEN_ANGLE) { vec2 tc = texCoord + vec2(cos(ang), sin(ang)) * texelSize * radius; vec4 sampleInput = texture(iChannel0, tc).rgba; vec3 sampleColor = sampleInput.rgb; float sampleDepth = sampleInput.a * uFar; float sampleSize = getBlurSize(sampleDepth, focusPoint, focusScale); if (sampleDepth > centerDepth) { sampleSize = clamp(sampleSize, 0.0, centerSize*2.0); } float m = smoothstep(radius-0.5, radius+0.5, sampleSize); color += mix(color/tot, sampleColor, m); tot += 1.0; radius += RAD_SCALE/radius; } return color /= tot; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.xy; vec4 color = texture(iChannel0, uv).rgba; float focusPoint = 78.0; float focusScale = (0.5 + sin(iTime) * 0.5) * 50.0; color.rgb = depthOfField(uv, focusPoint, focusScale); //tone mapping color.rgb = vec3(1.7, 1.8, 1.9) * color.rgb / (1.0 + color.rgb); //inverse gamma correction fragColor = vec4(pow(color.rgb, vec3(1.0 / DISPLAY_GAMMA)), 1.0); // Debug depth //fragColor.rgb = vec3(color.a)*0.015; }