In the previous post we got our mesh to work with. That has to be filled with colors, light, shadows and details to come to life with a texture. I’m using a few layers to create this and will explain them here.
First a “base” layer with a color ramp mapped to a clone of the height-map with paletteMap. The range 0-255 of possible colors is a little bit low, so a blur-filter is applied to smooth it out as a quick interpolation. I’m not really sure it helps though, have to check that.
While creating the example for the self-shadows below I rewrote it completely. And that trigged me to experimenting with a normalmap to get some volume and details to the texture. I found stok3d, a great library by David Lenaerts. I am so amazed of the people actually creating this stuff, and I salute him and the community for sharing their knowledge.
With the NormalMapUtil and the PhongNormalMapShader and 20 lines of code it was far simpler than I imagined to add a lightmap. (Or do I have to call it a bump-map?) It is powered by pixelbender, so it’s pretty fast, so this effect is applied even in edit-mode. To get the details I want, the size of the lightmap have to be huge. The solution to that was having different resolutions when editing and rendering, like with the self-shadows. And add a blur filter to smooth things out.
Here you can see how it works with a heightmap:
…and on the mesh. Select the shadow/light-tab, click and drag the sun around to see the sun affecting the light.
Lightmap on terrain demo
One more way of adding volume to the terrain is to add shadows. Regarding self-shadows I found some code written in C++ that is based on a method called “the strider technique“. It’s a simple type of directional light ray-tracing (or raymarcher ) that compare the height on the terrain with the height of a ray traveling across the height-map. If an intersection is detected along the ray you got a shadowed pixel. I’m sure there is way smarter and faster techniques than this though. This code was only using a light-source from 0,45 or 90 degrees. But I made a little trick to set the direction of the light. I think that it would be to slow to calculate the angle of the ray (with interpolation and stuff). So I just rotates the heightmap before the calculation is taking place, and rotate it back afterwards. One downside is that the bitmap that is calculated has to be larger for the rotated image to fit and therefor taking more time to calculate. My optimization-skills is just terrible, so if anyone want to try to make it faster, here is the source.
I really miss the GPU-support and multi-threading on this one. On large maps it’s pretty slow. Is there a way to achieve a similar effect with pixelbender? To keep the editing-mode up to speed I use different sizes of the map in edit and render-mode.
Gamedev.net have a great resource of documents and examples: http://www.gamedev.net/reference/list.asp?categoryid=188
Here is a couple of examples of this:
shadows on terrain demo
- Better and faster algorithm, pixel bender maybe?
- Soft-shadows. Slower, but more details.
A layer with a tiled BitmapMaterial is blended on top of the terrain in a second pass to get high resolution details. For first time a bitmap-asset is used. One idea is to select different type of bitmaps to get different characteristics. Or just use a regular noise-bitmap generated in flash. Will try that later.
The same asset is used once more in another layer, this time without tiling. This happens to add a kind of erosion to it. But I admit it’s wishful thinking, real erosion effects should be water-trails, wind, rain and such.
Texture details demo
All layers together
Lets see how it looks. Try to change colors, details, the amount of shadows and lightmap-blending. The high resolution texture is put on top of the grid in a separate viewportlayer, so that is only visible under the “Texture”-menu.
Texture combined demo
- Refactor the pipeline for blending textures. Better control over the blending between different layers.
- More features to modifying the height-map. Different noise types for example.
- Load elevation data and textures from Google earth or other API:s.
- Slope detection
- Splat textures, use a alpha mask to reveal different textures at different conditions (like slopes or another Perlin-noise bitmap as mask)