aboutsummaryrefslogtreecommitdiff
path: root/src/models
diff options
context:
space:
mode:
authorJames Barnett <noreply@jamesbarnett.xyz>2025-07-26 11:17:10 +0100
committerJames Barnett <noreply@jamesbarnett.xyz>2025-07-26 11:17:10 +0100
commit10bfc58085c6ab7e62077a1a9b6a6d922fffb025 (patch)
tree3e1d3ff39891c2c2408235c209566f4c51915859 /src/models
parentebc500c522e7233fbc6037bce0569edf3a0b5136 (diff)
downloadjs-raytracer-10bfc58085c6ab7e62077a1a9b6a6d922fffb025.tar.xz
js-raytracer-10bfc58085c6ab7e62077a1a9b6a6d922fffb025.zip
Rework multithreaded rendering
Render worker tasks are now split into chunks rather than row blocks for better thread utilisation
Diffstat (limited to 'src/models')
-rw-r--r--src/models/Colour.ts16
-rw-r--r--src/models/FrameChunk.ts10
-rw-r--r--src/models/Geometry.ts49
-rw-r--r--src/models/Light.ts10
-rw-r--r--src/models/Material.ts27
-rw-r--r--src/models/RaytraceContext.ts43
-rw-r--r--src/models/Vector.ts40
7 files changed, 195 insertions, 0 deletions
diff --git a/src/models/Colour.ts b/src/models/Colour.ts
new file mode 100644
index 0000000..3c9d8da
--- /dev/null
+++ b/src/models/Colour.ts
@@ -0,0 +1,16 @@
+import {Vector} from './Vector';
+import 'reflect-metadata';
+
+export class Colour extends Vector {
+ constructor(readonly r: number, readonly g: number, readonly b: number) {
+ super(r, g, b);
+ }
+
+ static fromVector(vector: Vector): Colour {
+ return new Colour(vector.x, vector.y, vector.z);
+ }
+
+ toVector(): Vector {
+ return new Vector(this.r, this.g, this.b);
+ }
+}
diff --git a/src/models/FrameChunk.ts b/src/models/FrameChunk.ts
new file mode 100644
index 0000000..f05fd88
--- /dev/null
+++ b/src/models/FrameChunk.ts
@@ -0,0 +1,10 @@
+export class FrameChunk {
+ constructor(
+ readonly xStart: number,
+ readonly yStart: number,
+ readonly width: number,
+ readonly height: number
+ ) {
+
+ }
+} \ No newline at end of file
diff --git a/src/models/Geometry.ts b/src/models/Geometry.ts
new file mode 100644
index 0000000..556c7ea
--- /dev/null
+++ b/src/models/Geometry.ts
@@ -0,0 +1,49 @@
+import {Type} from 'class-transformer';
+import {Colour} from './Colour';
+import {Albedo, Material} from './Material';
+import {Vector} from './Vector';
+
+export class Sphere {
+ @Type(() => Vector)
+ readonly centerPoint: Vector;
+ @Type(() => Material)
+ readonly material: Material;
+ constructor(
+ readonly radius: number,
+ centerPoint: Vector,
+ material: Material
+ ) {
+ this.centerPoint = centerPoint;
+ this.material = material;
+ }
+}
+
+export class Plane {
+ @Type(() => Colour)
+ readonly checkerboardColour1: Colour;
+ @Type(() => Colour)
+ readonly checkerboardColour2: Colour;
+ constructor(
+ readonly yPos: number,
+ readonly width: number, // How far the plane extends into x/-x from 0
+ readonly zStartPos: number,
+ readonly zEndPos: number,
+ readonly checkerboardScale: number,
+ checkerboardColour1: Colour,
+ checkerboardColour2: Colour
+ ) {
+ this.checkerboardColour1 = checkerboardColour1;
+ this.checkerboardColour2 = checkerboardColour2;
+ }
+
+ getMaterialAtPoint(x: number, z: number): Material {
+ let colour: Colour;
+ // prettier-ignore
+ if ((Math.round(this.checkerboardScale * x) + Math.round(this.checkerboardScale * z)) & 1) {
+ colour = this.checkerboardColour1;
+ } else {
+ colour = this.checkerboardColour2;
+ }
+ return new Material(colour, new Albedo(1, 0, 0, 0), 0, 1);
+ }
+}
diff --git a/src/models/Light.ts b/src/models/Light.ts
new file mode 100644
index 0000000..58e4185
--- /dev/null
+++ b/src/models/Light.ts
@@ -0,0 +1,10 @@
+import {Type} from 'class-transformer';
+import {Vector} from './Vector';
+
+export class Light {
+ @Type(() => Vector)
+ readonly position: Vector;
+ constructor(position: Vector, readonly intensity: number) {
+ this.position = position;
+ }
+}
diff --git a/src/models/Material.ts b/src/models/Material.ts
new file mode 100644
index 0000000..f0af5e2
--- /dev/null
+++ b/src/models/Material.ts
@@ -0,0 +1,27 @@
+import {Type} from 'class-transformer';
+import {Colour} from './Colour';
+
+export class Material {
+ @Type(() => Colour)
+ readonly diffuseColour: Colour;
+ @Type(() => Albedo)
+ readonly albedo: Albedo;
+ constructor(
+ diffuseColour: Colour,
+ albedo: Albedo,
+ readonly specularExponent: number,
+ readonly refractiveIndex: number
+ ) {
+ this.diffuseColour = diffuseColour;
+ this.albedo = albedo;
+ }
+}
+
+export class Albedo {
+ constructor(
+ readonly diffuseAlbedo: number,
+ readonly specularAlbedo: number,
+ readonly reflectionAlbedo: number,
+ readonly refractionAlbedo: number
+ ) {}
+}
diff --git a/src/models/RaytraceContext.ts b/src/models/RaytraceContext.ts
new file mode 100644
index 0000000..acd4336
--- /dev/null
+++ b/src/models/RaytraceContext.ts
@@ -0,0 +1,43 @@
+import {Type} from 'class-transformer';
+import {Colour} from './Colour';
+import {Plane, Sphere} from './Geometry';
+import {Light} from './Light';
+
+export class RaytraceContext {
+ @Type(() => Sphere)
+ readonly spheres: Sphere[];
+ @Type(() => Plane)
+ readonly planes: Plane[];
+ @Type(() => Light)
+ readonly lights: Light[];
+ @Type(() => Colour)
+ readonly backgroundColour: Colour;
+ constructor(
+ readonly height: number,
+ readonly width: number,
+ readonly fov: number,
+ spheres: Sphere[],
+ planes: Plane[],
+ lights: Light[],
+ backgroundColour: Colour,
+ readonly options: RaytracerOptions
+ ) {
+ this.spheres = spheres;
+ this.planes = planes;
+ this.lights = lights;
+ this.backgroundColour = backgroundColour;
+ }
+}
+
+export interface RaytracerOptions {
+ numThreads: number;
+ shadows: boolean;
+ diffuseLighting: boolean;
+ specularLighting: boolean;
+ reflections: boolean;
+ refractions: boolean;
+ maxRecurseDepth: number;
+ maxDrawDistance: number;
+ bufferDrawCalls: boolean;
+ directMemoryTransfer: boolean;
+}
diff --git a/src/models/Vector.ts b/src/models/Vector.ts
new file mode 100644
index 0000000..2be8e57
--- /dev/null
+++ b/src/models/Vector.ts
@@ -0,0 +1,40 @@
+export class Vector {
+ constructor(readonly x: number, readonly y: number, readonly z: number) {}
+
+ add(v: Vector): Vector {
+ return new Vector(this.x + v.x, this.y + v.y, this.z + v.z);
+ }
+
+ addScalar(n: number): Vector {
+ return new Vector(this.x + n, this.y + n, this.z + n);
+ }
+
+ subtract(v: Vector): Vector {
+ return new Vector(this.x - v.x, this.y - v.y, this.z - v.z);
+ }
+
+ multiply(n: number): Vector {
+ return new Vector(this.x * n, this.y * n, this.z * n);
+ }
+
+ dotProduct(v: Vector): number {
+ return this.x * v.x + this.y * v.y + this.z * v.z;
+ }
+
+ normalise(): Vector {
+ const vecLength = this.norm();
+ return new Vector(
+ this.x / vecLength,
+ this.y / vecLength,
+ this.z / vecLength
+ );
+ }
+
+ norm(): number {
+ return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
+ }
+
+ negative(): Vector {
+ return new Vector(-this.x, -this.y, -this.z);
+ }
+}