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.
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.
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.
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.
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.
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.
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.
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.
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.)
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.)
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.
Putting It All Together
So I think I have all the pieces I need, more or less.
More next week.
blog comments powered by Disqus