Open WoodNeck opened 5 years ago
#define FLT_MAX 3.402823466e+38 precision mediump float; uniform vec4 uScreenSize; uniform float uTime; float gSeed = 0.; struct ray { vec3 o, d; }; struct record { float t; vec3 p, n; }; struct hitable { vec3 c; float r; }; float rand(vec2 co) { return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453) * 2. - 1.; } vec3 randomInUnitSphere(float sd) { return vec3( rand(vec2(sd += .1, sd += .1)), rand(vec2(sd += .1, sd += .1)), rand(vec2(sd += .1, sd += .1)) ); } bool sphere(hitable sp, ray r, float tMin, float tMax, out record hr) { vec3 oc = r.o - sp.c; float a = dot(r.d, r.d); float b = dot(oc, r.d); float c = dot(oc, oc) - sp.r * sp.r; float d = b * b - a * c; if (d < 0.) return false; float s = sqrt(d); float val = (-b - s) / a; if (val > tMin && val < tMax) { hr.p = r.o + val * r.d; hr.n = (hr.p - sp.c) / sp.r; hr.t = val; return true; } val = (-b + s) / a; if (val > tMin && val < tMax) { hr.p = r.o + val * r.d; hr.n = (hr.p - sp.c) / sp.r; hr.t = val; return true; } return false; } bool worldHit(ray r, float tMin, float tMax, hitable[2] sp, out record rec) { bool hit = false; hit = hit || sphere(sp[0], r, tMin, tMax, rec); hit = hit || sphere(sp[1], r, tMin, tMax, rec); return hit; } vec3 rayDirection(float fov, vec2 size, vec2 fragCoord) { vec2 xy = fragCoord - size / 2.0; float z = size.y / tan(radians(fov) / 2.0); return normalize(vec3(xy, -z)); } vec3 color(ray r, hitable[2] sp, float sd) { const int MAX_RECURSION = 20; float tMax = FLT_MAX; vec3 col = vec3(1); record hr; for (int i = 0; i < MAX_RECURSION; i++) { if (worldHit(r, 0.001, FLT_MAX, sp, hr)) { col *= .5; vec3 rd = normalize(hr.p + hr.n + randomInUnitSphere(sd)); r.o = hr.p; r.d = rd; } else { float t = .5 * r.d.y + .5; col *= mix(vec3(1), vec3(.5, .7, 1.), t); return col; } } return col; } void main() { vec3 eye = vec3(0., 0., 5.); const int ns = 100; hitable spheres[2]; spheres[0] = hitable(vec3(0, 0, -1), 1.); spheres[1] = hitable(vec3(0, -101, -1.), 100.); float sd = rand(gl_FragCoord.xy); vec3 col = vec3(0, 0, 0); float ins = 1. / float(ns); for (int i = 0; i < ns; i++) { float rv = rand(gl_FragCoord.xy + float(i) * ins); vec3 rd = rayDirection(45., uScreenSize.xy, gl_FragCoord.xy + rv); ray r = ray(eye, rd); col += color(r, spheres, sd); sd += 0.1; } col = col * ins; col = vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2])); gl_FragColor = vec4(col, 1); }