2013-08-31 14 views
8

Sto imparando OpenGL ES 2.0 e mi piacerebbe creare un'app per capire meglio come funziona. L'app ha un set di filtri che l'utente può applicare alle immagini (lo so, niente di nuovo: P).Immagini e maschera in OpenGL ES 2.0

Uno di questo filtro prende due immagini e una maschera e mescola le due immagini che mostrano loro attraverso la maschera (qui un'immagine per spiegare meglio quello che voglio ottenere)

enter image description here

Al momento Sono davvero confuso e non so da dove iniziare a creare questo effetto. Non riesco a capire se devo lavorare con trame multiple e FrameBuffer multipli o posso lavorare con un singolo shader.

Avete qualche suggerimento per aiutarmi a fare questo progetto?

EDIT --------

ho trovato questa soluzione, ma quando uso come linee maschera al posto di cerchi il risultato è davvero "sgangherata", soprattutto se vengono ruotati linee.

precision highp float; 

varying vec4 FragColor; 
varying highp vec2 TexCoordOut; 

uniform sampler2D textureA; 
uniform sampler2D textureB; 
uniform sampler2D mask; 

void main(void){ 
    vec4 mask_color = texture2D(mask, TexCoordOut); 

    if (mask_color.a > 0.0){ 
     gl_FragColor = texture2D(textureA, TexCoordOut); 
    }else { 
     gl_FragColor = texture2D(textureB, TexCoordOut); 
    } 
} 

È probabilmente meglio utilizzare il buffer stencil o il blending?

+3

BTW, non è necessario utilizzare il canale alfa ('mask_color.a') per la maschera. Puoi usare qualsiasi altro canale 'r',' g', 'b' e in questo modo salvi la memoria della GPU usando la texture mask senza canale alfa. – keaukraine

+0

@MatterGoal Può essere possibile rispondere a questa domanda, http://stackoverflow.com/questions/24486729/uiimage-masking-with-gesture –

risposta

12

È possibile applicare la maschera in una sola riga senza utilizzare la costosa if:

gl_FragColor = step(0.5, vMask.r) * vColor_1 + (1.0 - step(0.5, vMask.r)) * vColor_2; 

O, meglio solo interpolare tra due colori:

gl_FragColor = mix(vColor_1, vColor_2, vMask.r); 

In questo caso la maschera può essere attenuato (cioè con sfocatura gaussiana) per produrre meno aliasing. Ciò produrrà risultati molto buoni rispetto a un valore soglia singolo.

+0

Devo usare multipass per creare una maschera sfocata? O stai suggerendo di creare la sfocatura con lo stesso shader? – MatterGoal

+2

È possibile creare sfocatura con lo stesso shader effettuando diversi (ovvero 5) recuperi della trama maschera e facendo una media del risultato. Quindi usando questo valore medio invece di '' vMask.r''. –

+2

Qui puoi trovare un'implementazione di una sfocatura gaussing in uno shader di frammenti: http://xissburg.com/faster-gaussian-blur-in-glsl/ –

1

Non sono necessari più shader o framebuffers, solo più unità di texture. Basta usare 3 unità di texture che sono tutte indicizzate con le stesse coordinate di texture e utilizzare la texture Mask per selezionare tra le altre due texture. Lo shader frammento sarebbe simile a questa:

uniform sampler2D uTextureUnit_1; 
uniform sampler2D uTextureUnit_2; 
uniform sampler2D uTextureMask; 
varying vec2 vTextureCoordinates; 

void main() 
{ 
    vec4 vColor_1 = texture2D(uTextureUnit_1, vTextureCoordinates); 
    vec4 vColor_2 = texture2D(uTextureUnit_2, vTextureCoordinates); 
    vec4 vMask = texture2D(uTextureMask, vTextureCoordinates); 

    if (vMask.r > 0.5) 
     gl_FragColor = vColor_1; 
    else 
     gl_FragColor = vColor_2; 
} 

Si può vedere che l'utilizzo di una terza unità consistenza solo per fare un test binario sul canale rosso non è molto efficiente, quindi sarebbe meglio per codificare la maschera nella Canali alfa di Textures 1 o 2, ma questo dovrebbe iniziare.

+0

Suggerisce di applicare alla scena determinate impostazioni per ottenere un risultato perfetto? Per alcune maschere "non lineari" ottengo un risultato finale terribile. – MatterGoal

+2

OpenGL in particolare non fornisce risultati perfetti per i pixel, ma è possibile migliorare la qualità aumentando le dimensioni delle trame. Per glTexParameteri(), utilizzare GL_LINEAR per MAG_FILTER e MIN_FILTER. MIP_MAP aiuta solo se ridimensionamento. – ClayMontgomery