Next step is to distribute the tree we just created on to the terrain. I use the heightmap as the source. I create an array with objects representing all pixels. The reason for this is that I now can filter and sort these points. First, filter out all points in the defined range, based on the y-value and the range defined in the editor. Then, sorting out a specified amount of random points, sort them on the z-value for correct render order. Before this last sorting I can add all different objects to the same batch. I’m sure there are much better and faster methods than this. Analyzing the terrain for more realistic distribution should make it more interesting. When rendering, I have to make a render for each position and merge the result with the final image. It will not work to just paste the result on top of the terrain. The tree is sometimes behind the terrain and partly hidden. And if the terrain is included in each pass, next render will cover the previous. So after some experimenting with masks, pixel bender matte calculation, my solution was this:
- Render the object by itself in a transparent viewport.
- Add the terrain and set the material to a white color material and viewport background color to white. Move the object to a new position and render.
- Get the boundingbox of all none white pixels with getColorBoundsRect. This is the rectangle that we want to work with. Draw a new BitmapData with this rectangle from the viewport. Lets call it maskTree, the object with white surroundings.
- Crop the transparent pass with the same clipping-rectangle as maskTree. Lets call the result transparentTree.
- Add effects like fog and filters like blur to transparentTree.
- If the tree got covered by any terrain, the edges now has straight cuts because we just use a rectangle clipping. We have to fix that. Loop through all pixels in the maskTree . If its completely white in the mask, its a transparent pixel in the transparent image, so set that pixel transparent in transparentTree. Left is a masked image, but with correct multiplied alpha colors.
- Merge transparentTree with the final result. To do this a put the final canvas and the new object in sprites and cache them with draw() to a new final canvas
- Send an event so the user can follow the progress and start over with next iteration.
I tried to use a matte pixelbender-filter so that I just had to render the viewport once, but the alpha-channel in flash is pre-multiplied (correct me if I’m wrong here), so the edges became white when blending it with the final canvas. One downside is that it’s pretty slow. Another is the z-sorting issues that occurs. Maybe a down-sampled heightmap can be used instead when setting the position in 3d space.
Shadows and effects
Because the result of each tree is a single transparent bitmap, I can use different effects on each tree. A blur-filter based on the distance to the camera is added. A small random value on the hue/saturation make the trees more random. If fog is enabled a color tint is added. I didn’t find out how to change the color-transformation correctly , so I found a workaround by setting the tint with TweenMax and change the progress to 0-1 depending on the z-position and fog amount. Have to work more on this later on.
I mentioned the shadow-layers in one of the previous posts. To add every shadow to the final result, I make a temporary container and add a sprite with a radial gradient fill for every tree and cache that with bitmapData.draw(). This is then baked into the texture with the multiply blendmode.
Things to improve:
– There is plenty of optimization here to do here. This is the most time-consuming part.
– Check visibility against the clipping planes and skip those objects.
– Adjust all the effects with better z-depth-control.
– Let the position of the sun affect the brightness.
– More realistic distribution such as slope detection or algorithms.