2013-08-31 9 views
8

私はOpenGL ES 2.0を学んでいます。その仕組みを理解するために、アプリケーションを作成したいと思います。 このアプリには、ユーザーが画像に適用できるフィルタのセットがあります(私は知っていますが、新しいものはありません:P)。このフィルタのOpenGL ES 2.0での画像とマスク

一つは、2枚の画像とマスクを取り、それは現時点では

enter image description here

を(より良い私が取得したいかを説明するためにここに画像)マスクを介してそれらを示す2枚の画像をミックス私は本当に混乱しており、どこからこの効果を生み出すのか分かりません。 私は複数のテクスチャと複数のFrameBuffersで作業する必要があるか、単一のシェーダでしか作業できないことは理解できません。

このプロジェクトで私を助けるヒントはありますか?

EDITは--------

私はこの解決策を見つけたが、私は代わりに、円のマスクラインとして使用する場合、結果はラインが回転している場合は特に、本当に「汚い」です。

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

ステンシルバッファまたはブレンドを使用する方が良いでしょうか?

+3

ところで、アルファ( 'mask_color.a')チャンネルをマスクとして使う必要はありません。あなたは他の 'r'、' g'、 'b'チャンネルを使うことができます。この方法でアルファチャンネルなしのマスクテクスチャを使ってGPUメモリを節約します。 – keaukraine

+0

@MatterGoalあなたはこの質問に答えることができるかもしれません。http://stackoverflow.com/questions/24486729/uiimage-masking-with-gesture –

答えて

12

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

または、より良いをちょうど2つの色の間を補間:

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

この場合、マスクは平滑化することができます(すなわち、ガウスぼかしで)エイリアシングを少なくします。これは、単一値の閾値化と比較して非常に良好な結果をもたらす。

+0

私はぼかしマスクを作成するためにマルチパスを使用しましたか?あるいは、同じシェーダーでブレを作成することを提案していますか? – MatterGoal

+2

複数の(つまり5つの)マスクテクスチャフェッチを行い、結果を平均化することで、同じシェーダでブラーを作成できます。次に、 '' vMask.r''の代わりにこの平均値を使用します。 –

+2

ここでは、ガウスブラーの実装をフラグメントシェーダで見つけることができます:http://xissburg.com/faster-gaussian-blur-in-glsl/ –

1

複数のシェーダやフレームバッファ、複数のテクスチャユニットは必要ありません。 3つのテクスチャユニットを使用して、すべて同じテクスチャ座標でインデックスを作成し、マスクテクスチャを使用して他の2つのテクスチャを選択します。あなただけのレッドチャンネルでバイナリのテストを行うために第三のテクスチャユニットを使用することは非常に効率的ではないので、にマスクをエンコードする方が良いだろうことがわかります

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

:フラグメントシェーダは次のようになります。テクスチャ1または2のアルファチャンネルが表示されますが、これを開始する必要があります。あなたは高価なifを使用せずに1行でマスクを適用することができます

+0

完璧な結果を得るためにシーンに特定の設定を適用することをお勧めしますか?いくつかの「非線形」マスクでは、ひどい最終結果が得られます。 – MatterGoal

+2

OpenGLは特にピクセル完全な結果を提供しませんが、テクスチャのサイズを増やすことによって品質を向上させることができます。 glTexParameteri()の場合は、MAG_FILTERとMIN_FILTERにGL_LINEARを使用します。 MIP_MAPは、縮小する場合にのみ役立ちます。 – ClayMontgomery