title: Shape Sheet Images!
thumbnail-image-url: http://picture-files.nuke24.net/uri-res/raw/urn:bitprint:B7ROKQOJ2LHBP54VVUGJULXNDCU7SZBX.QLLSXO42WRKIKUDRVJMOVUB2EBLO2UR3GOLO7XA/curly.png
date: 2016-04-09

Shape Sheet Images! - 2016-04-09 - Entry 7 - TOGoS's Project Log

I've always wanted to be able to store generic 'shapes' and re-render them with different materials and different lighting conditions rather than have to decide on those things up front when hand-crafting graphics for a game. None of my games so far have got to the point where graphics really matter all that much, but nonetheless the lack of such a system has bothered me to the point that I decided I needed to finally write it.

If my JavaScript runs in your browser, this box should soon be filled with some randomly generated shapes:

Reload the page to generate new ones.

This system is based around objects called ShapeSheets, which are defined by a width*height array of material indexes, and a width*height*4 array of cell corner depths (a number for the depth of each corner).

Material indexes are an integer 0-255. A mapping of material information is provided separately to the renderer so that a single shape can be rendered multiple different ways (a good example use case would be an object with indicator lights on it; you'll be able to re-use the same shape with the lights in different states or different colors). For now a material is only defined by a single diffuse color + opacity, but I intend to add support for multiple surface layers each with various other properties such as roughness and inherent brightness.

Shading is calculated by tracing from the surface towards each light and takes surface normal into account. Shadows fall off with distance so that only objects within a certain radius can shade each other. This can speed up shadow calculation for large objects, and is especially useful for incremental updates (think interactive shape editor).

This project's written in TypeScript, which is pretty nice. I use a drop-in replacement for RequireJS to load the compiled JavaScript.