A Game of Tricks IV – Stylized normal mapping
alkemi-games.com
alkemi-games.com
Related: I really need to learn more graphics-oriented programming.
I sometimes am flabbergasted as I look out the window of my office and see the sunset. The skies flawlessly gradient from blue to red, the lighting of the clouds is perfect. Nature's artistry is effortless.
To reproduce that on a screen -- or even a close approximation of that view! -- takes an incredible amount of artistry and know-how. As a more technically-minded person, I'm amazed at how much thought and energy goes into things like this, and how little I know of it.
Very cool read.
Just as a couple examples: once we needed to show a which way enemies would move for a tower defense game so we made a custom skin that looked like arrows that moved along a path but was really just a mostly transparent image on a plane that was slowly being offset.
Another time we needed to make it look like you were in space, but to make that realistic you need thousands of individual stars - so we pre-rendered the six space images needed for the sides of a cube and just made the code that projects 3D images down to a 2D plane (ie your screen) always put it behind everything else, even if it was technically on a 1x1 box around the camera.
These days, sadly, I do 2D which means fewer tricks.
When shading a 3d-rendered surface, the normals at each pixel are used to determine how bright the light on the surface is at that pixel. (If the light is shining directly at the surface, i.e. along the normal, it's bright; if it's shining shallowly along the surface, i.e. at a sharp angle to the normal, it's dim.)
If you make, say, a cube, and set all the normals "realistically" -- that is, you make them poke straight out of the squares that make up the surface -- and then you render a light shining on it, it will look like a cube. Every face will have all its normals pointing the same way, so every pixel on a given face will be lit the same and render the same brightness.
Now, instead, try _blending_ (or "interpolating") the normals smoothly -- so the center of each face has a normal that pokes straight out, but as you get closer to the edge, it gets flatter, so by the time you reach a corner, the normals on both adjacent faces are pointing the same way, straight out of the corner.
If you can picture that, you should see that this will look a lot like the normals on a sphere, because you have a continuous gradient of outward vectors that smoothly covers every direction.
If you now light the cube, using the normals as discussed above, so that a head-on light is bright and a shallow light is dim, you'll see that the faces are no longer lit with a single constant brightness, but rather a gradient that simulates the surface of a sphere.
So you'll see an object that has a cube-shaped silhouette, but a surface that's lit like a smooth sphere.
This will look very strange, but as you raise the number of faces you use, to 20 or 100, you'll have an object that looks basically just like a sphere, except the outside edges are slightly angular if you look very closely.
(You can see an example of this object here: http://www.twodee.org/weblog/wp-content/uploads/2011/02/sphe... , taken from this article: http://www.twodee.org/weblog/?p=594)
This is the same sort of cheating that the linked article is about, but the linked article is cheating even harder -- instead of merely blending the normals between adjacent surfaces, they're actually reorienting the normals of one surface all the way "around the corner", to point in the same direction of the normals on the adjacent surface. This means that when you look directly at the corner between the two surfaces, it will look like one surface extends around the corner, which gives the illusion of a notch in the corner.