August 9, 2013
Graphics 7-8: gods in motion
Long time no ABC, Pöysti mah man.
What you see above is a sneak peek from the latest work of the Great Sitting Artist, samuncle. He's been getting intimate with the new lighting system, and it shows - can you see how much it blushes? It's adorable really.
Back to our regular scheduled program. The topics for the biweek were motion blur and god rays. Bugs were found, and according to the great principles of persistence hunting (a method used by no other animal than humans), were ran after until they collapsed to death from mere exhaustion.
While that certainly takes the fun out of seeing the bugs writhe in pain, at times you simply can't outrun them and need other measures.
The existing motion blur was a radial blur with protection for a certain area of the screen. It looked good enough, but was a bit slow, and the protection area was static.
Given the task here is eye candy, physical correctness be damned; one had to see how it would act when optimized and tweaked first. Before and after, with the protected area visualized in rogue red:
As you can see, the static area didn't cover the kart when speeding, resulting in blur being applied to it when it shouldn't have.
With that fixed, some optimization improved the motion blur's speed by 33%, and as it still looked good, that was that.
God rays, light shafts, or a strange sky hybrid of SSAO and radial blur, are this thing you see when your room has not seen a vacuum cleaner in a month and somebody opens the curtains.
Implemented according to the letter and spirit of the long-dead guru GPU Gems 3, may she rest in peace, we draw the sky and sun to a texture, trace the path to the sun, and sample along that path.
Hijacking on the occlusion query for the lens flare, we can determine the visibility of both effects with one stroke, as both are only visible when the sun is.
This section will be a bit more technical than usual; please bear with us.
Shadow maps, invented by Sir Williams the Fourth in 1887 or thereabouts, are a method not used by ancient Romans to fake shadows in a two-dimensional quantum display, otherwise known as a picture.
The problem of shadows, unlike that of light, is still unsolved, to the dismay of many. There is no known method to have beautiful shadows that scales well. Therefore we limit ourselves to only casting shadows from the sun; as a directional light, it's merely one render pass more, compared to six for a normal point light.
The above picture is an implementation of a basic shadow map. Far from a next gen darkness system, it produces 50 shades of Minecraft, as one can't simply get enough resolution for the whole visible camera range.
Clearly this is not adequate for us; for we are neither Minecraft nor fans of Twilight fanfiction. As it happens, the current state of the art in shades is rectilinear shadow mapping, made public a year ago by Paul Rosen.
Unlike some other publications of the same era, this technique can be fully implemented in GL 2.1+, without requiring any kind of GPGPU or even float textures, and it also runs faster than the previous state of the art solution, cascading shadow maps.
Rest assured no animals were harmed in the production of this picture; the lines are completely fake leather. What we have here is a packed depth image from above the Jungle level. The area highlighted in white is the back-projection of every visible pixel to this camera, allowing us to find a much smaller area to focus the shadow map on.
The importance map in closer view. In Rosen's algorithm, we determine an importance value for each pixel; in this image, every visible pixel is given an importance of 1, and invisible pixels 0.
What you see on the borders are visualizations of the two 1-dimensional importance maps generated from this image. For each horizontal and vertical line, we take the maximum value to the corresponding 1D importance map. This is done via a per-pixel loop in a fragment shader.
For each importance map, we then generate a warp map of the same dimensions. Red means shift this pixel back, black means stay put, and green is shift this pixel forward.
It's these two 1D warp maps that make the core of this technique. No shadow map area is wasted on pixels not visible (with the exception of those in the same row/column), and the important pixels are bigger than the less important ones. This means that the core area of a shadow might have less resolution than the shadow edges, giving the illusion of a much higher resolution shadow map.
For the exact format, it is a normal RG8 texture, and you can easily use RGBA8 instead with two bytes wasted. The negative range, -1 to 0, is stored in the red channel, and the corresponding positive range in the green channel.
This gives us 16 bits of precision for the warp map, which ought to be plenty.
Here's a warped image of the same Jungle level. As this image only uses the visibility importance, it is not that warped yet; only invisible pixels are removed from the shadow map.
Applying other forms of importance, we can decide that shadow edges need more resolution, or that pixels close to the viewer need more. This is a quite powerful technique using little power or VRAM; 1x512 RGBA textures take 2kb each.
This implementation is not yet complete, there are some remaining artifacts, and optimization & tuning has yet to be done. So expect more shadow work in the coming weeks.
Finishing this investigative report, we have a picture of an old classic game Slicks'n'slide. It's a top-down racing game with weapons, a favorite of mine.