2016-10-25 9 views
2

出力の各ピクセルに対して計算が行われ、シェーダパイプラインの以前のステップから渡されたデータが使用されます。この計算をフラグメントシェーダで実行するのが最も理にかかります。私が最も簡単な例で始めたかどうかは、各プリミティブのピクセル数をカウントするだけです。あなたはそれだけで、シェーダ記憶バッファオブジェクトの要素をインクリメント見ることができるように可視ピクセル専用のフラグメントシェーダを実行

#version 430 
layout(early_fragment_tests) in; 

out vec4 out_color; 

layout(std430, binding = 3) buffer out_data { 
    int data[]; 
}; 

void main() {{ 
    atomicAdd(data[gl_PrimitiveID], 1); 
    out_color = vec4(1, gl_PrimitiveID, 0, 1); 
}} 

#version 430 
in vec3 position; 

void main() {{ 
    gl_Position = vec4(position, 1); 
}} 

とフラグメントシェーダ:頂点シェーダ - これは2つだけのシェーダが必要です。

次に、2つの三角形(6点)を入力します:[-1, -1, 0], [-1, 1, 0], [1, 1, 0], [-1, -1, 0], [1, -1, 0], [-1, 1, -1]。赤い三角形と緑色の三角形が正しく表示されますが、それぞれがウィンドウの半分を占めていますが、緑の三角形が上にあるため、赤い三角形の半分(ウィンドウの1/4)しか表示されません。

もちろん、赤い三角形の場合はウィンドウサイズの1/4、緑色の場合は約1/2になると予想されましたが、それらは両方とも1/2に等しいです! Btw、すべての入力Z座標をゼロに設定すると、赤い三角形が一番上にあり、緑色が半分隠されています。この場合、カウントは正しいです。

OpenGLドキュメント(私がオプションearly_fragment_testsを見つけたところ)を読んでいるうちに、何らかの理由で破棄された断片(例えば、私の場合のように深度テスト)がアトミックカウンタとSSBOに影響しないことを理解しました - hereを参照してください。しかし私の例が示すように、彼らは明らかにそれらに影響を与えます!問題を解決できるものは他にありますか?

これが重要なのであれば、Intel Skylake iGPU、OpenGL 4.3を使ってLinux上で実行しました。

+0

深度テストが正常に機能していますか? (深度テストを有効にし、書き込みマスクなし、深度関数は正常です...)これは、三角形のZ値を変更し、上三角形が変化するかどうかを調べることで確認できます。どのZ値を使用していますか?両方の三角形にまったく同じ値を使用すると、問題が発生する可能性があります。これが原子カウンタを変更するかどうかを確認するためにフラグメントを手動で破棄しようとしましたか? – dv1729

+1

どのような順序で三角形を描いていますか?赤とそれに続いて緑を描画すると、レンダリングされた時点で赤い三角形が完全に表示されるため、結果は驚くことではありません。 – BDL

+0

私は、2つの三角形(6点)でシェーダーにフィードすると言いました - そして、私はDrawArraysを一回呼び出すだけでこれを行います。 – aplavin

答えて

3

別々の三角形からフラグメントを処理する順序は、ほとんど定義されていません。初期のフラグメントテストでは、各三角形のフラグメントをラスタライザ順に処理する必要はありません。 OpenGLは大部分が "as-if"ルールの下で動作しますが(つまり、すべてが "そのまま"そのまま処理されます)、Image Load/StoreとSSBOメモリアクセスのインコヒーレントな性質は、注文処理。

作業のバッチを発行し、FSが各フラグメントに対して1回だけ実行されるようにするには、深さのプレパスを実行する必要があります。まず、シーンをレンダリングしますが、FSはまったく使用しません。つまり、書き込まれるのは深さの値だけです。次に、シーンを通常どおりにレンダリングします。

これらのうちの2つの間には、第1パスのすべての三角形が第2パスの開始前に確実に終了するような何らかの形の同期が必要です。残念なことに、OpenGLにはそれを求める良い方法がありません。 use a fence sync object with glWaitSyncでも可能ですが、それには明示的に安価ではないglFlushコールが必要です。

関連する問題