Commit 24a10882 authored by Tobias Rautenkranz's avatar Tobias Rautenkranz


parent e44cf049
layout: post
title: Glitzer.js
lang: en
category: code
tags: code
date: 2019-10-01 19:39 +0200
[![abstract]({{ "/img/glitter/glitter_abstract.svg" | relative_url }})](/glitzer)
Glitter sparkles are simulated with JavaScript for the 2D screen surface of a mobile phone.
The rotation of the phone causes the individual glints to appear and disappear;
as would be the case for an actual glittery surface.
## Physical Glitter
Some physics considerations is required to convincingly simulate glitter:
> Snow sparkle is harder than you think […]
> Decent solution: Use 3D position to index 3D noise
> function, add the view vector, use frac function to
> further randomize things
When there are fewer particles than in the previously considered snow example,
a more detailed treatment is advantageous:
> To understand the behavior of glitter patterns, consider a surface
> sprinkled with flakes and illuminated by an area source. Each flake
> has a position and a normal, and some reflect the light to produce
> glints. This happens when a flake’s position is inside the pixel’s
> footprint on the surface and its normal vector is halfway between
> the view direction and the direction to some point on the light.
> […]
> For example, on an ornament covered in craft
> glitter, there are relatively few flakes with normals broadly distributed,
> so if the light source is small the average number of glints
> per pixel is much less than 1, leading to occasional, widely separated glints.
Thus, the flakes can be treated as tiny mirrors reflecting a light source when
they are in the right aliment.
## Implementation
The implementation uses JavaScript and the
[DeviceOrientation Event](
to draw to a _canvas_ element.
<video src="/img/glitter/glitter_demo.webm" loop=true autoplay=true></video> [**Demo**](/glitzer)
For the given task of the 2D surface only its orientation is considered and
the light source and view position is assumed to be fixed. Thus, only the
orientation sensors of the phone have to be used.
A distribution of flakes for the rotational angles of the phone can be
reproducibly generated by a noise function.
This angle is used to look up the flakes with an angle near it. The
angle is taken to mean that the direction the perfectly reflected light would
take. Thus, the specular reflection for the chosen flakes is calculated. Then
the flakes are draw on the screen using the calculated opacity.
The position used for the calculation is slightly varied over
time to animate the glitter for stationary situation or when no device
orientation can be obtained. The biggest remaining issue for a convincing
simulation is, that the eye position is not considered; so moving only ones head
does not lead to glints. Also, narrow reflection angles respectively close
flakes the two eyes would see different glints for real glitter.
## Source Code
The source code is available form GitLab:
## References
1. <a name="1"></a> Jeremy Shopf
[Gettin’ Procedural](
3D Application Research Group
2. <a name="2"></a>Wenzel Jakob, Miloš Hašan, Ling-Qi Yan, Jason Lawrence, Ravi Ramamoorthi, and Steve Marschner. 2014.
[Discrete Stochastic Microfacet Models](
In ACM Transactions on Graphics (Proceedings of SIGGRAPH) 33(4). 115:1–115:10.
<script type="module">
// import Glitter from '/assets/modules/glitter.js';
import Glitter from '/glitzer/modules/glitter.js';
let canvas = document.createElement('canvas');
let imgE = Array.from(document.getElementsByTagName("img")).filter(e => e.alt === "abstract")[0];
let img = new Image();
img.src = imgE.src;
var glitter = new Glitter(canvas, img);
let style = window.getComputedStyle(imgE);
Array.from(style).forEach(key =>, style.getPropertyValue(key), style.getPropertyPriority(key)))
imgE.parentElement.replaceChild(canvas, imgE);;
// allow sparkle on mousemove for development/debugging on a desktop
window.addEventListener('mousemove', (e) => {
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment