2012-02-02 12 views
5

He dibujado con éxito un polígono de varias texturas pero desafortunadamente solo se está utilizando el primer píxel de la textura superpuesta en toda el área de la textura.OpenGL, GL_MODULATE y Multitexturing

Éstos son las texturas (GL_TEXTURE0 y GL_TEXTURE1):

iconoverlay

El resultado es el siguiente: se está utilizando

result

Sólo el píxel rojo en la parte superior. Lo he intentado con solo un píxel azul de 1x1 en la parte superior y obtengo el mismo resultado con la superposición azul.

Mi código:

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); 

Este es un problema de OpenGL, pero el proyecto de iOS está disponible aquí para los interesados: http://dl.dropbox.com/u/33811812/cocos2d/OpenGLTest.zip

EDIT: Desde el Libro Rojo:

Si tiene varias copias y usa glTexCoord *(), está configurando la textura coo indica la primera unidad de textura. En otras palabras, utilizando glTexCoord *() es equivalente a usar glMultiTexCoord * (GL_TEXTURE0, ...)

¿Alguna pista sobre cómo pasar una matriz de coordenadas? OpenGL ES 1.1 no admite glBegin() etc.

+2

Parece que busca [glClientActiveTexture] (http://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml). –

+0

¡Brillante! Funciona, excepto que el ajuste 'glClientActiveTexture (GL_TEXTURE0);' después del dibujo hace que vuelva a fallar. Tengo otros métodos de dibujo para los que necesito revertir los estados. ¿Cómo se puede lograr esto? –

+0

También he mirado 'glVertexAttribPointer', pero no tengo ni idea de cómo usar esto para especificar las coordenadas para GL_TEXTURE1 ... –

Respuesta

6

¡Por fin! La solución era que tenía que hacer tres cosas:

  • Uso glClientActiveTexture (GL_TEXTURE *) para 0 y 1 antes de la glTexCoordPointer
  • Uso glEnableClientState (GL_TEXTURE_COORD_ARRAY) para cada textura, así
  • volver a glClientActiveTexture (GL_TEXTURE0) para evitar entrar en conflicto con sorteos más

Aquí está el código que funciona:

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); 

Y el resultado:

works