From ec776ad8bf37d25b9308e2c770d66247135b46ea Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 6 Dec 2020 01:25:00 +0200 Subject: [PATCH] slightly improved raytracer --- sdr/whitted.p.glsl | 124 ++++++++++++++++++++++++++++++++++++++++++++++------ sdr/whitted.v.glsl | 8 +++- src/part_whitted.c | 3 ++ 3 files changed, 119 insertions(+), 16 deletions(-) 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; } diff --git a/sdr/whitted.v.glsl b/sdr/whitted.v.glsl index ad2878e..1c55752 100644 --- a/sdr/whitted.v.glsl +++ b/sdr/whitted.v.glsl @@ -1,13 +1,17 @@ #define FOV 0.873 /* about 50 deg */ +uniform float aspect; + varying vec3 v_rorg, v_rdir; void main() { gl_Position = gl_Vertex; - float dist = 1.0 / tan(FOV / 2.0); - vec3 dir = vec3(gl_MultiTexCoord0.xy * 2.0 - 1.0, dist); + vec2 s = vec2(aspect, 1.0); + + float dist = -1.0 / tan(FOV / 2.0); + vec3 dir = vec3((gl_MultiTexCoord0.xy * 2.0 - 1.0) * s, dist); v_rdir = gl_NormalMatrix * dir; v_rorg = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; } diff --git a/src/part_whitted.c b/src/part_whitted.c index 5b98ad6..d71585c 100644 --- a/src/part_whitted.c +++ b/src/part_whitted.c @@ -29,6 +29,7 @@ static int bnstate[8]; static int mouse_x, mouse_y; static unsigned int sdr; +static int uloc_aspect; void reg_whitted(void) @@ -42,6 +43,7 @@ static int init(void) if(!(sdr = create_program_load("sdr/whitted.v.glsl", "sdr/whitted.p.glsl"))) { return -1; } + uloc_aspect = get_uniform_loc(sdr, "aspect"); return 0; } @@ -71,6 +73,7 @@ static void draw(long tm) glTranslatef(0, 0, cam_dist); glUseProgram(sdr); + glUniform1f(uloc_aspect, win_aspect); glBegin(GL_QUADS); glTexCoord2f(0, 0); -- 1.7.10.4