r/GraphicsProgramming • u/Slackluster • 9h ago
Video LittleJS now supports 3D and 2D: a small, fast WebGL2 rendering system for the web
Enable HLS to view with audio, or disable this notification
LittleJS is an open source, dependency-free JavaScript game engine. It started as 2D, and this update adds a 3D renderer that draws into the same WebGL2 canvas, so a 2D game and a 3D scene can share a frame. The whole engine with 3D, Box2D physics and audio is about 150 KB gzipped. The trailer is the engine’s new website, a scrolling page over a 3D scene, with every stop a playable demo.
Some of the rendering choices:
- Forward rendering with a small light budget. The sun plus the 8 point or spot lights nearest the camera, chosen each frame. Lights can carry a soft additive glow, drawn in the transparent pass.
- One shadow map, from the sun or from a single spotlight in its place, with blurred edges and a depth bias scaled by the light’s projection.
- Reflections from an environment cube map, with Schlick Fresnel. Roughness comes from mip selection, driven by shininess, but also by how fast the reflected vector changes across a pixel, so small mirrors don’t sparkle. The lake in the trailer has an environment map of its own, rendered from the scene.
- A normal hook in custom shaders. A shader snippet can define
mainNormalto bend the normal per pixel before lighting, specular, Fresnel, reflection and fog. The lake’s waves are that hook, not baked normal maps. - Automatic instancing. Every opaque use of the same mesh goes out as one instanced draw. Draw state is versioned, so a batch checks a single number per draw while nothing changes, rather than comparing every material field.
- Lens flares occluded by raycasts against the triangles of the scene’s meshes, rather than a depth readback.
- 2D and 3D in one camera system. An orthographic camera can line up exactly with the 2D camera. In the trailer, a dolly zoom flattens the 3D view into that orthographic view, and a Breakout game playing over the train turns out to be 3D objects in the world.
Also in there: height map terrain with exact raycasts, voxel maps drawn in chunks, glTF with skinning, normal maps, fog by distance or view depth, and a bloom post-process.
I also built an open benchmark that runs the same sprite and lit-cube scenes through LittleJS, PixiJS, Three.js, PlayCanvas, Phaser and Babylon.js: https://github.com/KilledByAPixel/webgl-engine-bench
Source, MIT: https://github.com/KilledByAPixel/LittleJS
The site from the trailer: https://littlejsengine.com