X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=demo_prior;a=blobdiff_plain;f=sdr%2Fwhitted.p.glsl;fp=sdr%2Fwhitted.p.glsl;h=fc197f67e42b429e3985da2b608e33ada9e37205;hp=567f127694bf39c5de5e5c0ec92bc34a97ebfd11;hb=ec776ad8bf37d25b9308e2c770d66247135b46ea;hpb=a89e74326444df1da625ad9614919bb7ad2352cb diff --git a/sdr/whitted.p.glsl b/sdr/whitted.p.glsl index 567f127..fc197f6 100644 --- a/sdr/whitted.p.glsl +++ b/sdr/whitted.p.glsl @@ -1,43 +1,139 @@ +struct Material { + vec3 diffuse, specular; + float shin; +}; + +struct HitPoint { + float dist; + vec3 pos, norm; + vec2 surfpos; + Material mtl; +}; + varying vec3 v_rorg, v_rdir; -vec3 shade(in vec3 pos, in vec3 norm); + +vec3 shade(in vec3 ro, in vec3 rd, in HitPoint hit); vec3 backdrop(in vec3 dir); -float isect_plane(in vec3 ro, in vec3 rd, out vec3 norm_ret); + +bool isect_scene(in vec3 ro, in vec3 rd, out HitPoint hit); + +bool isect_floor(in vec3 ro, in vec3 rd, float rad, out HitPoint hit); +bool isect_plane(in vec3 ro, in vec3 rd, in vec4 plane, out HitPoint hit); +bool isect_sphere(in vec3 ro, in vec3 rd, in vec3 pos, float rad, out HitPoint hit); + void main() { vec3 rdir = normalize(v_rdir); + gl_FragColor.rgb = backdrop(rdir); - float t = isect_floor(v_rorg, rdir); - if(t >= 0.0) { - gl_FragColor.rgb = shade(v_rorg + rdir * t, vec3(0.0, 1.0, 0.0)); + HitPoint hit; + if(isect_scene(v_rorg, rdir, hit)) { + gl_FragColor.rgb = shade(v_rorg, rdir, hit); } else { gl_FragColor.rgb = backdrop(rdir); } gl_FragColor.a = 1.0; } -vec3 shade(in vec3 pos, in vec3 norm) +vec3 shade(in vec3 ro, in vec3 rd, in HitPoint hit) { + return (hit.norm * 0.5 + 0.5) * hit.mtl.diffuse; } +#define M_PI 3.1415926 +#define M_2PI (M_PI * 2.0) + vec3 backdrop(in vec3 dir) { + return mix(vec3(0.8, 0.3, 0.2), vec3(0.2, 0.3, 0.8), smoothstep(-0.1, 0.1, dir.y)); } -float isect_floor(in vec3 ro, in vec3 rd) +const Material mtl_sph = Material(vec3(1.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0), 80.0); +const Material mtl_floor = Material(vec3(0.5, 0.5, 0.5), vec3(0.0, 0.0, 0.0), 1.0); + +bool isect_scene(in vec3 ro, in vec3 rd, out HitPoint hit_res) { - float t = isect_plane(ro, rd, vec4(0.0, 1.0, 0.0, -1.0)); - if(t < 0.0) return t; + HitPoint hit, nearest; - vec3 p = ro + rd * t; - float d = max(abs(p.x), max(abs(p.y), abs(p.z))); - if(d >= 1.0) return -1.0; + nearest.dist = 10000.0; - return t; + if(isect_sphere(ro, rd, vec3(0.0, 0.0, 0.0), 1.0, hit)) { + nearest = hit; + nearest.mtl = mtl_sph; + } + + if(isect_floor(ro, rd, 5.0, hit) && hit.dist < nearest.dist) { + nearest = hit; + nearest.mtl = mtl_floor; + } + + if(nearest.dist >= 10000.0) { + return false; + } + + hit_res = nearest; + return true; } -float isect_plane(in vec3 ro, in vec3 rd, in vec4 plane) +bool isect_floor(in vec3 ro, in vec3 rd, float rad, out HitPoint hit) { + if(!isect_plane(ro, rd, vec4(0.0, 1.0, 0.0, -1.0), hit)) { + return false; + } + + float d = max(abs(hit.pos.x), abs(hit.pos.z)); + if(d >= rad) return false; + + return true; +} + +bool isect_plane(in vec3 ro, in vec3 rd, in vec4 plane, out HitPoint hit) +{ + float ndotrd = dot(rd, plane.xyz); + + if(abs(ndotrd) < 1e-6) { + return false; + } + + vec3 pp = plane.xyz * plane.w; + vec3 pdir = pp - ro; + float t = dot(pdir, plane.xyz) / ndotrd; + + hit.dist = t; + hit.pos = ro + rd * t; + hit.norm = plane.xyz; + hit.surfpos = hit.pos.xz; /* XXX */ + return true; +} + +bool isect_sphere(in vec3 ro, in vec3 rd, in vec3 pos, float rad, out HitPoint hit) +{ + float a = dot(rd, rd); + float b = dot(rd * 2.0, (ro - pos)); + float c = dot(ro, ro) + dot(pos, pos) - 2.0 * dot(ro, pos) - rad * rad; + + float d = b * b - 4.0 * a * c; + if(d < 1e-6) { + return false; + } + + float t0 = (-b + sqrt(d)) / (2.0 * a); + float t1 = (-b - sqrt(d)) / (2.0 * a); + + if(t0 < 0.0) t0 = t1; + if(t1 < 0.0) t1 = t0; + float t = min(t0, t1); + + if(t < 1e-6) { + return false; + } + hit.dist = t; + hit.pos = ro + rd * t; + hit.norm = normalize(hit.pos - pos); + hit.surfpos.x = atan(hit.norm.z, hit.norm.x); + hit.surfpos.y = acos(hit.norm.y); + return true; }