Pixel Perfecting the DOM: Rendering in Memento Mori
Having massaged Twine into doing a number of things outside its typical function, building a rudimentary visual novel engine felt like a reasonable and entertaining pursuit within the scope of a few-days project. This challenge was compounded by team member Nao's request that the game be rendered in pixel art.
Integer scaling a bitmap is a naive approximation of viewing a genuine low resolution display. Like most contemporary approaches to rendering pixel art this one misses a lot of the finer nuance of low resolution graphics, more appropriately measured as a point cloud of colour than a grid of squares.
Still, that emulator-crisp quality that renders individual pixel blocks scrutable while the art itself aims to visually ease jagged edges is, we think, an appreciable look. It has helped quiet my personal inner design-snob to acknowledge that a lot of popular contemporary pixel art, while not technically well executed in a historical sense, still manages to communicate an appreciable consistency in uniquely and pleasingly rendering light and geometry.
On the contemporary web, the aging "pixel" measurement no longer necessarily maps to hardware display pixels. Wresting control back from normalized browser vendor behaviour to attempt a responsive, scalable, pixel-correct rendering style takes a bit of work against that grain. For Memento Mori, the effect is achieved using a combination of hacks and workarounds, some old, some new.
After a time experimenting with pixel fonts on different browser engines on numerous platforms, it became clear that sharp, upscaled, non-aliased font rendering could not be reliably or consistently executed.
Historically this has been a tricky set of problems, with patchy inconsistent solutions. Rendering upscaled pixel art (images alone) has seen a number of temporary solutions come and go. As for text, there appears to never have been an established solution. Developer of Papers Please, Lucas Pope, touches on this briefly in his lengthy documentation of a proprietary localization tool; relying on an image quantizing post-process to eliminate unwanted colour produced by sub-pixel antialiasing.
Happily, in early 2015, the "image-rendering" property was implemented in Chrome, making it an established reliable, normalized property for dictating pixel-correct nearest neighbour scaling across common browsers. This solution is not immediately comprehensive though, as the image rendering property is not intended to account for vector-based text rendering; text rendering in most browsers is highly specialized and platform-specific.
Enter Simo Kinnunen's Cufon (heir to Shaun Inman's SIFR), a once-popular library for rendering text to images. Specifically, Cufon renders individual words using canvas elements, so as to otherwise preserve normal layout flow. Originally designed to bridge the gap during early rocky support for consistent web font rendering, Cufon is largely outdated and impractical for contemporary implementation. However, despite the library's shortcomings in a contemporary context, having words rasterized on canvas means the image rendering property applies, thus allowing text and images alike to receive proper pixel-correct upscaling. Bitmap font data for use with Cufon can be generated using Shaun Inman's Pxfon. See for example, the promotional website for Christine Love's Digital: A Love Story.
(Zooming in on the above image will reveal the disparity between the muddied sub-pixel blending seen in default browser text rendering and the crisp, grid snapped per-pixel accuracy of Pxfon combined with the pixelated image rendering CSS property)
Combining Cufon with CSS pixelated image rendering and viewport media queries, responsive, pixel-perfect upscaling is achievable. This technique not only works for layouts with fixed dimensions, but will also function with responsive designs that can accommodate a variety of display and input densities.
There are several wrinkles here; when the browser moves an element into a hardware-accelerated texture layer, pixelated image rendering is no longer properly applied. This necessitates older and less performative absolute-positioning style techniques for spatial animation, instead of the preferred contemporary method of translating DOM elements. Exactly which properties move elements into hardware accelerated textures appears relative to browser vendor: element opacity does so on MacOS Safari for example, but not on other platforms.
As with most art built under constraint, Memento Mori lost some features and content along the way, in order to meet the TOJam deadline. Our initial intention was for the game viewport to be truly display-independent; to leverage responsive layout design to allow for art to be a borderless "full-bleed" rather than letter and/or pillarboxed, regardless of device orientation, aspect ratio, or pixel density. As of the current date, the game has a little width-responsivity for small screens, and upscales in integers (200%, 300%, etc.) as the viewport size permits.
Combining pixelated image rendering and responsive design within the DOM offers potential affordances for adaptive game layouts; a largely-unexplored territory for pixel art games, which usually fall back on simply upscaling a game canvas of fixed dimensions. We intend to continue exploring these possibilities, and hope others will as well.