2010-11-14 10 views
8

Come posso utilizzare OpenGLES 1.1 (iPhone) per disegnare una trama, ma solo utilizzando l'alfa per disegnare un colore?Uso di alpha dalla texture per disegnare tinta unita

Il risultato dovrebbe essere la stessa maschera alfa della texture originale, con all'interno un singolo colore solido al posto dei colori originali.

Sto usando glDrawArrays con glCoordPointer e glVertexPointer.

Penso che fare due passaggi, uno con la trama e uno con un colore solido per questo. Non riesco a trovare l'invertito di glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);.

Modifica: dopo un po 'di più in giro, penso che questo dovrebbe essere possibile ottenere utilizzando glTexEnvf. È solo questione di trovare gli argomenti giusti.

+0

Vorrei che fosse correlato pitone, avrei un trilione di risposte ormai. – sharvey

risposta

8

Come menzionato, glTexEnv è la strada da percorrere.

per sostituire i componenti RGB vostra struttura e mantenere la sua alfa incontaminata, si potrebbe provare qualcosa di simile (questo codice utilizza il rosso come colore di sostituzione):

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 

Arrivano alcune spiegazioni.

Quando si utilizza GL_COMBINE, si ha il controllo completo su come l'input/output delle diverse fasi di trama viene combinato insieme. In questo caso, specifichiamo che vogliamo sostituire (GL_REPLACE) le componenti RGB dello stage di texture 0 con quello che proviene dallo stage precedente (GL_PREVIOUS) che in questo caso è un singolo colore (impostato con glColor4f).

Non abbiamo impostato nulla di speciale per il componente alfa perché vogliamo il comportamento normale. aggiungendo le seguenti righe avrebbe avuto lo stesso effetto se non incluso (comportamento di default):

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

Grazie per questa risposta davvero informativa! Ho dovuto cambiare 'GL_TEXTURE_0' in' GL_TEXTURE0' per renderlo compilato, e aggiungere 'glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);' dopo il disegno per far funzionare il resto del rendering. Ora la forma è disegnata correttamente, ma usa sempre il bianco come colore. Potrebbe essere correlato ai cambiamenti che ho fatto? – sharvey

+0

Non penso che le tue modifiche siano la ragione del tuo problema e sì, devi aggiungere glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); dopo il disegno per tornare alla modalità di texturing predefinita. Non ho una chiara idea del perché otterresti risultati bianchi ... Hai aggiunto correttamente glColor4f() come descritto nell'esempio? – Ozirus

+0

Sì, glColor4f viene chiamato nella stessa identica posizione dell'esempio di codice. – sharvey

2

Se è possibile utilizzare OpenGL ES 2.0, è possibile farlo con uno shader di frammento personalizzato. Se utilizzi un framework basato su 1.1 o dispositivi di targeting che non supportano 2.0, questo non sarà di grande aiuto. Ma se è possibile, questo è come si fa:

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

Se è possibile garantire la SolidColor ha un alfa pari a zero è possibile saltare la fase di moltiplicazione.

+0

Grazie per il suggerimento. Non sono sicuro di poter usare gli shader. Non c'è un modo per usare l'inverso di glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); per fare questo? – sharvey

+0

Questa risposta dice che OpenGLES 1.1 non supporta shader personalizzati: http://stackoverflow.com/questions/543948/opengl-es-1-x-shaders/544022#544022. – sharvey

+1

Spiacente, modifico la risposta, anche se non ti è utile, potrebbe valere la pena di essere conservata per qualcun altro che fa una ricerca. – benzado

0

glBlendFunc(source_factor, dest_factor) si traduce in:

dest= source*source_factor + dest*dest_factor 

Così glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA) è:

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

Il secondo passaggio (che non è l'inverso) dovrebbe essere glBlendFunc(GL_SRC_ALPHA, GL_ONE):

dest= source*source.alpha + dest 

dal momento che ha già applicato la maschera alfa nel primo passaggio. Anche se è ancora necessario capire come applicare un colore costante con alfa invece della trama di origine.

Problemi correlati