5

私が間違っていることを説明してください。3D モデルを自己コード化された opengl レンダー (v 3.3) にロードし、頂点シェーダーを使用して X 線効果のように透明にしようとしました。

#version 330

attribute vec3 coord3d;
attribute vec2 texcoord;
varying vec2 f_texcoord;

uniform mat4 projectionMatrix; 
uniform mat4 modelViewMatrix; 

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec4 inColor;

smooth out vec4 theColor;

void main()
{
    gl_Position = projectionMatrix*modelViewMatrix*vec4(inPosition, 1.0);
    theColor = vec4(0.0,0.2,0.4,0.4);
    f_texcoord = texcoord;

}

モデルはエディターで三角測量され、次のように描画されます。

glDrawArrays(GL_TRIANGLE_FAN, 0, (vertices.at(i)->size()/3));

私が使用する場合

glEnable(GL_ALPHA_TEST);
glEnable( GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0); 

不要な三角形または線が表示されます。

深度テストなしでそれを行うと、顔の内側に複数の三角形が表示されます(これは望ましくありません):

不要な効果を取り除き、Google Sketchup のように X 線効果を実装するにはどうすればよいですか

すべてのモデルを透明にしたい場合、深度ソートを実装する必要がありますか?

どうすればこれを実装できますか:

GS

4

2 に答える 2

10

問題 1:

まず、深度テストを無効にしないでください。ブレンドが有効な場合でも、フラグメントが正しくドロップされることを確認するために、ブレンドの前に深度テストが実行されます。フラグメントごとの操作とそれらが実行される順序の詳細については、コア OpenGL 4.4 仕様のセクション 17.3を参照してください。

深度テストを無効にすると、描画呼び出しの順序が完全に正しい場合を除き、予期しない結果が得られるため、深度バッファリングの本来の目的に反します。また、順序を正しく設定したとしても、すべての副作用がなくなるとは期待できず、すべてのコマンドを必要な順序で並べようとしても、最も単純なプログラム以外では機能しません。

次の非常に単純な例を考えてみましょう。

ここに画像の説明を入力

通常の tex 座標空間 (s,t E [0, 1]) を視覚化する最も遠い 3 つのクワッド、後者とブレンドする青いクワッド、および前面にあるはずの不透明な赤いクワッドが表示されます。明らかに、赤いクワッド前面にありませんが、深度値はそうでないことを示しています。また、明らかなように、意図は青いクワッドと赤いクワッドをブレンドしないことです。青い四角形の後に赤い四角形をレンダリングすると問題が解決したように見えますが、青と赤の四角形の両方の背後にあるはずの別の四角形を描画すると、深度テストが無効になっていて、単に上に表示されます。これはすべて間違っています。

ここに画像の説明を入力

黄色のクワッドは、赤と青のクワッドの背後にあるはずですが、すべてを覆い隠しています。正しい画像は次のとおりです。これは、純粋に深度テストを有効にすることによって取得されます。

ここに画像の説明を入力

私の一般的な提案は次のとおりです。たとえば、オーバーレイをレンダリングし、深度バッファーに煩わされたくない場合など、深度テストを無効にする非常に正当な理由がない限り、深度テストを有効のままにしてください。

注:デプス バッファリングでは、正しい結果を得るために不透明でないジオメトリを前後に配置する必要があるという問題は解決しません。透明性をシミュレートしようとするときに順序から完全に独立したい場合は、順序に依存しない透明性に関する多くの論文の中から通常の疑わしいものを探してください。

問題 2:

見た目から、次のブレンド関数を使用していると思います。

gl::BlendFunc (gl::ONE, gl::ONE);

または、次のような値の安定した連続的な蓄積につながるもの

gl::BlendFunc (gl::SRC_ALPHA, gl::ONE);

RGB およびアルファ コンポーネントのデフォルトのブレンド式:

gl::BlendEquation (gl::FUNC_ADD);

そうでない場合は、アドバイスを再確認して編集できるように、実際の値を記載したコメントを追加してください。色は嘘をつかないので、以下は依然として適用されます。;)

2番目の問題は、投影下でのzファイティングによるものです。一部のフラグメントは正しく破棄されますが、そうでないものもあります。いくつかの場所で正確に一致する重複面があることは明らかであるため、1 つのフラグメントについて、最初の面に対してわずかに高い深度値が生成される可能性があります。2 番目の面がレンダリングされると、わずかに低い深度値が生成されてフラグメントが通過し、実際には存在しないはずの場所でオーバードローが発生します。

最初のフラグメントはすでにすべてのマジックを実行しており、ブレンドされた値がフレーム バッファーに書き込まれ、深度値が深度バッファーに書き込まれています。つまり、すべてのテストに合格し、背景とブレンドされた顔のフラグメントが 1 つあります。これは、深度値がわずかに低く、フレーム バッファで既にブレンドされたカラーと再びブレンドされるため、破棄されません。加法混合により、観察した結果が得られます。次の例では、使用したのと同じ色とアルファ値でこのケースを再現しました。

ここに画像の説明を入力

問題 3:あなたのモデルには多くの面が重複しているように見え、一般的に三角測量はひどく見えます。本当にやり直したほうがいいです。ブレンディングを理解して使用することは、そのままでは十分に困難です。最適化されていないデータで複雑にしないでください。

于 2013-09-19T15:23:50.587 に答える
0

透明なオブジェクトをレンダリングする一般的な手順は次のとおりです。

  1. 不透明なオブジェクトを描く
  2. 深度マスクを false に設定します。glDepthMask(GL_FALSE);
  3. 透明な三角形を後ろから前に並べ替えます。
  4. この順番で透明化します。
  5. 深度マスクを true に設定します。glDepthMask(GL_TRUE);

これは、正確な結果が確実に得られる唯一の方法です。残念ながら、深度ソートは複雑で時間がかかります。場合によっては、スキップしても「十分」な結果が得られることがあります。また、順序に依存しない透過性を実現する手法もあり、かなり良い結果が得られます。

あなたの場合、深さの並べ替えは避けられないようです。

編集:透明なオブジェクトを描画する場合、深度テストを完全に有効のままにしておくことはできません。これは、描画したものの背後にあるピクセルが上書きされるためです。また、完全に無効にすることもできません。これは、不透明なオブジェクトの背後にある場合でも、透明なオブジェクトを見ることができるためです。解決策は、描画する透明なフラグメントが近くの (不透明な) フラグメントによって遮られているかどうかを引き続き確認することですが、後でチェックされないように透明なフラグメントの深さを保存しないことです。深度値の保存を停止/開始するように OpenGL に指示するために使用されるメソッドはglDepthMask().

于 2013-09-19T20:21:42.280 に答える