Home       About Me       Contact       Downloads       Part 66    Part 68   

Part 67: Scenery I Can Live With

October 4, 2012

Back in Part 64, I had implemented a modified heightmap for the distant scenery. For x and z, I was using the cell dimensions, which increase in powers of two in the distance. But for the y dimension, I was using the exact maximum height in the cell, not a power of two. The result looked like Figure 1.

Fig 1: Modified heightmap scenery

As you can see, the distant blocks are still huge, and they are a single color. It was still better than using power of two heights for everything though. In particular, there is no abrupt height change when it switches to the next larger cell.

Fig 2: A bounding box
I wasn't happy with this though, because I wanted to represent three-dimensional scenery, like giant caves or floating islands. I also wanted to show modifications to the landscape more clearly and I was worried that this sampling would ruin even fairly close structures.

In the last part, I did a Minecraft landscape out to 2km and used power of two blocks to represent it in the distance. It didn't look as bad as I had feared. I was going to implement the heightmap approach over that scenery, but then it occurred to me that I could use a bounding box in three dimensions.

When I'm reducing the resolution in the distance, the important thing is that I convert an N by N by N cell into a single box. It doesn't have to be a cube. It just has to have fewer vertexes, making it quicker to draw. So I can just take a bounding box in three dimensions. Figure 2 shows it in two dimensions.

I implemented a hacked version of this in my sample Minecraft scenery. I'm just adding more cubes to fill out the bounding box, not drawing this with fewer vertexes.

At 2 by 2 by 2 sampling, you'll get an effect like Figures 3 and 4. This is very similar to the power of two sampling, since there's not much difference between a 1x2x1 bounding box and the full 2x2x2 cell. But you can still see a few places where vertical 1 by 1 columns are preserved.

Fig 3: Original data
Fig 4: bounding boxes within 2x2x2 grid

When we get out to 4 by 4 by 4 cells, the sampling is more pronounced, but again you can see places where details are preserved. This is also much better than a simple height map, which would kill all the vertical detail. By the way, I'm rendering these landscapes with transparent turned solid, and non-cube shapes turned into white cubes. I haven't decided what to do about those cases yet.

Fig 5: Original data
Fig 6: bounding boxes within 4x4x4 grid

These shots are done with cubes, but in the real system, I'll be drawing quads with a texture pattern derived from the missing cubes. If I texture each face with the projection of the removed cubes, I should be able to preserve a lot of detail. Figures 7 and 8 show a bit of 4x4x4 grid, and the projection preserves the lettering. If I extend this to the highest scale, you'll see a map of a distant city projected into the landscape. I haven't implemented this yet, but I'm cautiously optimistic.

Fig 7: Original data
Fig 8: projected textures within 4x4x4 grid

Finally, when we get out to 8x8x8 cells, the sampling is very coarse, but a surprising amount of the shape is preserved. On the airplane wing, we are still getting a tapering because the bounding boxes are tight around the wing. There are still small patches of ice on the water because the texture is capturing this.

Fig 9: Original data
Fig 10: bounding boxes within 8x8x8 grid

The large white patch on the wall below the plane is a problem. It's hard to see on the left, but the two black decks have open space between them. When I'm trying to build a wall around this bounding box, I have nothing to put in those cells (the texture would have to be empty there). I use the first cell seen as the default, which in this case is snow.

Fig 11: 2048 by 128 patch, side by side

Figure 11 shows the full test patch done with this technique. Go here for the full resolution version (800k).

I'm pretty encouraged by this, and I'm hoping I can get the full Crafty to use this style with reasonable performance.

Quads not Bricks

This week I also went ahead and implemented the code to render my 32x32x32 chunks with quads instead of individual faces. My test case was 1,476,321 cube faces (the same strip of Minecraft data I've been using). Converted to quads without regard to color, it was 379,104 quads. To get that to work, I need the tile mapping shader I mentioned last time.

Surprisingly, if I draw quads only where all faces have the same pattern, it's still only 446,444 quads. I changed the code to draw with quads and that 70% drop in the number of vertexes caused a 60% drop in my draw time. So this is definitely worth doing. I still need to decide how quad rendering interacts with lighting however.

Extracting Buildings

I also wanted to take my sample Minecraft world and extract all the buildings. Then I could place them randomly around new landscapes and see how buildings looked in the distance, up the side of a mountain, etc.

If I had the algorithm for generating Minecraft landscape, and the seed for this world, I guess I could just diff the default and actual landscapes to get the buildings. Without that information, I thought I could just subtract all the "natural" brick types out from the bottom up to get something like the built portion. Unfortunately, this doesn't work. Stone is the main component of the ground, and also a popular building material (Figure 12.)

Fig 12: Everything is stone!

I fooled around with this far too long, and then decided to take the list of "manufactured" brick types as the buildings (shown in blue below), and just add a buffer of a few blocks around all of those. That made me remember something about the TwentyMine world -- it's a regular anthill of tunnels and paths (Figure 13.)

Fig 13: It's all connected!

I finally did cut this up into buildings and save them away, but the results are very rough. I need to handle the region boundaries better, and the building boundaries could also use some work. In Figure 14, you can see that the gray ship in the background has connected to the shore (which has a small built area), and the large blue building has been wrecked (since so much of it is stone.)

This was one of those projects that seemed to be close to right for hours at a time, and I wasted too much time on it. Very annoying.

Fig 14: Buildings, sort of...

Putting It All Together

So I think I have all the pieces I need, more or less.

  • The nearby landscape is still individual bricks, but I can improve the draw time by using quads instead of individual faces. This also cuts display memory use for cubes by 70%.

  • I can use instancing to essentially eliminate all the display memory use for the non-cube shapes. This cuts total vertexes by at least 50% in my sample landscapes. There will be a cost in drawing time, but I'm not sure it's significant. On laptops with small display memories, the extra drawing time might be made up by not having to write large numbers of vertexes to the display.

  • The distant landscape is summarized with these bounding boxes instead of just sampling. I can keep a separate map of all these reduced resolution versions. I'm not sure how much disk that's going to take yet.

  • I can further improve the look with textures that show the summarized bricks. This is just a question of memory use since it will draw just as quickly as solid quads.

  • I'm not sure yet if I can keep the summarized versions of the landscape up to date in real time as changes are made. It's just a question of how often I update the summaries I suppose.

More next week.

Home       About Me       Contact       Downloads       Part 66    Part 68   

blog comments powered by Disqus