Here’s some more progress on the SeedWorld voxel engine. Last week has been mostly occupied with tweaking stuff- tweaking noise outputs, heightmap parameters, and color gradients. It’s been a ton of trial and error to get a landscape that I was happy with, but I think I needed a new perspective in order to not burn myself out on it.
I added some basic voxel shadow casting code. All it does is, for every X, Z coordinate on the surface, start from the topmost voxel and move down, checking if a voxel is solid or empty. The first solid voxel blocks sunlight and the rest of the voxels are darkened. It’s simple, but with some shadow smoothing the effect will look even better.
I know how to make a landscape that can alternate between long, mostly flat plains and rolling hills and mountain ranges. But the more I looked and moved around it, the more it looked the same. It looked boring. But then I remembered that the environment was far from complete. There are no trees, boulders or other clutter filling up the place. So I decided to start adding trees. The first step I took was making a function that can produce a voxel sphere. These were the leaves for the tree. Then I added a square pillar for the stump.
Now at least I’m getting somewhere. Here are a bunch of spheres casting shadows on the ground.
Enjoy that green while it lasts, because I soon removed it. This helped me just look at the details of the landscape and not think of how repetitive it looks with everything being grass green. All the code for coloring voxels was hard-coded into the Chunk class, and this had to be moved sooner or later. Voxel color of natural features will probably be controlled by Biome classes or something similar.
So for now, everything is colored white with AO and directional lighting. Here are some screenshots of Grayscale Land.
The only condition for the tree-generation code is that they are to be placed where the elevation is lower than 80. But trees don’t naturally occur in such an orderly fashion, so it’s time to mix it up. My tree generation code consists of finding a surface voxel to “plant” it, and then use some loops to place cubes near the bottom for the trunk. For the leaves, a function to determine whether a location is inside a sphere is used. Leaf cubes are placed anywhere it’s in the sphere.
The placement now needs to be randomized. Each chunk can be identified by its location in the world, and I can use a pseudo-random number generator that will have a different seed for each chunk. Here is how I determined the seed:
chunkSeed = ((chunkOffsetX << 16) + chunkOffsetY) ^ worldSeed;
The chunk’s 2D location creates a 32 bit int that then is XOR’ed with the seed that is used everywhere for generating the surface of the world. You might notice that if you walk 65536 blocks in one direction (maybe if you’re a voxel granddad) the same seeds will be produced again. I don’t think it’s an issue for now, as that’s a very far distance to travel and repeated object placement will likely go unnoticed if you are moving around the world for that long. The world seed will still have an influence on this item placement later on, so things may not even be 100% the same then.
Random values are used for almost everything in tree generation, from its location in the chunk, trunk height and foliage dimensions. Spheres can now be ellipsoids and I can probably add several of them in one tree to make their forms look more varied and natural.
There will be cases where parts of the tree will intersect other chunks, so other chunks need that tree information. What did I do here? On every chunk, I actually compute the random values for all 8 chunks surrounding it, and then piece together that information by attempting to render parts of the trees on each chunk.
That sounds terribly inefficient on paper, and it probably is, but the chunks are still made as fast as ever. The tree generation code is still fairly simplistic compared to computing 3D simplex noise, plus I do not have to loop through every single voxel to see if something needs to go there (I’d have to check for out of bounds voxels anyways, otherwise the program will crash for trying to access an array element that isn’t there).
So here are the results of how that looks:
(Not Bad image macro goes here)
Keep in mind this is with just one tree randomly placed in each chunk, where elevation is below 80. I first thought I needed 3 or 4 trees per chunk to look decent, but I plan on making the trees bigger anyways. A dense jungle might get away with 2 per chunk, though.
Next, I’ll refine the tree generation to make more interesting shapes for the trunk and leaves, and then work on varying the colors with the trees and terrain!