Skip to main content
GameDev.net gamedev.net
🔒 Locked

Converting Multipass splat to Multitexture splat

Started by Tinyn Jan 7, 2007 at 5:44 AM 3 replies 1.3k views
Original Post
Tinyn
Tinyn
I have an existing terrain system with textures like so: Base Detail 1 Detail 1 Alpha Detail 2 Detail 2 Alpha Detail 3 Detail 3 Alpha Shadow Color (basically a simple white w/ glColorf()) Shadow Alpha The details are sometimes left out, so the grand total varies between 3 and 9 textures needed. On a system where GL_MAX_TEXTURE_UNITS_ARB is 1, this will never look right, ever ever. When GL_MAX_TEXTURE_UNITS_ARB is 2, it can look right, but only if its split into 2-5 passes. I have this working. If GL_MAX_TEXTURE_UNITS_ARB is 4, I think it can be reduced to 1-3 passes, depending on detail count. The resolution is the alpha maps is higher hen the resolution of the terrain position vertices, so I figured trying to combine the alphas into a color array and using the color-as-alpha shader splat trick wouldn't work real well (read: wouldn't produce the exact same output as the existing 5 pass method). So I figured I could just layer the textures ontop of each other, up to GL_MAX_TEXTURE_UNITS_ARB per pass, and do something with glTexEnv() and it would still work out. Well, its not.

    int TexUnit = 0;
    for(int Loop = 0; Loop < Passes[PassNum].Layers.size(); Loop++) {

        glActiveTextureARB(GL_TEXTURE0_ARB+TexUnit);        
        glEnable(GL_TEXTURE_2D);
        Passes[PassNum].Layers[Loop].BaseTexture->Bind();
        glClientActiveTextureARB(GL_TEXTURE0_ARB+TexUnit);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2, GL_FLOAT, 0, Passes[PassNum].Layers[Loop].BaseTexCoords);
        if(PassNum == 0 && Loop == 0)
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        else {
            glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE); 
            glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ARB,GL_ADD); 
            glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_PREVIOUS);
            glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_TEXTURE);
            glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA,GL_TEXTURE);
            glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_PREVIOUS);    
            glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
            glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR); 
        }
        TexUnit++;

        if(Passes[PassNum].Layers[Loop].AlphaTexture != NULL) {
            glActiveTextureARB(GL_TEXTURE0_ARB+TexUnit);        
            glEnable(GL_TEXTURE_2D);
            Passes[PassNum].Layers[Loop].AlphaTexture->Bind();
            glClientActiveTextureARB(GL_TEXTURE0_ARB+TexUnit);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glTexCoordPointer(2, GL_FLOAT, 0, Passes[PassNum].Layers[Loop].AlphaTexCoords);
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
            glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
            glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_PREVIOUS);     
            TexUnit++;
        }

        glColor4fv((float*)&Passes[PassNum].Layers[Loop].BaseColor);

    }
    for( ; TexUnit < MaxTexturesPerPass; TexUnit++) {
        glActiveTextureARB(GL_TEXTURE0_ARB+TexUnit);
        glClientActiveTextureARB(GL_TEXTURE0_ARB+TexUnit);
        glDisable(GL_TEXTURE_2D);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }

Funnily enough, if I fool my program into thinking GL_MAX_TEXTURE_UNITS_ARB is 2 when its splits the layers up into passes it renders fine, so the glTexEnv stuff isn't horribly screwing up the first layers. But when GL_MAX_TEXTURE_UNITS_ARB is allowed to be the cards natural 4, when it tried to combine Base + Detail 1 + Detail 1 Alpha is goes nuts. And it goes nuts trying to combined Detail 2 + Detail 2 Alpha + Detail 3 + Detail 3 Alpha as well. I'm starting to suspect its just not possible to get this to work right since the details and alphas are separate layers.
Tinyn
Tinyn
I know that, thats the part that works. The problem is trying to group these layers together for cards with 4+ texture units. The multitexture glTexEnv thing only wants to work in a sort of stack, one after the other type system, while what I need it to do is cluster the textures with their alphas, and then layer them on top of each other.
Digitalfragment
Digitalfragment
i havent played with TexEnv stuff for ages but from looking at your code for binding the alpha texture

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_PREVIOUS); <--- ???

Shouldnt you be calling in the texture alpha there instead of GL_PREVIOUS?
Tinyn
Tinyn
That was definitely wrong, but didn't help much. Near as I can tell the problem is that OpenGL handles the textures in fixed 1, 2, 3, 4 order, but what I need it to do is 1+2=A, 3+4=B, A+B=C. A Fragment shader could do that, but then I could have to take over the lighting and fog myself, when its currently using the fixed functionality pipeline for those.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.