thewhodidthis / rtx

The Raytracer Challenge in JS

Home Page:https://thewhodidthis.github.io/rtx/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

about

Going through The Ray Tracer Challenge in JS.

This took three plus days to render

I put this here because none of the JavaScript implementations I have come across on GitHub are cover to cover complete. The ones I found seem to also be OOP based, whereas I am using classes selectively for defining shapes mostly. I did choose to extend from Array when it comes to tuples and matrices, but the corresponding math helpers are pure functions.

There are probably more concise ways of creating a ray tracer1, but I enjoyed the mildly comprehensive, test first, language agonstic approach in this book. I am also happy to have used Node.js, Deno, and browser cross compatible plain JS, as well as solely console.assert() for unit testing.

Next to practical understanding, my goal taking this up was to work out WebGL model, view, projection matrices and to avoid having to rely on external libraries like glMatrix if possible as a result. I am already using the relevant bits on Cyclops and Hypnotized, but should be extracting those parts out into a separate branch ideally.

setup

Import from GitHub directly:

import { mat4, Matrix } from "https://thewhodidthis.github.io/rtx/matrix.js"

console.assert(mat4() instanceof Matrix)

Source from an import map, given an imports.json of:

{
  "imports": {
    "@thewhodidthis/rtx": "https://thewhodidthis.github.io/rtx/main.js"
  }
}

And an example.js of:

import { vector, Tuple } from "@thewhodidthis/rtx"

console.assert(vector() instanceof Tuple)

Using Deno for example:

deno run --import-map=imports.json example.js

usage

Rendering the exercise from Chapter 6:

import { color, point, multiply, subtract, normalize } from "./tuple.js"
import { intersect, sphere } from "./sphere.js"
import { WHITE } from "./pattern.js"
import { pointlight } from "./light.js"
import { hit } from "./intersection.js"
import { material, lighting } from "./material.js"
import { ray, position } from "./ray.js"
import { canvas, ppm } from "./canvas.js"

const origin = point(0, 0, -5)
const c = canvas(300, 300)

const wall = 7
const resolution = wall / c.width
const center = wall / 2

const shape = sphere()
const purple = color(1, 0.2, 0.5)

shape.material = material(purple)

const light = pointlight(point(-10, 10, -10), WHITE)

for (let j = 0; j < c.height; j += 1) {
  const y = center - (resolution * j)

  for (let i = 0; i < c.width; i += 1) {
    const x = (resolution * i) - center

    const direction = normalize(subtract(point(x, y, 10), origin))
    const r = ray(origin, direction)

    const k = intersect(shape, r)
    const h = hit(k)

    if (h) {
      const eye = multiply(r.direction, -1)
      const p = position(r, h.t)
      const n = shape.normal(shape, p)

      const shade = lighting(shape.material, shape, light, p, eye, n)

      c.write(i, j, shade)
    }
  }
}

console.log(ppm(c))

see also

Footnotes

  1. @ssloy/tinyraytracer might be one.

About

The Raytracer Challenge in JS

https://thewhodidthis.github.io/rtx/

License:GNU Affero General Public License v3.0


Languages

Language:JavaScript 100.0%Language:HTML 0.0%