cd ../portfolio
Phase 2 // WebGL & Three.js

3DMatrixCards

A 3D card display system built with pure Three.js. Four layout modes -- Grid, Sphere, Helix, and Table -- with Matrix rain, drag-and-drop images, and billboarding. No frameworks. No build tools. 793 KB of WebGL.

Created Jul 17, 2025 Size 793 KB Lang HTML 99% Renderer Three.js WebGL

Project Overview

3dMatrixCards is a WebGL showcase that arranges image cards in 3D space. Users drag and drop their own images, then browse them in four spatial layouts. Cards billboard toward the camera, Matrix digital rain falls in the background, and the whole thing runs in a single HTML file with no build step. This was the first Three.js project -- proof that the browser could handle real 3D.

4
Layout Modes
793 KB
Total Size (with Three.js)
99%
HTML (all inline)
0
Build Tools Required

Technology

Three.js loaded via CDN. Everything else is inline HTML, CSS, and JavaScript. The entire app is one file.

HTML 99%
JS 1%
Three.js WebGL PerspectiveCamera TextureLoader Raycaster TWEEN.js Drag & Drop API FileReader

Spatial Layouts

Four distinct 3D arrangements with smooth TWEEN transitions between them.

Grid
Flat card grid in XY plane
Sphere
Cards on sphere surface
Helix
Spiral DNA strand
Table
Periodic-table layout

Key Features

🎨
Drag & Drop Images
Drop images onto the page to create 3D cards. Each image becomes a textured plane in the scene.
🌐
Matrix Rain
Falling green characters rendered in the 3D scene as a transparent particle system behind the cards.
👁
Billboarding
Cards always face the camera regardless of layout. Quaternion-based lookAt on every frame.
📱
Mobile Optimized
Touch controls for orbit, pinch-to-zoom, and reduced particle counts on mobile devices.

Code Snapshot

The sphere layout calculation -- distributing cards evenly across a sphere surface using spherical coordinates.

index.html -- sphere layout
function createSphereLayout(cards, radius) {
    const positions = [];
    const count = cards.length;

    for (let i = 0; i < count; i++) {
        // Fibonacci sphere distribution
        const phi = Math.acos(1 - 2 * (i + 0.5) / count);
        const theta = Math.PI * (1 + Math.sqrt(5)) * i;

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

        positions.push(new THREE.Vector3(x, y, z));
    }

    // Animate cards to new positions
    cards.forEach((card, i) => {
        new TWEEN.Tween(card.position)
            .to(positions[i], 1200)
            .easing(TWEEN.Easing.Exponential.InOut)
            .start();
    });
}

Development Timeline

Jul 17, 2025
Project Created -- First Three.js Scene
Scene, Camera, Renderer. The holy trinity. First card rendered in 3D space.
Day 2-3
Four Layout Modes
Grid, Sphere, Helix, Table. TWEEN transitions between layouts.
Day 4-5
Drag & Drop + Matrix Rain
Image upload via drag-and-drop. Matrix particle system in the background.
Day 6
Mobile + Billboarding
Touch controls, performance tuning, card-to-camera billboarding.

What This Project Taught

01

Three.js Without a Build Step is Possible

Everyone says you need Webpack or Vite for Three.js. You do not. A CDN script tag, an inline module, and you have a full 3D scene. The browser is the runtime. The file is the app. 793 KB, zero dependencies beyond the CDN.

02

Math is Not Optional in 3D

Fibonacci sphere distribution, spherical coordinates, quaternion rotations. The Godot engine hid this math behind nodes. Three.js puts it in your face. And understanding it makes everything else easier.

03

Transitions Make the Experience

Without TWEEN animations between layouts, the app would just "jump" between arrangements. The smooth 1.2-second eased transitions are what make it feel alive. Motion is information.

04

WebGL is Real Power

The browser's GPU is waiting to be used. Three.js abstracts WebGL enough to be productive, but the underlying power is immense. This project opened the door to shaders, FXBackgrounds, and everything GPU-accelerated that came after.