https://mango-media.eu/media/pages/creative-coding/galaxy-simulator/66d5ae8c72-1620580157/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.

09/04/2021

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);
}```
```