glass-shards · made with Three.js · GitHub

namespace SelectedWork;


get<LivingNPC>();

Agentic NPCs in a 3D scene with procedural lip sync, conversational gaze, skeletal animation, shadow mapping, and a day/night cycle, all on a custom Vulkan engine. Built with Raymond at Hack the North 2026.

open<LivingNPC>();
An NPC speaking to the player in the 3D scene

get<Rath>();

A game engine I am currently building in C++ with Vulkan. So far it covers the basics of the API: swapchain setup, render passes, graphics and compute pipelines, command buffer recording and synchronisation, and a free-fly camera for moving around the scene. Math comes from enginemath, my own library.

open<Rath>();

get<ShaderRenderer>();

A multi-pass deferred C++/OpenGL renderer with three non-photorealistic GLSL shaders: cel shading (inspired by Guilty Gear Xrd), crosshatch/screentone manga, and isophote contours. Features two-tone cel lighting, rim lighting, screen-space outlines from normal and depth buffers, and a ping-pong Gaussian bloom pipeline with HDR tone mapping.

open<ShaderRenderer>();

get<Holofragment>();

A lyric visualizer for Magical Mirai 2026, built with Eason Chou in TypeScript, three.js, and GLSL. I built the graphics and simulation, Eason set up the songs. As a song plays, 65,000 particles drift through the scene and gather into the lyrics on the beat, the glass sphere surrounds the lyrics and bends the light, and an aurora shifts above the water in the background.

open<Holofragment>();

get<PokemonNiosV>();

A Pokémon RPG in C on bare-metal DE1-SoC (no OS, no engine, no drivers) built with AnRi1202. The full game runs in a 36-state machine with Nintendo's actual damage, catch rate, and EXP formulas; all game data in compile-time lookup tables with no heap allocation; hardware driven by direct register writes; graphics writing RGB565 directly to a double-buffered VGA framebuffer at a deterministic 20 fps.

open<PokemonNiosV>();
Battle

get<GANTerrainGen>();

A DCGAN trained on real satellite data (Copernicus 30m elevation + ESA WorldCover land cover) to generate 256×256 terrain maps, benchmarked against a Perlin fBm baseline. I built a real-time C++/OpenGL viewer to inspect checkpoints live: early terrain was too spiky to walk on. Two training penalties (smoothness term + slope limit) were added to training, keeping terrain navigable for eventual RL agent deployment.

open<GANTerrainGen>();
GAN generated terrain side view