Rendering Spins using WebGL and JavaScript.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Rendering Spins using WebGL and JavaScript.


Just download the minified JavaScript file or clone this repository:

git clone

WebGLSpins.js has no dependencies to other JavaScript files, but it requires browser support of WebGL 1.0 and the ANGLE_instanced_arrays and OES_element_index_uint extensions.

Usage Examples

A static, minimal example showing a single spin arrow:

<canvas id="webgl-canvas" width="800" height="800"></canvas>
<script src="webglspins.js"></script>
<script type='text/javascript'>
  var webglspins = new WebGLSpins(document.getElementById('webgl-canvas'));
  webglspins.updateSpins(1, [0, 0, 0], [1, 0, 0]);

For a more complex examples showing the different colormaps and animated spins, see this demo.


To render spins on a canvas element, first create a WebGLSpins object:

var webglspins = WebGLSpins(<HTMLCanvasElement> canvas, <options> options?);
Options Type Default Description
verticalFieldOfView Number 45.0 Vertical field of view of camera.
allowCameraMovement Boolean true Enable/Disable moving the camera using the mouse and the shift and alt keys.
cameraLocation Array [0.0, 0.0, 1.0] Location of the camera.
centerLocation Array [0.0, 0.0, 0.0] Location fo the point the camera is looking at.
upVector Array [0.0, 1.0, 0.0] Direction that should be up.
backgroundColor Array [0.0, 0.0, 0.0] Color of the background.
colormapImplementation String red (see below) GLSL code for mapping spin direction to a color.
renderers Array [Arrows] (see below) Array of renderers to use and (optionally) their viewports.
zRange Array [-1, 1] The range of visible z values. Spins with a direction z component outside this range will not be rendered.
boundingBox Array null The bounding box to be rendered around the spins, or null. The value should be in the form of [xmin, ymin, zmin, xmax, ymax, zmax]
boundingBoxColor Array [1, 1, 1] The color to be used for rendering the bounding box.

Arrow renderer options:

Options Type Default Description
coneHeight Number 0.6 Height of the spin cone/arrow tip.
coneRadius Number 0.25 Radius of the spin cone/arrow tip.
cylinderHeight Number 0.7 Height of the spin cylinder/arrow shaft.
cylinderRadius Number 0.125 Radius of the spin cylinder/arrow shaft.
levelOfDetail Number 20 Number of sides for the spin arrow mesh. Must be at least three.

Surface renderer options:

Options Type Default Description
surfaceIndices Array [] Array of indices for rendering a surface.

Sphere renderer options:

Options Type Default Description
innerSphereRadius Number 0.95 Radius of the gray sphere rendered inside the spin sphere. Use a radius of 0.0 to disable the sphere.
useFakePerspective Boolean false The spin sphere is rendered using an orthographic perspective. If you wish to make distant points smaller anyway, set this option to true.
pointSizeRange Array [1,1] Point size can vary due to position on the sphere and distance to the viewer (in case of the fake perspective). This sets the valid point size range.

To change these options later on, use:

webglspins.updateOptions(<options> options);

Use the following function to set the spin positions and directions:

webglspins.updateSpins(<Number> n, <Array> spinPositions, <Array> spinDirections);

If you use a cartesian grid, you can generate the surfaceIndices for the surface render mode using:

WebGLSpins.generateCartesianSurfaceIndices(<Number> nx, <Number> ny);


By default, spins are rendered as arrows using the full size of the canvas. However, WebGLSpins.js allows you to use multiple renderers, even at the same time. By setting the renderers option, you can specify an array of renders and (optionally) their viewports, e.g.:

  renderers: [
    [WebGLSpins.renderers.SPHERE, [0.0, 0.0, 0.2, 0.2]


Spins are rendered as arrows. This renderer is available as WebGLSpins.renderModes.ARROWS.


Spins are rendered as surface. To define the surface, WebGLSpins needs to know which points should be connected as triangles. To do this, set the surfaceIndices option to an array of indices into the spin position array. For example, if you only have three spins and want to render them as a triangle, use:

  surfaceIndices: [0, 1, 2]

This renderer is available as WebGLSpins.renderModes.SURFACE.


Spins are rendered as points on a sphere, with their position on the sphere defined by the spin direction. Camera zoom and translation are disabled in this renderer. This renderer is available as WebGLSpins.renderModes.SPHERE.

Coordinate System

Spins are not rendered. Instead, a coordinate system is rendered as lines, using the current colormap to color the axes. Camera zoom and translation are disabled in this renderer. This renderer is available as WebGLSpins.renderModes.COORDINATESYSTEM.

Colormap implementations

There are three colormaps already available, basically as templates for your own: red, redblue and hue. These can be accessed as attributes of WebGLSpins.colormapImplementations.

Colormap 'red'

vec3 colormap(vec3 direction) {
  return vec3(1.0, 0.0, 0.0);

Colormap 'redblue'

A transition from red for positive z to blue for negative z direction.

vec3 colormap(vec3 direction) {
  vec3 color_down = vec3(0.0, 0.0, 1.0);
  vec3 color_up = vec3(1.0, 0.0, 0.0);
  return mix(color_down, color_up, direction.z*0.5+0.5);

Colormap 'hue'

The angle between z and y is mapped to a hue value between 0 and 1, with a positive z direction resulting in red.

float atan2(float y, float x) {
  return x == 0.0 ? sign(y)*3.14159/2.0 : atan(y, x);
vec3 hsv2rgb(vec3 c) {
  vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
  vec3 p = abs(fract( + * 6.0 - K.www);
  return c.z * mix(, clamp(p -, 0.0, 1.0), c.y);
vec3 colormap(vec3 direction) {
  vec2 xy = normalize(direction.yz);
  float hue = atan2(xy.x, xy.y) / 3.14159 / 2.0;
  return hsv2rgb(vec3(hue, 1.0, 1.0));