Jump to content
  • Advertisement
Sign in to follow this  
CodeZero

Terrain Texture Generation

This topic is 3966 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been pondering the last day or so on how to best generate the colormap for my terrains, represented by a height map, of course. This will be combined with a detail texture in the end, so I'm keeping my terrain engine relatively simple, but I'd like it to still look the best it can. Obviously when generating the colormap both height and slope need to be considered when assigning weights to certain colors ( In the end I'll pull weighted colors from a texture, but for simplicity I'm starting with just color ). I'd like the user to be able to set up rules which the generator will use to determine weights. The questions I have are: 1. Should I use a base color, then have rules that will 'override' the base whenever they apply or should there be rules that cover all possible values? 2. Should rules be defined by a range of height and slope values, or should they be a single point of height and slope? With either option, somehow blending from one color to the next needs to be addressed. 3. How do you determine the weight of a certain color, considering both height and slope? I have thought most of these through, but I was wondering what has been done already by other people. Has anyone seen any good articles or tutorials on this, or was it mostly trial and error? Anyone care to share exactly how they did it? Thanks, Jake

Share this post


Link to post
Share on other sites
Advertisement
None of your questions have definite answers. Whatever you decide works for your project is correct. Make a decision!

1) Having a rule that applies to all values (e.g. really high maximum height and angle, really low minimums) is equivalent to having a base colour AND having rules for all possible values. It can be useful to assign 'importance' values to each rule too, so the default rule (base colour equiv.) is ignored if a rule of higher importance also applies. In general you'd want the rules that are least likely to be applied to be the ones with the highest importance values, to make sure they appear whenever possible.

2) A range will be much more manageable and easy to use. Assuming you use an 'if' for each rule, for each pixel, having a rule for each possible combination of 2 real numbers would be madness. ;)

3) I assign a single colour (well, material... but it's signified by a greyscale value at this point in the process) to each heightmap pixel, then use the blending described in Bloom's splatting to get normalised weights for each material. This also sorts out the bending between materials you asked about in 2.

I end up with an RGBA weights texture, normalised to allow 5 weights per pixel - the final weight is (1.0 - R+G+B+A)

Bloom's description is pretty good, especially the distance based weighting. Any kernel based blur filter would probably work just as well with a bit of tweaking though.

Share this post


Link to post
Share on other sites
You should definitely go for ranges of values and blending, since it`s simple to implement and a detailed-enough heightmap shall therefore take care for itself and texture itself nicely just based on a set of rules.
Start simple - few ranges with static color per each range, then calculate the weight by calculating how far into range the current texel/vertex is, then blend between two neighbouring ranges to fix the artifact of sudden and obvious range start (though it may be desirable sometimes to have a not smooth range start). Finally add some random into the process and you`ll end up with something like this:

I`ve got just 3 base ranges there plus few inner sub-ranges (i.e. small range within base range). Yet, it produces interesting result, since the heightmap data is pretty wild. You`ll spend 1 day max with coding this (after all, the resulting function is about 1-2 pages long), but you can easily spend a week tweaking it to get some usable results. So, if you have some time to burn, this is the way to go.
The beauty of this method is that it runs on ancient HW like GF2 with only 2 texture units (base colormap + detail texture) in a single pass.

Share this post


Link to post
Share on other sites
Thanks for the replies guys. I think I've worked out a good system that works and makes sense.

VladR - I like the look of your terrain. It looks like you are using a blend of a couple different textures as the detail texture. Could you explain how you did this on a GF2 in one pass? I'm currently working with older cards right now to get the most compatibility possible.

Share this post


Link to post
Share on other sites
Just put your materials into corners of the texture and use the alpha per vertex texture stage operation (BLENDDIFFUSEALPHA). To avoid seams between two neighbouring submaterials, the alpha at the edges between those materials must be totally transparent and only slowly raise towards the middle of the material area.

But either way, it`s visible only on screenshots, if the terrain moves and you`re at moderate distance, it`s hardly noticeable, provided your color texture is detailed enough.
On the above scene, if I actually switch off the detailed multi-material texture, it`s like 5% quality drop.

But, should the base color texture detail be lowered, the multimaterial texture is necessary.

Share this post


Link to post
Share on other sites
I would suggest instead of "colors" you think "textures." Thus, when the slope is greater than 60 degrees, you might want a "granite" texture. When the slope is zero, and altitude less than 20, you might want a "grass" texture. When the slope is smaller than 60 degrees, and altitude greater than 200, you might want a "snow" texture. Etc.

Then, for each texel, you calculate the fitness of the pixel for each of the defined functions, into some score (i e, this is 90% fit for grass, 50% fit for sand, 30% fit for granite and 10% fit for snow). Read from the texture of the highest fitness function, and then blend in a proportional amount of the next-highest fitness texture. In this case, you'd be 90% grass and 10% sand in that texel.

This will generate a really large texture -- you have to have sufficient resolution to make it look good. When you "read texture" for the base textures, that's basically software rasterization, where you tile the base textures some number of times across the large texture -- say, 16 times for a 256x256 base texture, generating a 4096x4096 texture.

You can get a more varied look if you use not just a regular tiling, but angle each base texture differently, and use a different scaling factor for each.

Last, given a height field, and render-to-texture capabilities, you can actually use the GPU to generate the texture, by coding the selection process into a fairly long pixel shader. With shader model 3, that shouldn't be a problem :-)

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603
Last, given a height field, and render-to-texture capabilities, you can actually use the GPU to generate the texture, by coding the selection process into a fairly long pixel shader. With shader model 3, that shouldn't be a problem :-)

Actually, on a GF2 (which is what he requires) that would be a problem. Terrain texturing on GF2 and GF6 is totally incomparable, IMHO.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!