A raytraced scene is rendered by drawing (a lot) of circles with increasing radius for each pixel. The amount of circles depends on the brightness of the corresponding circle.
#raytracer #pixels #rays
Log in to post a comment.
// Global code will be evaluated once. const turtle = new Turtle(); const canvas_size = 95; const light_position = [-2,3,-4]; const ro = [0,0,-3.5]; const sphere_pos = [-.2,0,0]; function get_image_intensity(x,y) { x *= 2; y *= 2; const rd = vec_normalize([x,-y,2]); let normal; let light = 0; let hit; let plane_hit = false; let dist = intersect_sphere(ro, rd, sphere_pos, 1); if (dist > 0) { hit = vec_add(ro, vec_mul(rd, dist)); normal = vec_normalize(hit); } else { dist = 10000; } if (rd[1] < 0) { const plane_dist = -1/rd[1]; if (plane_dist < dist) { dist = plane_dist; plane_hit = true; hit = vec_add(ro, vec_mul(rd, dist)); normal = [0,1,0]; } } if (dist > 0 && dist < 100) { let vec_to_light = vec_sub(hit, light_position); const light_dist_sqr = vec_dot(vec_to_light, vec_to_light); vec_to_light = vec_mul(vec_to_light, -1/Math.sqrt(light_dist_sqr)); let light = vec_dot(normal, vec_to_light); light *= 30 / light_dist_sqr; // shadow ? if (plane_hit && intersect_sphere(hit, vec_to_light, sphere_pos, 1) > 0) { light = 0; } return Math.sqrt(Math.min(1, Math.max(0,light))); } else { return 0; } } function draw_pixel(x, y, intensity, res) { const steps = 16; for (let i=0; i<steps; i++) { if (intensity < (i+1)/(steps)) { const radius = canvas_size/res * ( 1 - (i+.5)/(steps+.5)); turtle.penup(); turtle.goto( x * 2 * canvas_size + canvas_size/res, y * 2 * canvas_size - radius + canvas_size/res ); turtle.pendown(); turtle.circle(radius,360); } } } // The walk function will be called until it returns false. function walk(i) { const res = 32; const x = (i % res) / res -.5; const y = ((i/res)|0) / res -.5; let int = 0; for (let j=0; j<2; j++) { for (let k=0; k<2; k++) { int += get_image_intensity(x + (j-.5)/res, y + (k-.5)/res); } } draw_pixel(x, y, int/4, res); return i < res*res; } // math functions function vec_normalize(a) { const l = Math.sqrt(vec_dot(a,a)); return [a[0]/l,a[1]/l,a[2]/l]; } function vec_add(a, b) { return [a[0]+b[0], a[1]+b[1], a[2]+b[2]] } function vec_mul(a, b) { return [a[0]*b, a[1]*b, a[2]*b] } function vec_sub(a, b) { return [a[0]-b[0], a[1]-b[1], a[2]-b[2]] } function vec_dot(a, b) { return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]; } function intersect_sphere(ro, rd, center, radius) { const oc = vec_sub(ro, center); const b = vec_dot( oc, rd ); const c = vec_dot( oc, oc ) - radius * radius; const h = b*b - c; if( h<0 ) return -1; return -b - Math.sqrt( h ); }