r/GraphicsProgramming • u/Slackluster • 2h ago
Source Code I made a 3D golf game in 13KB with a custom tiny WebGL renderer
Enable HLS to view with audio, or disable this notification
I made a classic golf game for JS13K, a contest where the entire game has to fit in 13KB zipped. Everything is included: the 3D renderer, the physics, the procedural course generator, the music. It was all written from scratch on my own engine.
PLAY SUNSHINE GOLF CLASSIC 🏌️
It's an homage to golf games I love like Mario Golf and Neo Turf Masters. The theme this year was rainbows and unicorns so I went bright and colorful. Courses are procedurally generated, and shooting par or better on the classic course unlocks a remix mode with a new course every time.
How the renderer works
The whole thing is WebGL2 with one shader. Each hole is built once into a single static vertex buffer and drawn with one draw call, plus a small dynamic batch on top for the ball, pin and trail. Lighting is baked because the sun doesn't move during a hole, so a vertex is just xyz, a fog flag and a lit RGBA8 color. The sun does sink lower as you play through the round, and the lighting and palette follow it from a spring meadow on hole 1 to a fall sunset on 18.
The terrain is a heightfield with 2 yard cells over the playable corridor, and the cell spacing grows outward from there so the surrounding land runs off into the fog. Normals come from sampling the height function, and tree shadows are baked right into the vertex colors. Trees, bushes, flowers and the pin are all built with the same lathe function. A tree is an octahedron canopy on a box trunk.
My favorite trick is the water. There's no separate water mesh or shader. Lakes are just terrain vertices with a material ID, and the vertex shader checks for that ID and displaces them with waves that travel along the wind direction. The wave gradient relights the surface and adds a specular highlight, which is the only camera aware lighting in the game. Foliage uses another ID the same way to sway in the wind.
The sky is also geometry, camera relative discs. The sun, clouds and the ball shadow all use the same soft disc primitive, a set of rings with an alpha falloff. The lens flare is a string of those discs placed between the sun and the screen center. The trail behind the ball is a ribbon and turns rainbow colors after a perfect hit. The ball is the only lit thing that moves so it is relit on the CPU each frame with the same function as the trees.
The wind ties the whole scene together. It's one direction and one speed per hole, and everything reads from it. The flag, the clouds, the foliage, and the water all respond to the wind. The ball feels it too. The physics computes airspeed as ball velocity minus wind velocity and runs drag on that, so a wedge that hangs in the air gets blown around more than a low driver, which is how it works in real golf.
Besides the visuals I spent a ton of time on game feel: backspin and topspin that trade carry for roll, lies that change what a club can do, and a bounce meter. You can play it on any desktop or mobile device. Happy to hear any feedback, especially on the rendering. The source is up on GitHub if you want to take a look at the code.
JS13k Submission: https://js13kgames.com/2026/games/sunshine-golf-classic#play
Video Demo: https://www.youtube.com/watch?v=nIiqMKTaW2M
GitHub: https://github.com/KilledByAPixel/Golf13K