Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Visual example:

MultiTexturing by looking at neighbour's textures, set

I've been trying to understand multitexturing for a while now, I've created a terrain generator but have no need for height just yet and I still want one texture to blend over to another texture nicely.

I think Blau said that you only need 4 textures per vertex. My only guess then is that each point in a terrain has 4 neighbours - right? And that point is the main texture to sample from / blend from. Because it can't mean that 4 textures are all you get on a whole map in a game.

My idea is to have an "TextureID" for each point and whenever this point comes up, you load the textures in the effect with that neighbours textures.

Example (for each point):

effect.Parameters["MainTexture"].Setvalue(Content.Load<Texture2D>("MainTexture"))
effect.Parameters["TextureTopOfPoint"].SetValue(Content.Load<Texture2D>(textureID));
effect.Parameters["TextureRightOfPoint"].SetValue(Content.Load<Texture2D>(textureID));
effect.Parameters["TextureBottomOfPoint"].SetValue(Content.Load<Texture2D>(textureID));
effect.Parameters["TextureLeftOfPoint"].SetValue(Content.Load<Texture2D>(textureID));

/*
   Now the Pixel and Vertex Shader can calculate a blend effect
   from Center point to it's neighbouring points
*/

and somehow in the Effect file, blend from "Center point" to all it's neighbours. I also guess this would be a "slow" process.

Problems are:

  • Is this possible? I can't accept 4 textures for a whole map, so how do I manage to have multiple textures at the same time? And I don't want a solution with colors (like this) or heightmap, because I want it to be possible to have 4 or more textures on a flat surface.

  • How do I access each point's neighbour and when do I know when to set them?

My map contains Areas, each Area has it's own VertexBuffer and IndexBuffer.

(Example: MapWidth=4096, MapHeight=4096, each square = 128x128 = (32 * 128 x 32 * 128 grid)

public class Area
{
    public VertexPositionTexture[] Vertices { get; set; }
    public int[] Indexs { get; set; }

    public VertexBuffer GetVertexBuffer() { /* create a vertexbuffer */ }
    public IndexBuffer GetIndexBuffer() { /* creates a indexbuffer */ }
}

Edit (still not optimal)

Implemented some kind of method, but this method still relies on colors and I have no blendmap. I just use the color in the Vertex to check for a value (r, g, b, a)

enter image description here

Effect Code:

float4 PixelShaderFunction(VS_OUTPUT input) : COLOR
{
   float4 colour = float4(0,0,0,0);

   colour += tex2D(GroundText0Sampler, input.TexCoord) * input.Color.r;
   colour += tex2D(GroundText1Sampler, input.TexCoord) * input.Color.g;
   colour += tex2D(GroundText2Sampler, input.TexCoord) * input.Color.b;
   colour += tex2D(GroundText3Sampler, input.TexCoord) * input.Color.a;

   return colour;
}
share|improve this question

1 Answer 1

The idea of blending 4 textures together by using a 5th texture to specify how to blend them together can be easily extended to 8, 12, 16, ... textures. As a quick refresher this is how the default approach works:

You have 4 textures for detailing, for example:

  • Rocks
  • Grass
  • Water
  • Concrete

And one texture which specifies how to blend these together. In the pixel shader we sample the colour for the final pixel like this:

float4 blending = tex2D(blendmap, In.uv);
float4 output;
output.rgba = 
    tex2D(rocks, In.uv).rgba * blending.r + 
    tex2d(grass, In.uv).rgba * blending.g +
    tex2d(water, In.uv).rgba * blending.b +
    tex2d(concrete, In.uv).rgba * blending.a +

output.rgba /= 4;

As you see we are limited to 4 textures because our blend map has only 4 channels.

Now all we need to allow 8 textures is adding a second blend map, add the terms of the second blend map and then divide by 8 at the end. We can keep doing this, it's not going to get any cheaper anyway because we will need to store in some way how the textures are blended.

I also think that you don't need more than 8 or maybe 12 textures to have a really good looking terrain. Smaller details can be added using projections and of course you can use multiple terrain meshes that partially obscure each other.

share|improve this answer
    
Isn't this exactly like the answer that I said in my post that I didn't want? It looks like this: toyfactorygame.com/wp.php/2010/05/06/… –  Deukalion Jan 5 '13 at 18:08
    
I mean this way, for each square to be able to have blending effect with other textures I need to add a vertexbuffer for each square; change the textures in the effect for each vertexbuffer (by checking what textures are at each corner which makes the rendering process really slow down. Right now, I render an area (non specific size), but let's say 4096x4096 pixels with 128x128 grid, so 32*32 squares. Each point should have it's own texture. So, simply put I have to check every triangle and the texture with it. Or have a blendmap for every square. –  Deukalion Jan 5 '13 at 19:12
    
This could have worked with an extra int by declaring my own IVertexType and having a Texture2DArray but I can't set the value to a Texture2DArray. –  Deukalion Jan 5 '13 at 19:14
    
You only need one vertex buffer for the entire terrain and it only needs to have two streams (position and texture coordinate) for this to work and X + X/4 textures. I don't see how you would need a vertex buffer for each square, that would indeed be extremely slow. Note that you can tile the normal textures multiple times, but not the blendtexture to get better results. This is how the Unreal Engine does it :). –  Roy T. Jan 5 '13 at 19:42
    
Or are you just looking for a way to merge/blend seams of your tiles? –  Roy T. Jan 5 '13 at 19:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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