Pixel Globe

p5jsmath

This scene has a lot in common with the previous Christmas scene. 3D points are rendered with p5js, individual points are managed with Point classes. Points have a lifecycle; they fade as they age, and then they disappear and float back down from the top. The entire scene rotates, which produces a cool effect.

The biggest challenge with this scene was getting the globe shape correct. Each point has a “home” y position that is determined with complicated math:

// Calculate the sagitta (arc height) or depth of a spherical segment/cap
this.y = Math.sqrt(sR*sR + (this.r * this.r)) - sR - aH;

This part of the project definitely took the longest, especially since I wrote this before the AI boom. Getting this line took a ton of trial and error, googling, and scratching out equations on bits of paper. The process was fun, and the result was worth it!

PSA: these graphics are very intense, even more than the tree. I messed around with a bit of shader code to get each pixel to glow:

precision highp float;
// x,y coordinates, given from the vertex shader
varying vec2 vTexCoord;

// the canvas contents, given from filter()
uniform sampler2D tex0;

const float blurSize = 1.0/1000.0;

void main() {
    // get the color at current pixel
    vec4 originalColor = texture2D(tex0, vTexCoord);
    vec4 texColor = vec4(0.0);
    texColor += texture2D(tex0, vec2(vTexCoord.x - blurSize, vTexCoord.y + blurSize)) * 0.15;
    texColor += texture2D(tex0, vTexCoord - blurSize) * 0.15;
    texColor += texture2D(tex0, vTexCoord + blurSize) * 0.15;
    texColor += texture2D(tex0, vec2(vTexCoord.x + blurSize, vTexCoord.y - blurSize)) * 0.15;
    texColor += texture2D(tex0, vTexCoord) * 0.16;
    texColor += originalColor;
    gl_FragColor = texColor;
}

Applying this shader turned out to be very expensive. Apologies if your page starts to stutter on older hardware.

That’s all for the pixel globe, see you next time!