Shaders - Combining colors

Hey all



Just a quick shader question.



I have a shader I’m playing with for some detail terrain texturing. In the shader I end up with three vec4’s that contain a texture color and an alpha value from a detail alphamap. The alpha is taken from either the r,g, or b channel in the alphamap depending on the texture. I want to find a way to combine these into one vec4 color. “mix” is clearly not the way to go, as what I need to do is have the resultant vec4 only show the textures with the correct alpha for that texture.



For example, here’s some naff textures and a map:







So, I only want to see texture1 where there is red in the map, texture2 for green, and texture3 for blue. If there’s green and blue pixels, then the resulting color should be a combination of the two textures, based off the strength of the green and blue elements.



Sorry if I didn’t explain that very well, but if anyone has any suggestions they would be well received.



Thanks





Mak

So you want texture splatting using a combined alpha map.

Let's assume you have color maps tex0 through tex2 in texture units 0 to 2, and your alpha map in tex3, which maps to texture unit 3. Here's a solution that should work:





uniform sampler2D tex0, tex1, tex2, tex3;

void main(){
    //texture coordinates for the colormaps
    vec2 tc0 = vec2(gl_TexCoord[0].x, gl_TexCoord[0].y);
    //texture coordinates for the alphamap
    vec2 tc1 = vec2(gl_TexCoord[1].x, gl_TexCoord[1].y);

    //obtain the base texture color
    vec4 result = texture2D(tex0,tc0);

    //get the alpha values from texture unit 1
    vec4 alp0= texture2D(tex1, tc1);

    //get the color from texture unit 2, the first splat layer
    vec4 col0 = texture2D(tex2, tc0);

    //blend in col0 with the intensity taken from alp0's red channel
    result = mix(result, col0, alp0.r);

    //get another splat layer color
    vec4 col1 = texture2D(tex3, tc0);

    //blend it in using the green channel from our alpha texture as intensity
    result = mix(result, col1, alp0.g);

   //multiply it with gl_Color to apply the vertex lighting
    gl_FragColor = result * gl_Color;
}



Does that help?

This could be done easily in say, 3ds max. (I use multi/sub materials containing blends – Only drawback is you cant join 3 textures)

It should be something you can easily do in a shader, but I can't get my head round it. :roll:



Mak

Works like a dream ! Thank you very much.





Mak

Just out of interest, why didn't you do the following? Is there something I dont know about with regards to performance and accessing built in GL variables (As you use the texture coordinates multiple times)?



...

//obtain the base texture color
vec4 result = texture2D(tex0, gl_TexCoord[0].xy);

//get the alpha values from texture unit 1
vec4 alp0= texture2D(tex1, gl_TexCoord[1].xy);

....


Last time I tried that, it caused some implicit casting problem on nvidia (not sure why though!), that's why I got into the habit of just rolling my own vec2 in the end. So no, nothing performance specific here, I'd really expect the built in thing to be slightly faster. But the way I do it seems to be more robust at least for older nvidia drivers, which I happen to be stuck with on my dev. machine.

Understood, i'd never heard of that one before now and quite frankly don't understand why that happens since sizzling (.xy)

should return a vec2 of the same components anyway.



What graphics card do you have?