10
\$\begingroup\$

I'm working with XNA on a 3D Game, and I'm trying to have a proper and nice environnement. I actually followed a tutorial to create a terrain from a heightmap. To texture it, I just apply a grass texture on it and tile it a number of times.

But what I want to do is to have a really realistic texturing, but also generate it automatically (for example if I want to use Perlin noise to generate a terrain and then texture it).

I already learned about multi-texturing, loading a map file with different colors for different textures, but I don't think this is really efficient, for instance for cliffs or very steep areas it will tile a texture badly as it's a view from the top. (Also, I don't know how I'll draw roads or dirt paths with that.)

I'm looking for an efficient solution to realistically texture mapping procedurally-generated terrain.

\$\endgroup\$
  • 1
    \$\begingroup\$ Your mapping issue isn't at all trivial. It can't be properly answered in a few paragraphs. I recommend you take a look at harmonic mappings and what is explained in this paper: cs.ubc.ca/~sheffa/papers/TOG02.pdf \$\endgroup\$ – teodron Nov 8 '13 at 16:54
2
\$\begingroup\$

I guess you're not concerned with blend maps or texture splatting (as that's independent of your UV mapping). Since you specifically asked for minimizing distortion caused by the mapping, you could consult section 1.5 of this GPU Gems article:

https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch01.html

This could work even on procedurally generated terrain. The concept is also known as "triplanar texturing".

LATER EDIT: I've tested the technique in my own terrain renderer using no precomputed uvs for the mapping. All you have to do is compute 3 sets of UVs for the 3 different projection planes (XY, YZ and ZX). This can be achieved using simple vertex and fragment shader snippets:

VShader:

float tileSize = 2.0;
vec4 worldPos = ( gl_Vertex);//So we obtain the world position

TexCoordX = (worldPos.zy/tileSize);//here are our texture coordinates...
TexCoordY = (worldPos.xz/tileSize);
TexCoordZ = (worldPos.xy/tileSize);
normal =  gl_Normal;
wNormal = normal;

FShader:

vec3 n = wNormal;
n*=n;
vec2 tcX = fract(TexCoordX);
vec2 tcY = fract(TexCoordY);
vec2 tcZ = fract(TexCoordZ);

vec4 grassCol = texture2D(grassTexture,tcX)*n.x+
                texture2D(grassTexture,tcY)*n.y+
                texture2D(grassTexture,tcZ)*n.z;
\$\endgroup\$
3
\$\begingroup\$

You could define a set of textures (grass, dirt, rock) and use those. Let's say using these three layers (rock at the bottom, dirt on top and grass topmost), you can define three alpha channels to define how much of each texture is visible. Start with a simple noise map for your alpha channels and maybe take the slope of terrain into account. The more slope, the more rock will shine through. This is a technique called 'Texture Splatting' as far as I remember. Here are some links to get you started. Advanced Texture Splatting (gamasutra)

TextureSplatting (charlesbloom, the one I used to get started with this topic)

You should be able to get good looking results rather quick, very rewarding topic

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.