Based on the shaders of the excellent article 'Cameras and Lenses' by @BCiechanowski: ciechanow.ski/cameras-and-lenses/
Log in to post a comment.
#version 300 es precision highp float; // Cameras and Lenses. Created by Reinder Nijhoff 2020 // https://oneshader.net/shader/a170d04c71 // // Based on the shaders of the excellent article 'Cameras and Lenses' by // @BCiechanowski: https://ciechanow.ski/cameras-and-lenses/ // uniform float focusingDistance; // value=2, min=1.5, max=4, step=0.01 uniform float focalLength; // value=0.46, min=0.38, max=0.5, step=0.01 uniform float aperture; // value=0.15, min=0.005, max=0.25, step=0.001 uniform vec2 iResolution; in vec2 vScreen; out vec4 fragColor; vec2 hash2(float n) { return fract(n * vec2(0.754878, 0.56984)); } vec2 random_in_unit_disk(float seed) { vec2 h = hash2(seed) * vec2(1.,6.28318530718); return sqrt(h.x) * vec2(sin(h.y),cos(h.y)); } // https://www.shadertoy.com/view/4d2XWV by Inigo Quilez float sphere_intersect(vec3 ro, vec3 rd, vec4 sph) { vec3 oc = ro - sph.xyz; float b = dot( oc, rd ); float c = dot( oc, oc ) - sph.w*sph.w; float h = b*b - c; if( h<0.0 ) return -1.0; return -b - sqrt( h ); } vec3 render(vec3 ro, vec3 rd) { vec3 color = vec3(0.94); // sphere positions and sphere colors const vec4 s0 = vec4(0.7, 0.7, 0.3, 0.3); const vec4 s1 = vec4(-0.7, -0.7, 0.5, 0.5); const vec3 c0 = vec3(1.0, 0.1, 0.05); const vec3 c1 = vec3(0.1, 0.8, 0.05); vec4 sphere = rd.y > 0.0 ? s0 : s1; float dist = sphere_intersect(ro, rd, sphere); if (dist > 0.0) { // spheres float diff = 0.5 + 0.5 * normalize(ro + rd * dist - sphere.xyz).z; color = ( rd.y > 0.0 ? c0 : c1) * sqrt(diff); } else if (rd.z < 0.0) { // plane float dist = -ro.z / rd.z; vec2 pos = ro.xy + rd.xy * dist; if (abs(pos.x) < 2. && abs(pos.y) < 2.) { // checker pattern vec2 fpos = floor(pos * 2.0); float s = mod(fpos.x + fpos.y, 2.0) > 0.5 ? 0.54 : 0.66; // fake ambient occlusion vec2 d0 = pos - s0.xy; float f0 = 12.0 * dot(d0, d0); vec2 d1 = pos - s1.xy; float f1 = 5.0 * dot(d1, d1); float f = (f0*f1 - 1.0) / ((f0 + 1.0)*(f1 + 1.0)); color = vec3(f * s); } } return color; } void main(void) { float seed = fract(sin(dot(gl_FragCoord.xy, vec2(1234.0, 5134.0)))); vec3 ro = vec3(3.1 - focalLength, 0, 0.7); vec3 color = vec3(0.0); float ratio = focusingDistance / focalLength; for (float x = 0.0; x <= 6.0; x += 1.) { for (float y = 0.0; y <= 6.0; y += 1.) { vec2 offset = random_in_unit_disk(seed + x + 5.0 * y) * aperture; vec2 aa = vec2(x - 2.5, y - 2.5) * (0.4 / iResolution.y); vec3 rd = normalize(vec3(-focusingDistance, (vScreen + aa) * ratio * 0.3 + offset)); color += render(ro - vec3(0.0, offset), rd); } } color *= (1.0/36.); fragColor = vec4(pow(color.rgb, vec3(0.45454)), 1.0); }