GLSL 400 multi texturing, how best?


I need to help with multi texturing. I wanna more then 4 textures and also using shader color for changing texture color(look to following img)


Currently I’m using textures based on height (3: grass[base], rock, snow). I read they using vec4 to combine one texture per channel, this mean just 4 textures, how to do more textures?

Current GLSL:

    vec2 uvNear, uvFar;

    nearAndFarTexCoords(uvNear, uvFar);

    float textureDistanceFactor = textureDistanceBlendFactor();

    // Get grass texture color
    vec4 grassNear  = texture(grassTexture, uvNear);
    vec4 grassFar   = texture(grassTexture, texCoords);
    vec4 grassColor = mix(grassNear, grassFar, textureDistanceFactor);

    // Get rock texture color
    vec4 rockNear  = texture(rockTexture, uvNear);
    vec4 rockFar   = texture(rockTexture, uvFar);
    vec4 rockColor = mix(rockNear, rockFar, textureDistanceFactor);

    // Blend rock and grass texture based upon the worldNormal vector
    vec4 grassRockColor = mix(rockColor, grassColor, smoothstep(0.75, 0.95, clamp(worldNormal.y, 0.0, 1.0)));

    // Now blend with snow based upon world height
    vec4 snowNear  = texture(snowTexture, uvNear);
    vec4 snowFar   = texture(snowTexture, 5.0 * uvFar);
    vec4 snowColor = mix(snowNear, snowFar, textureDistanceFactor);

    vec4 diffuseColor = mix(grassRockColor, snowColor, smoothstep(10.0, 15.0, worldPosition.y));

    // Calculate the lighting model, keeping the specular component separate
    vec3 ambientAndDiff, spec;

    phongModel(ambientAndDiff, spec);

    vec4 color = vec4(ambientAndDiff, 1.0) * diffuseColor + vec4(spec, 1.0);

You said something about using vec4 to combine textures… This sounds odd to me, I’m not sure what you mean by this.

vec4 has four components and a texture typically also has four components. vec4(Red, Green, Blue, Alpha). One vec4 is one texture.

So far as the number of textures you can use… I would say that 8 textures will probably work on most machines, maybe not well… There will likely be a few here and there that won’t like this at all.

You can also look up ‘texture atlas’ which is a technique for packing many UV coordinates into just one texture.

I assume that he’s referring to texture splatting (aka splat mapping), where you have up to four terrain textures then another texture which is effectively 4 alpha channels, one for each of the terrain textures. Most of the time, one channel will be at 1.0 to select a specific terrain texture and the other three at zero; at boundaries between terrain types, two channels will have intermediate values to blend between two textures, with the other two at zero.

It would be possible to have another 4 terrain textures and another alpha texture (OpenGL 3.x guarantees at least 16 texture image units per shader), but getting to be expensive in terms of both memory consumption and bandwidth and processing time. Given that you’re unlikely to want to blend more than two textures at any given point, you’d probably be better off with e.g. a GL_RG8UI texture holding the indices of a primary and secondary texture for each texel plus a GL_R8 texture to specify the blend factor between the two. That supports up to 256 terrain textures with less memory consumption for the “map” texture than the 4-alpha-channels approach (which was originally designed for hardware which lacked array textures, so you couldn’t choose which textures to blend, only vary their blend factors).

marClintDion: GClements was right, I meant texture splatting

GClements: So texture splatting is not perfect for this?

I’m making world editor, so I want to change textures by painting tool

Is possible with GLSL 3.3+ multitexturing do it through alphamaps?

See ex:
On picture are 5 textures (including base). Base texture is green, alphamap is full. And others alphamaps (each for texture) are filled just where texture is painted. Do you understand what I mean?

Or exists still better way to make multitexturing for change with tools?

[QUOTE=glararan;1254786]See ex:
On picture are 5 textures (including base). Base texture is green, alphamap is full. And others alphamaps (each for texture) are filled just where texture is painted. Do you understand what I mean?[/QUOTE]
Yes. That’s typical texture splatting; one base texture and four overlays controlled by a 4-channel alpha map.

If you’re asking how to do it, try:

uniform sampler2D textureMap;
uniform sampler2D textureBase;
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D texture3;
in vec2 texcoordMap;
in vec2 textureScale;
void main()
    vec2 texcoord = texcoordMap * textureScale;
    vec4 alpha = texture(textureMap, texcoordMap);
    vec4 color = texture(textureBase, texcoord);
    color = mix(color, texture(texture0, texcoord), alpha[0]);
    color = mix(color, texture(texture1, texcoord), alpha[1]);
    color = mix(color, texture(texture2, texcoord), alpha[2]);
    color = mix(color, texture(texture3, texcoord), alpha[3]);

Ok thanks, and this is btw not possible with more than 4 textures right?

You’d need another alpha map for each set of 4 terrain textures, but the only hard limit is the number of texture units supported by the implementation. OpenGL 3.x guarantees at least 16 texture units, so 1 base texture, 3 alpha maps and 12 terrain textures is possible.

However, it’s inefficient to read many textures when you’re typically only using 1 or 2 at any given point, so you’d probably want to use a different approach with more than 4 textures (or even just with 4 textures).

And even that isn’t a limit anymore, if you’re on a GPU/driver which supports ARB_bindless_texture.