2013-08-31 7 views
8

Ich lerne OpenGL ES 2.0 und ich möchte eine App erstellen, um besser zu verstehen, wie es funktioniert. Die App hat eine Reihe von Filtern, die der Benutzer auf Bilder anwenden kann (ich weiß, nichts neues: P).Bilder und Maske in OpenGL ES 2.0

Einer dieser Filter nimmt zwei Bilder und eine Maske und es mischt die zwei Bilder, um sie durch den Maske zeigen (hier ein Bild besser zu erklären, was ich erreichen will)

enter image description here

Im Moment Ich bin wirklich verwirrt und ich weiß nicht, wo ich anfangen soll, diesen Effekt zu erzeugen. Ich kann nicht verstehen, ob ich mit mehreren Texturen und mehreren FrameBuffern arbeiten muss oder einfach mit einem einzelnen Shader arbeiten kann.

Haben Sie Hinweise, um mir bei diesem Projekt zu helfen?

EDIT --------

Ich habe diese Lösung gefunden, aber wenn ich als Maske Linien anstelle der Kreise verwenden das Ergebnis ist wirklich „grungy“, vor allem, wenn Linien gedreht werden.

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

Ist es wahrscheinlich besser, Stencil Buffer oder Blending zu verwenden?

+3

BTW, Sie müssen nicht Alpha ('mask_color.a') Kanal für Maske verwenden. Sie können jeden anderen 'r',' g', 'b' Kanal verwenden und auf diese Weise speichern Sie den GPU-Speicher mit Hilfe der Maskentextur ohne Alphakanal. – keaukraine

+0

@MatterGoal Möglicherweise können Sie diese Frage beantworten, http://stackoverflow.com/questions/24486729/uiimage-masking-with-gesture –

Antwort

12

Sie können die Maske in einer Zeile anzuwenden, ohne die teueren if mit:

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

Oder besser, nur zwischen zwei Farben interpolieren:

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

In diesem Fall wird die Maske geglättet werden kann (dh mit Gaußscher Unschärfe), um weniger Aliasing zu erzeugen. Dies führt zu sehr guten Ergebnissen im Vergleich zu einem Schwellenwert mit einem einzigen Wert.

+0

Muss ich Multipass verwenden, um eine verschwommene Maske zu erstellen? Oder Sie schlagen vor, die Unschärfe mit demselben Shader zu erstellen? – MatterGoal

+2

Sie können eine Unschärfe mit demselben Shader erstellen, indem Sie mehrere (d. H. 5) Texturabholungen durchführen und das Ergebnis mitteln. Dann verwende diesen Durchschnittswert anstelle von "vMask.r". –

+2

Hier finden Sie eine Implementierung einer Gauß-Unschärfe in einem Fragment-Shader: http://xissburg.com/faster-gaussian-blurin-in-glsl/ –

1

Es gibt keine Notwendigkeit für mehrere Shader oder Framebuffer, nur mehrere Textureinheiten. Verwenden Sie einfach 3 Textureinheiten, die alle mit denselben Texturkoordinaten indiziert sind, und verwenden Sie die Maskentextur, um zwischen den beiden anderen Texturen zu wählen. Das Fragment-Shader würde wie folgt aussehen:

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

Sie können sehen, dass eine dritte Textureinheit mit nur einem binären Test auf dem roten Kanal zu tun, ist nicht sehr effizient, so wäre es besser, die Maske in die codieren Alpha-Kanäle von Texturen 1 oder 2, aber dies sollte Ihnen den Anfang machen.

+0

Schlagen Sie vor, bestimmte Einstellungen auf die Szene anzuwenden, um ein perfektes Ergebnis zu erhalten? Bei manchen "nichtlinearen" Masken bekomme ich ein schreckliches Endergebnis. – MatterGoal

+2

OpenGL liefert zwar keine pixelgenauen Ergebnisse, aber Sie können die Qualität verbessern, indem Sie die Abmessungen der Texturen erhöhen. Verwenden Sie für glTexParameteri() GL_LINEAR für MAG_FILTER und MIN_FILTER. MIP_MAP hilft nur beim Herunterskalieren. – ClayMontgomery