← back

Exploring 3D

April 2026

I've been experimenting with 3D design lately. No particular reason other than curiosity — I wanted to understand how light, geometry, and material interact in a rendered scene. It's a different kind of building. Less logic, more feel.

This is one of the first things I made: a heart-shaped gem with refraction, glow, and particle effects. You can rotate it. Try changing the color.

How it's made

The heart curve

The shape isn't drawn by hand — it's a parametric equation. You feed in an angle t from 0 to 2π and out come x/y coordinates that trace a heart. The key is that sin(t)³ produces the top lobes while layered cosine terms carve the bottom point.

const x = 16 * Math.pow(Math.sin(t), 3);
const y = 13 * Math.cos(t)
        - 5 * Math.cos(2 * t)
        - 2 * Math.cos(3 * t)
        -     Math.cos(4 * t);

200 points around the curve give a smooth outline. Three.js turns that into a Shape, and ExtrudeGeometry pushes it into the third dimension with beveled edges — that's what gives the gem its faceted look.

Faking gemstone light

Real gemstones refract light internally, which is expensive to simulate. Three.js has a MeshPhysicalMaterial that fakes it convincingly with a few properties: transmission makes the material see-through, ior (index of refraction) set to 2.42 mimics diamond, and thickness controls how deep light travels before bending.

const gemMat = new THREE.MeshPhysicalMaterial({
  transmission: 0.92,   // almost fully transparent
  ior:          2.42,   // diamond-like refraction
  thickness:    1.2,    // depth of internal refraction
  roughness:    0.0,    // perfectly smooth surface
  reflectivity: 1.0,    // maximum reflections
});

The glow around the gem is a separate mesh scaled slightly larger with additive blending — light adds up instead of replacing, so it blooms naturally against the dark background.

Sine waves everywhere

Almost everything that moves uses Math.sin() with elapsed time. Sine waves are smooth and periodic, which makes them perfect for organic-feeling motion. The heartbeat pulse, the glow breathing, the halo pulsing, the spark twinkle — each is just a sine wave at a different frequency and amplitude.

// heartbeat: subtle 4% scale oscillation
const pulse = 1 + 0.04 * Math.sin(t * 2.5);

// glow breathing: slower, larger range
const breathe = 1.08 + 0.06 * Math.sin(t * 1.8);

// halo pulse: big and slow
const h1 = 4.0 + 0.8 * Math.sin(t * 1.2);

Layering sine waves at different speeds creates the illusion of complexity from very simple math. The floating orbs use sine and cosine together for circular paths, with randomized phases so they don't all move in sync.

Particles on a sphere

The sparkles are 120 points scattered on a sphere using spherical coordinates — a random angle for longitude (theta), one for latitude (phi), and a radius. Converting to cartesian gives x/y/z positions that wrap evenly around the gem.

const theta = Math.random() * Math.PI * 2;
const phi   = Math.random() * Math.PI;
const r     = 0.5 + Math.random() * 1.2;

x = r * Math.sin(phi) * Math.cos(theta);
y = r * Math.sin(phi) * Math.sin(theta);
z = r * Math.cos(phi);

The whole particle system slowly rotates, and opacity fades in and out with — you guessed it — another sine wave.

There's something satisfying about making a thing that just exists to look interesting. No product, no pitch. Just shape and light. I'll keep going.