2

ポイントスプライトを(iOSでOpenGL ES 2.0を使用して)ユーザーの描画ストロークとしてレンダリングしています。これらのポイントを頂点バッファオブジェクトに保存しているので、スプライトが描画に送信されたときに正しい順序で表示されるように、深度テストを実行する必要があります。

次のスクリーンショットに示すように、これらの描画ストロークをレンダリングすると、奇妙な効果が見られます。

ポイントスプライトブレンディングの問題

青のストロークの端の周りの背景色の「境界線」に注意してください。ここでは、緑の上に描画されています。ユーザーは緑のストロークの後に青のストロークを描画しましたが、VBOが再描画されると、青のストロークが最初に描画されます。緑のストロークを描くことになると、深度テストが開始され、青のストロークの後ろにあるはずであることがわかります。これもある程度の成功を収めています。ある種のブレンディングの問題であるように見えますか、それともフラグメントシェーダーで色を誤って計算することに関係していますか?すべてのストロークのエッジは透明である必要がありますが、フラグメントシェーダーは、それらのフラグメントを処理するときに、それを背景テクスチャと組み合わせているように見えます。

私のアプリでは、深度レンダーバッファーを作成し、glEnable(GL_DEPTH_TEST)を使用して呼び出しましたglDepthFunc(GL_LEQUAL)glDepthMask()私は無駄に実験しました。ブレンディングはに設定されglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)、ポイントスプライトカラーは事前に乗算されたアルファ値を使用します。描画ルーチンは非常に単純です。

  • レンダリングからテクスチャへのFBOをバインドします。
  • 背景テクスチャを描画します。
  • (多数のVBOから)ポイントスプライトを描画します。
  • このFBOのテクスチャをメインフレームバッファに描画します。
  • メインフレームバッファを提示します。


編集

これが描画ルーチンからのコードです。

描画前のセットアップ状態:

glDisable(GL_DITHER);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

描画ルーチン:

[drawingView setFramebuffer:drawingView.scratchFramebuffer andClear:YES];
glUseProgram(programs[PROGRAM_TEXTURE]);
[self drawTexture:[self textureForBackgroundType:self.backgroundType]];

glUseProgram(programs[PROGRAM_POINT_SPRITE]);

// ...
// Draw all VBOs containing point sprite data
// ...

[drawingView setFramebuffer:drawingView.defaultFramebuffer andClear:YES];
glUseProgram(programs[PROGRAM_TEXTURE]);
[self drawTexture:drawingView.scratchTexture];

[drawingView presentFramebuffer:drawingView.defaultFramebuffer];

助けてくれてありがとう。

4

1 に答える 1

4

不透明でないジオメトリを描画する場合は、それらを後ろから前にzソートする必要があります。これは、長年にわたって適切なブレンドを行う唯一の方法です。最近では、Dual Depth Peelingのように順序に依存しない透明性のためのアルゴリズムがいくつかありますが、それらはiOSには適用できません。

于 2011-09-22T16:36:26.050 に答える