Skip to content

arpanlaha/spectrum

Repository files navigation

Spectrum

Animate randomly-generated art with Rust + WebAssembly.

Spectrum

Background

The patterns generated by Spectrum are inspired by my submission to CS 225's MP1 Part 3, which invovles using the HSL color space to generate artwork.

Spectrum uses three different rendering methods:

  • WebGL + WebAssembly
  • WebAssembly only (2d canvas rendering context)
  • JavaScript only (2d canvas rendering context)

This originated as a way for me to test out Rust with WebAssembly, but after seeing the limitations of a CPU-only render (the WebAssembly-only implementation), I decided to try out implementing the same logic in WebGL to better understand the benefits of GPU-accelerated rendering. To illustrate the benefits of WebAssembly, I also created the JavaScript-only implementation as a comparison.

Algorithm

For a given canvas, a number of "sources" are assigned. Each source is assigned a random position (x, y) that falls within the canvas, and a random hue value in the HSL color space. Every pixel in the canvas is colored according to a weighted average of distance from each source, using the inverse squared distance from each source as the weighting factor (with a small constant added value to avoid dividing by zero).

However, as hue is a periodic/circular metric, weighting by mean will yield incorrect results. For example (in degrees), the mean of hues 10 and 350 will be 180, while the actual average hue will be 0. To account for this, each source's hue is broken in to sine and cosine components which are summed to reach a total. The arctangent is then applied to the total to calculate the resulting hue.

The formula for calculating the hue of a pixel is as follows:

formula

The saturation and lightness are held to be 100% and 50%, respectively, to get the purest form of the hue. The resulting HSL is converted to the RGB color space to set the color of the pixel.

Usage

Spectrum requires that you have the Rust default toolchain and Node.js installed. Additionally, wasm-pack is also required to build and package the WebAssembly.

Setup

Build and package the WebAssembly using the wasm-pack script:

npm run wasm-pack

Install NPM dependencies using npm install: (note: this requires the wasm-pack script to have been run as the results are marked as a local dependency)

npm install

Start the application for local development using npm start:

npm start

Build and bundle the application to the dist directory using the build script:

npm run build

Other scripts

Serve files from the dist directory using the serve script: (note: requires the build script to have been run to generate the dist directory):

npm run serve

Minify index.html and spectrum.css: (note: requires the build script to have been run to generate the dist directory):

npm run minify

Formatting

Format files or check for formatting compliance with the format and format:check scripts, respectively:

npm run format
npm run format:check

Linting

Check for lint errors or fix them with the lint and lint:fix scripts, respectively:

npm run lint
npm run lint:fix

References

Spectrum draws heavily from the following examples:

Formulas