http://mango-media.eu/media/pages/creative-coding/galaxy-simulator/e796876a55-1633080374/galaxy.jpeg
Mango Media - Galaxy Simulator

Galaxy Simulator

2021

Interactive particle simulation built with Three.js.

Three.js is a cross-browser JavaScript library + application programming interface (API) used to create + display animated 3D computer graphics in a web browser using WebGL. This project was inspired by the course Three.js Journey by Bruno Simon a creative developer based in Paris.

Date

09/04/2021

Client

Nobody

Location

Messier 84 Galaxy

Service

Interaction, 3D, Creative Coding

Tools

Three.js + Javascript

Three.js is capable of creating wonderful particle simulations.

In this project, I have animated an intergalactic scene with shader materials. In this case, animating each vertex of the geometry isn’t an efficient solution for performance reasons. This is where the GPU comes in - by animating those vertices directly in the vertex shader to make the stars rotate at different speeds depending on the centre’s distance.

The Code


uniform float uTime;
uniform float uSize;

attribute vec3 aRandomness;
attribute float aScale;

varying vec3 vColor;

void main()
{
    /**
    * Position - using position and converting to vector 4
    */
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);

    // Spin
    float angle = atan(modelPosition.x, modelPosition.z); // Atan stands for arc-tangent providing x z axis and gives us the angle
    float distanceToCenter = length(modelPosition.xz); // Getting distance to make particles closer to the center spin faster simulating gravity
    float angleOffset = (1.0 / distanceToCenter) * uTime; // Calculate offset angle according to the time and disatnce how much the particle should spin
    angle += angleOffset;
    modelPosition.x = cos(angle) * distanceToCenter;
    modelPosition.z = sin(angle) * distanceToCenter;

    // Randomness
    modelPosition.xyz += aRandomness;
    
    vec4 viewPosition = viewMatrix * modelPosition;
    vec4 projectedPosition = projectionMatrix * viewPosition;
    gl_Position = projectedPosition;

    /**
    * Size
    */
    gl_PointSize = uSize * aScale; // Multiplying the size by a random value between 0-1 as it makes the particles appear more realistic.
    gl_PointSize *= (1.0 / - viewPosition.z); // Adding size attenuation to give perspective to make the pixles closest to the camera appear bigger

    /**
    * Colour
    */
    vColor = color;
}

varying vec3 vColor;

void main()
{
    // Disc
    //float strength = distance(gl_PointCoord, vec2(0.5)); // Creating a round shape out of the fragment by taking the distance from the centre and hiding anything above 0.5 using a UV filter
    //strength = step(0.5, strength);
    //strength = 1.0 - strength;

    // Difuse Point - fade around the edge with a linear defuse
    //float strength = distance(gl_PointCoord, vec2(0.5));
    //strength *= 2.0;
    //strength = 1.0 - strength; // Invert it

    // Light Point - Non-linear defuse of light creating a huge conentration of light which fades fast
    float strength = distance(gl_PointCoord, vec2(0.5));
    strength = 1.0 - strength; // Invert the value
    strength = pow(strength, 10.0);

    // Final colour
    vec3 color = mix(vec3(0.0), vColor, strength);

    gl_FragColor = vec4(color, 1.0);
}
See Project

Related Projects

Start creating an award
winning website today!

Anything is possible,
Let's make dreams a reality.

Get a Quote!