2012-01-16 6 views
5

FBOでテクスチャにレンダリングされるシーンがあり、フルスクリーンクワッドを描画するのではなくプリミティブを使用して領域を描画するフラグメントシェーダからサンプリングしています。私は必要な断片を生成するだけでリソースを節約しています。レンダリングされたFBOへのテクスチャルックアップがピクセル単位でオフになっています

これをテストするには、テクスチャレンダリングと全く同じジオメトリを発行しています。つまり、作成されたラスタライズパターンはまったく同じでなければなりません。私のフラグメントシェーダが、それが与えられた他の値と完全に一致するはずです。ここで

は、私は、自動テクスチャに私のフラグメントシェーダ私のフルスクリーンテクスチャを持つジオメトリを座標を与えている方法は次のとおりです。

// Vertex shader 
uniform mat4 proj_modelview_mat; 
out vec2 f_sceneCoord; 
void main(void) { 
    gl_Position = proj_modelview_mat * vec4(in_pos,0.0,1.0); 
    f_sceneCoord = (gl_Position.xy + vec2(1,1)) * 0.5; 
} 

私はので、私は透視除算と自分を心配していない2Dで働いていますここに。私はちょうど[-1,1]から[0,1]に縮尺されたクリップスペース位置を使ってsceneCoord値を設定しました。

uniform sampler2D scene; 
in vec2 f_sceneCoord; 
//in vec4 gl_FragCoord; 
in float f_alpha; 
out vec4 out_fragColor; 
void main (void) { 
    //vec4 color = texelFetch(scene,ivec2(gl_FragCoord.xy - vec2(0.5,0.5)),0); 
    vec4 color = texture(scene,f_sceneCoord); 
    if (color.a == f_alpha) { 
     out_fragColor = vec4(color.rgb,1); 
    } else 
     out_fragColor = vec4(1,0,0,1); 
} 

注意アルファが一致しない場合は、赤い断片が吐き出されます。テクスチャレンダリングは、各レンダリングされたオブジェクトのアルファを特定のインデックスに設定するので、何が何に一致するかを知ることができます。

申し訳ありませんが表示する画像がありませんが、私のピクセルがオフであることは非常に明確です(0.5,0.5):私のオブジェクトの周りの薄い、赤い境界線をオブジェクトの下側と左側に表示し、でる。それはかなり "一時的な"見た目です。プレゼントは、オブジェクトの下側と左側だけに現れます。

通知texelFetchを使用している行がコメントアウトされています。この方法は機能し、赤い断片が表示されなくなりました。しかし、私はtextureでこれを正常に動作させ、テクスチャ座標を正規化したいと思います。なぜなら、より多くのハードウェアがそれをサポートすると思うからです。おそらく本当の疑問は、制服を通して私のビューポート解像度を送信せずにこの権利を得ることが可能なのでしょうか?それを避ける方法があるはずです!

更新:テクスチャのアクセスを半分ピクセル、ピクセルの1/4、ピクセルの1/100ずつずらしてみましたが、すべてが悪化し、エッジの周りに間違った値の堅い境界線が生成されました。 gl_Position.xy+vec2(1,1))*0.5トリックは正しい値を設定しますが、サンプルは少しだけ何とかオフになります。これは非常に奇妙です...赤い断片を見ますか?オブジェクトが動いているときに、それらは少しでもずっとやりとりします。これは、設定したアルファ値が、それらのピクセルに完全に一致していないことを意味します。

transient red fragments indicate a texture sampling mis-match

私の実際のアプリケーションのためにそのアルファインデックスチェックのためのピクセルの完璧な精度を得ることは重要ではないのですが、この動作は、私が期待したものだけではありません。

答えて

4

まあ、最初screenSizeが均一(多分前分割)された状態で、(すでにあなたの例でこれを持っているが、-0.5がゴミである)f_sceneCoordが変化し、ちょうどテクスチャ座標としてgl_FragCoord/screenSizeを使用していることをドロップすることを検討してください。デフォルトではgl_FragCoordがピクセル中心(意味はi+0.5)にあり、テクセルセンター((i+0.5)/textureSize)でテクスチャをサンプリングするときにOpenGLが正確なテクセル値を返すので、これはほぼ正確に動作するはずです。

これは、有限の精度などに起因して、正確なテクセル値(もしあれば)から非常に非常にわずかな偏差を導く可能性があります。しかし、もう一度、とにかくこのような1対1のテクスチャとスクリーンのマッピングには、GL_NEARESTのフィルタリングモードを使用することをお勧めします。実際にあなたの存在しているf_sceneCoordのアプローチはすでにうまくいくかもしれません。それはアーチファクトを作成するGL_NEARESTによって防止された小さな丸めの問題です。しかし、もう一度、あなたはまだそのf_sceneCoordものは必要ありません。

編集:texelFetchの移植性について。この機能は、GLSL 1.30(〜SM4/GL3/DX10-hardware、〜GeForce 8)で導入されたと私は思う。しかし、このバージョンは、使用している新しいin/out構文(旧式のvarying/attribute構文とは対照的に)で既に必要です。したがって、これらを変更しない場合は、texelFetchを指定した場合は全く問題はなく、texture(GLSL 1.30が必要です(旧texture2Dとは対照的に))より少し速いかもしれません。

+0

...画面の端でランダム丸め誤差を得る:...

私は使用しません。これは問題の解決につながる可能性があります。なぜなら、非常にわずかに異なる精度ベースのエラーでも、私のチェックに失敗する可能性がある線形フィルタリングがどのように見えるかがわかります。私はその最初のチャンスを試すつもりです。 'FragCoord'と画面サイズの統一を使うよりも、私の' f_sceneCoord'ソリューションがより洗練されていることがわかります。それは画面のサイズを一定に保つことが必要な私とは独立しています。 –

+0

私は複数回upvoteできることを望む! upvoteと受け入れをしてください。 –

+0

ええ、私はglslDevilでデバッグしようとしましたが、1.2構文に戻す必要がありましたので、すべてを 'varying/attribute'と' texture2D'に戻しました... glslDevilはまだ私に値を表示しません。とにかく重要でないものは、GL_NEARESTが完璧な結果を生み出しています。私の実際の実装では、GL_LINEARを使用する必要があるので、スムーズに見えるようにする必要がありますが、これを一番下に置いて本当にうれしいです。 –

1

丸め誤差のない完全なX、Y [0,1]で作業している場合は...しかし、特に極座標で作業する場合、計算された座標をテクスチャ 'グリッド'に合わせることを検討することがあります。 GL_NEARESTを育ててくれてありがとうをお守りのような

// align it to the nearest centered texel 
curPt -= mod(curPt, (0.5/vec2(imgW, imgH))); 

作品と私はもはや