2012-07-17 15 views
5

Sto disegnando colori e trame uniformi su tela WebGL. I miei colori e le mie trame hanno valori alfa variabili e voglio che vengano miscelati correttamente. Voglio avere uno sfondo trasparente (dovrebbero essere mescolati con contenuti HTML, che è sotto tela).Fusione con sfondo HTML in WebGL

In WebGL, io uso

gl.clearColor(0, 0, 0, 0); 
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 
gl.enable(gl.BLEND); 

Funziona correttamente, quando lo sfondo è nero HTML. Ma quando imposto un motivo JPG come sfondo, disegno un triangolo nero (alfa = 1) e un triangolo bianco (alfa = 0,5), posso vedere il motivo dello sfondo al posto in cui i triangoli si intersecano tra loro. È corretto questo comportamento?

risposta

11

La mia risposta precedente era effettivamente errata. Che è il risultato atteso di ciò che descrivi.

gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) significa che l'alfa risultante è

A_final = A_s * A_s + (1 - A_s) * A_d 

Nel tuo esempio, dopo il triangolo nero (alfa = 1) è disegnato, un pixel disegnato nella framebuffer avrà un alfa di

1 * 1 + (1 - 1) * 0 == 1 + 0 == 1 

Quindi sarà completamente opaco. Successivamente, dopo il triangolo bianco (alfa = 0,5) è disegnata, un pixel nella intersezione dei due triangoli avrà un alfa di

.5 * .5 + (1 - .5) * 1 == .25 + .5 == .75 

Ciò significa che il colore finale sarà trattato come parzialmente trasparente, e , quando è composto con la pagina, lo sfondo della pagina verrà visualizzato.

Questo è un problema un po 'raro in OpenGL regolare, poiché il contenuto di solito è composto su uno sfondo vuoto. Viene fuori quando si disegna su un FBO e si devono comunque comporre i risultati con altri contenuti nel proprio contesto. Ci sono alcuni modi per affrontare questo.

Un modo è quello di avere la vostra miscela alpha con gl.ONE, gl.ONE_MINUS_SRC_ALPHA in modo da ottenere

A_final = A_s + (1 - A_s) * A_d 

che è quello che di solito si desidera con alpha blending. Tuttavia, desideri che i tuoi colori si fondano ancora con gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA. È possibile utilizzare gl.blendFuncSeparate anziché gl.blendFunc per impostare separatamente le funzioni di fusione del colore e fusione alfa. In questo caso, si dovrebbe chiamare

gl.BlendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); 

Un'altra opzione è quella di avvalersi di colori con alfa premoltiplicato (che WebGL actually already assumes you are using, per esempio, quando il campionamento di un colore da una texture). Se si disegna il secondo triangolo con l'alfa già moltiplicato attraverso il colore (quindi un mezzo trasparente triangolo bianco avrebbe gl_FragColor insieme a vec4(.5, .5, .5, .5)), quindi è possibile utilizzare il metodo di fusione

gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) 

e agirà come vuoi sia per il colore che per l'alfa.

La seconda opzione è quello che si vede in comunemente esempi WebGL, dal momento che (come detto), WebGL assume già i vostri colori sono premoltiplicati (così vec4(1., 1., 1., .5) è fuori gamma, l'uscita di rendering è definito, e l'autista/GPU può emettere qualsiasi colore pazzo che vuole). È molto più comune vedere gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) in normali esempi OpenGL, il che porta ad una certa confusione.

+0

Grazie mille, sei fantastico! :) Ho deciso di utilizzare gl.blendFuncSeparate(). Ho provato a usare alfa pre-moltiplicato, ma sembra strano, perché le mie trame non sono premoltiplicate. Io uso gl.texImage2D (gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bd.image); ? Come posso cambiarlo in premoltiplicato? –

+0

Per impostazione predefinita, le trame non sono premolteplicate per te quando caricate. Per fare in modo che il browser moltiplica automaticamente i colori in base all'alfa mentre importa la trama, è necessario impostare il parametro texture prima di chiamare texImage2D. Quindi chiamerai 'gl.pixelStorei (gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);' prima che texImage2D chiami l'elenco qui sopra. Vedere la nota sui parametri di memorizzazione dei pixel nelle specifiche WebGL: http://www.khronos.org/registry/webgl/specs/latest/#PIXEL_STORAGE_PARAMETERS –