tutorials

Fireworks with Shader Code


Fireworks with Shaders

As with any code it is important to have a firm idea of what you want to achieve, what is possible to code and a design.

Requirements

The requirements are for a collection of coloured facets to burts out from a central position so that each fragment lies on the surface of an expanding sphere. All fragments should be equally spaced on the sphere and should change colour during the expansion, fading over time.

First Stage Design

A sphere created in BabylonJS is made up of facets where vertices of adjoining facets share normals to ensure a smooth surface. Converting the sphere to a flat shaded mesh will give each facet its own set of normals which will be the mathematical normals for the plane of the facet. To make a facet travel outwards from the centre over time its position at any time will be start position + normal * function of time

The sphere is flat shaded and the normals for the three vertices of each facet will be the same. The original position of each vertex and its normal are accessible to the shader as attributes passing time as a uniform will be enough.

To obtain an initially fast expansion the slowing down a logarithmic function of time will be used.

Second Stage Design

The colour and transparency of all the facets will be the same at the same time and so a change to each component of the colour of a vertex can be applied as a function of time.

Third Stage Design

After the first coding of the shaders adjustments were made to the functions of time, manually, to obtaim a satisfactory appearance to the burst of facets.

Shader Material Code

Vertex Shader Main Function

void main(void) {
    vec3 p = position;
    vec3 j = vec3(0., -1.0, 0.);
    p = p + normal * log2(1. + time) * 25.0;
    gl_Position = worldViewProjection * vec4(p, 1.0);
}

Fragment Shader Main Function

void main(void) {
    gl_FragColor = vec4(1. - log2(1. + time)/100., 1. * log2(1. + time), 0., 1. - log2(1. + time/2.)/log2(1. + 3.95));
}

Sphere

var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:10}, scene);
sphere.convertToFlatShadedMesh();    

sphere.material = shaderMaterial;

Animation Loop

var t = 0.;
var time = 0.;
scene.registerBeforeRender(function() {
    if(time<8) {
        sphere.material.setFloat("time", time);
        time +=0.1;
    }   
    else {
        sphere.dispose();
    }
});

Fireworks

Guide Example - Shader Material
Playground Example - Shader Material -