### Raytraced Sphere #2

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

Created by reinder on 2018/10/24
541
0

```// 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) {
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;
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;

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

// 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];
}

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