2010-11-14 15 views
8

¿Cómo puedo usar OpenGLES 1.1 (iPhone) para dibujar una textura, pero solo usando el alfa para dibujar algo de color?Usar alfa de textura para dibujar un color sólido

El resultado debe ser exactamente la misma máscara alfa de la textura original, con un único color sólido dentro en lugar de los colores originales.

Estoy usando glDrawArrays con glCoordPointer y glVertexPointer.

Creo que hacer dos pases, uno con la textura y otro con un color sólido para esto. Simplemente no puedo encontrar la inversión de glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);.

Editar: después de mirar un poco más, creo que esto debería ser posible con glTexEnvf. Es solo cuestión de encontrar los argumentos correctos.

+0

Me gustaría que fuera relacionado pitón, que tendría unos tropecientos respuestas a estas alturas. – sharvey

Respuesta

8

Como se mencionó, glTexEnv es el camino a seguir.

Para sustituir los componentes RGB de su textura y mantener intacta su alfa, podría intentar algo como esto (el código utiliza el rojo como color de sustitución):

glColor4f(1.0f, 0.0f, 0.0f, 1.0f); 

glActiveTexture(GL_TEXTURE_0); 
glEnable(GL_TEXTURE_2D); 
glBindTexture(GL_TEXTURE_2D, spriteTexture); 

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); 
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); 
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); 
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); 
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); 

// ... draw as usual 

Aquí vienen algunas explicaciones.

Al usar GL_COMBINE, tiene control completo sobre cómo la entrada/salida de las diferentes etapas de textura se combinan juntas. En este caso, especificamos que queremos reemplazar (GL_REPLACE) los componentes RGB de la etapa de textura 0 con lo que viene de la etapa anterior (GL_PREVIOUS) que en este caso es un color único (establecido con glColor4f).

No establecimos nada especial para el componente alfa ya que queremos el comportamiento normal. Añadiendo las siguientes líneas habría tenido el mismo efecto que si no está incluido (comportamiento predeterminado):

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); 
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); 
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); 
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); 
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); 
+0

Gracias por esta respuesta realmente informativa! Tuve que cambiar 'GL_TEXTURE_0' por' GL_TEXTURE0' para hacerlo compilar, y agregar 'glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);' después del dibujo para que el resto del renderizado funcione. Ahora la forma está dibujada correctamente, pero siempre usando blanco como color. ¿Podría estar relacionado con los cambios que hice? – sharvey

+0

No creo que los cambios sean la razón de su problema y sí, debe agregar glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); después del dibujo para volver al modo de texturización predeterminado. No tengo una idea clara de por qué obtendría resultados en blanco ... ¿Ha agregado correctamente el glColor4f() como se describe en el ejemplo? – Ozirus

+0

Sí, se llama a glColor4f exactamente en la misma posición que en el ejemplo del código. – sharvey

2

Si puede usar OpenGL ES 2.0, puede hacerlo con un sombreador de fragmentos personalizado. Si está utilizando un marco basado en 1.1 o está apuntando a dispositivos que no son compatibles con 2.0, esto no será de mucha ayuda. Pero si se puede, así es como se hace:

uniform lowp sampler2D sampler; // which texture unit to use 
uniform lowp vec4 solidColor; 

varying highp vec2 fragmentTexCoord; 

void main() 
{ 
    // Get the color with an alpha of zero 
    vec4 color = vec4(1,1,1,0) * solidColor; 
    // Get the alpha from the texture, zero the r,g,b components 
    vec4 alpha = vec4(0,0,0,1) * texture2D(sampler, fragmentTexCoord); 
    // their sum is the solid color with the alpha mask of the texture 
    gl_FragColor = color + alpha; 
} 

Si se puede garantizar la solidColor tiene un alfa de cero se podría omitir el paso de multiplicación.

+0

Gracias por la sugerencia. No estoy muy seguro de si puedo usar sombreadores. ¿No hay una forma de usar el inverso de glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); ¿para hacer esto? – sharvey

+0

Esta respuesta dice que OpenGLES 1.1 no admite sombreadores personalizados: http://stackoverflow.com/questions/543948/opengl-es-1-x-shaders/544022#544022. – sharvey

+1

Lo siento, voy a editar la respuesta, incluso si no es útil para usted, podría valer la pena preservar para alguien más haciendo una búsqueda. – benzado

0

glBlendFunc(source_factor, dest_factor) se traduce en:

dest= source*source_factor + dest*dest_factor 

Así glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA) es:

dest= source*0 + dest*(1 - source.alpha) 

El segundo pase (que no es el inverso) debe ser glBlendFunc(GL_SRC_ALPHA, GL_ONE):

dest= source*source.alpha + dest 

ya que ya aplicó la máscara alfa en el primer pase. Aunque todavía necesita averiguar cómo aplicar un color constante con alfa en lugar de la textura de origen.

Cuestiones relacionadas