12: Multiple Workers
- Download code
- 12-multiple-workers.zip
- Live example
- examples/12-multiple-workers/index.html
In the last section, we looked at using the ImageData
and the Uint8ClampedArray
types to reduce the overhead of passing messages between our background workers and our frontend web application.
Multiple Workers
We can improve the performance of our ray tracer even further by dividing our image into sections, creating a dedicated worker for each section of the image, and then allowing the browser to run those workers across multiple CPU cores.
First, we need to modify our renderer, so that we can render a specific subset of our full image. We’ll pass a new block
parameter into the render()
method, and modify the renderer so that it will only render the pixels within that block:
// modules/renderer.js
import { Color } from './color.js';
import { Vector } from './vector.js';
import { Camera } from './camera.js';
import { Scene } from './scene.js';
class Renderer {
constructor(canvasWidth, canvasHeight) {
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
}
render(scene, callback, block) {
let xMin = (block && block.x ? block.x : 0);
let xMax = (block && block.width ? xMin + block.width : this.canvasWidth);
let yMin = (block && block.y ? block.y : 0);
let yMax = (block && block.height ? yMin + block.height: this.canvasHeight);
console.log(`Rendering block (${xMin}, ${yMin}) => (${xMax}, ${yMax})`);
for (let pixelY = yMin; pixelY < yMax; pixelY++) {
for (let pixelX = xMin; pixelX < xMax; pixelX++) {
let sceneX = (pixelX / this.canvasWidth) - 0.5;
let sceneY = (pixelY / this.canvasHeight) - 0.5;
let pixelColor = scene.trace(sceneX, sceneY);
callback(pixelX, pixelY, pixelColor);
}
}
}
}
export { Renderer, Scene, Camera, Color, Vector };
- Download code
- 12-multiple-workers.zip
- Live example
- examples/12-multiple-workers/index.html