OpenGL, GL_MODULATE and Multitexturing
Asked Answered
P

1

6

I have successfully drawn a multi-textured polygon but unfortunately only the first pixel of the overlaying texture is being used across the entire texture area.

Here are the textures (GL_TEXTURE0 and GL_TEXTURE1):

icon overlay

The result is this:

result

Only the red pixel at the top is being used. I've tried with just a 1x1 blue pixel up the top and I get the same result with blue overlay.

My code:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_COLOR_ARRAY);

const CGPoint vertices[] = {
    ccp(0,0),
    ccp(100,0),
    ccp(0,100),
    ccp(100,100),
};

// This will flip the image for us as well
const CGPoint coordinates[] = {
    ccp(0,1),
    ccp(1,1),
    ccp(0,0),
    ccp(1,0),
};

// Config multitextures
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, icon.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, overlay.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

GLubyte points = 4;

// Draw the square
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, points);

// Revert back
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);

// glClientActiveTexture(GL_TEXTURE0); // breaks multitexturing
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);

glEnableClientState(GL_COLOR_ARRAY);

This is an OpenGL problem, but the iOS project is available here for those interested: http://dl.dropbox.com/u/33811812/cocos2d/OpenGLTest.zip

EDIT: From the Red Book:

If you are multitexturing and you use glTexCoord*(), you are setting the texture coordinates for the first texture unit. In other words, using glTexCoord*() is equivalent to using glMultiTexCoord* (GL_TEXTURE0,...)

Any hints as to how to pass an array of coordinates? OpenGL ES 1.1 doesn't support glBegin() etc.

Ploce answered 2/2, 2012 at 16:59 Comment(3)
It seems you are looking for glClientActiveTexture.Foot
Brilliant! Works, except that setting glClientActiveTexture(GL_TEXTURE0); after drawing causes it to fail again. I have other draw methods that I need to revert the states for. How can this be achieved?Ploce
I've also looked at glVertexAttribPointer but I have no clue how to use this to specify the coordinates for GL_TEXTURE1...Ploce
P
7

Finally! The solution was that I had to do three things:

  • Use glClientActiveTexture(GL_TEXTURE*) for 0 and 1 before the glTexCoordPointer
  • Use glEnableClientState(GL_TEXTURE_COORD_ARRAY) for each texture as well
  • Revert back to glClientActiveTexture(GL_TEXTURE0) to avoid conflicting with further draws

Here's the code that works:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_COLOR_ARRAY);

const CGPoint vertices[] = {
    ccp(0,0),
    ccp(100,0),
    ccp(0,100),
    ccp(100,100),
};

// This will flip the image for us as well
const CGPoint coordinates[] = {
    ccp(0,1),
    ccp(1,1),
    ccp(0,0),
    ccp(1,0),
};

// Config multitextures
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, icon.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, overlay.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glEnable(GL_TEXTURE_2D);

GLubyte points = 4;

// Draw the square
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, points);

// Revert back
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);

glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);

glEnableClientState(GL_COLOR_ARRAY);

And the result:

works

Ploce answered 3/2, 2012 at 4:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.