5

フラットな色とテクスチャをWebGLキャンバスに描画しています。私の色とテクスチャにはさまざまなアルファ値があり、正しくブレンドする必要があります。背景を透明にしたい(キャンバスの下にあるHTMLコンテンツとブレンドする必要があります)。

WebGLでは、

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

HTMLの背景が黒の場合、正しく機能します。しかし、JPGパターンを背景として設定すると、黒い三角形(alpha = 1)と白い三角形(alpha = 0.5)を描画すると、三角形が交差する場所に背景パターンが表示されます。これは正しい動作ですか?

4

1 に答える 1

15

gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)結果のアルファが

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

あなたの例では、黒い三角形(alpha = 1)が描画された後、フレームバッファに描画されたピクセルのアルファは

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

したがって、完全に不透明になります。次に、白い三角形(alpha = .5)が描画された後、2つの三角形の交点にあるピクセルのアルファは

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

つまり、最終的な色は部分的に透明として扱われ、ページと合成されると、ページの背景が透けて見えます。

コンテンツは通常、空の背景に対して合成されるため、これは通常のOpenGLではややまれな問題です。ただし、FBOに描画し、その結果をコンテキスト内の他のコンテンツと合成する必要がある場合に発生します。これに対処する方法はいくつかあります。

1つの方法は、アルファをとブレンドするgl.ONEことgl.ONE_MINUS_SRC_ALPHAです。

A_final = A_s + (1 - A_s) * A_d

これは、アルファブレンディングで通常必要なものです。gl.SRC_ALPHAただし、色を、とブレンドする必要がありますgl.ONE_MINUS_SRC_ALPHA。カラーブレンディング関数とアルファブレンディング関数を別々に設定する代わりに、gl.blendFuncSeparateを使用できます。gl.blendFuncこの場合、あなたは

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

もう1つのオプションは、アルファが事前に乗算された色を利用することです( WebGLは、たとえば、テクスチャから色をサンプリングするときに、実際に使用していると想定しています)。アルファがすでに色に掛けられた状態で2番目の三角形を描画する場合(つまり、半分透明な白い三角形がにgl_FragColor設定されているvec4(.5, .5, .5, .5)場合)、ブレンドモードを使用できます。

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

そしてそれはあなたが色とアルファの両方のために望むように機能します。

2番目のオプションは、WebGLの例でよく見られるものです。これは、(前述のように)WebGLはすでに色が事前に乗算されていると想定しているためvec4(1., 1., 1., .5)です(つまり、色域外であり、レンダリング出力は未定義であり、ドライバー/ GPUは任意のクレイジーカラーを出力できます)欲しい)。通常のOpenGLの例で見られるのははるかに一般的gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)であり、混乱を招きます。

于 2012-07-18T02:15:20.443 に答える