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);
}