2016-04-13 9 views
1

ここ数日、私は特にトリッキーなバグに遭遇しました。私は自分のコードを非常に単純で直接的な例にまで減らしました。予期せぬテクスチャ座標の補間 - 処理+ GLSL

これは私が私のシェーダを呼び出すために使用する処理コードです:ここで

PGraphics test; 
PShader testShader; 
PImage testImage; 

void setup() { 
    size(400, 400, P2D); 
    testShader = loadShader("test.frag", "vert2D.vert"); 
    testImage = loadImage("test.png"); 
    testShader.set("image", testImage); 
    testShader.set("size", testImage.width); 
    shader(testShader); 
} 

void draw() { 
    background(0, 0, 0); 
    shader(testShader); 
    beginShape(TRIANGLES); 
    vertex(-1, -1, 0, 1); 
    vertex(1, -1, 1, 1); 
    vertex(-1, 1, 0, 0); 
    vertex(1, -1, 1, 1); 
    vertex(-1, 1, 0, 0); 
    vertex(1, 1, 1, 0); 
    endShape(); 
} 

は、私の頂点シェーダです:

attribute vec2 vertex; 
attribute vec2 texCoord; 
varying vec2 vertTexCoord; 
void main() { 
    gl_Position = vec4(vertex, 0, 1); 
    vertTexCoord = texCoord; 
} 

私は、このフラグメントシェーダを呼び出すとき:

uniform sampler2D image; 
varying vec2 vertTexCoord; 
void main(void) { 
    gl_FragColor = texture2D(image, vertTexCoord); 
} 

私はこれを得る:
enter image description here
これは予期した結果です。私はレンダリングするときただし、テクスチャではなく、次のフラグメントシェーダで赤と緑のチャンネルに座標:

uniform sampler2D image; 
uniform float size; 
varying vec2 vertTexCoord; 
void main(void) { 
    gl_FragColor = vec4(vertTexCoord, 0, 1); 
} 

私はこの取得:大半、あなたが見ることができるよう

enter image description here

を画面の黒は、これらのフラグメントでは、テクスチャ座標が[0、0]であることを示します。ただし、texture2D関数に渡されたときに、画像内の対応する位置に正しくマッピングされるため、これは当てはまりません。これらの両方のケースでテクスチャ座標の正確な値が同じであることを確認するために、それらを次のシェーダと組み合わせました。

uniform sampler2D image; 
uniform float size; 
varying vec2 vertTexCoord; 
void main(void) { 
    gl_FragColor = texture2D(image, vertTexCoord) + vec4(vertTexCoord, 0, 0); 
} 

は、これが生産:
テクスチャ座標がスムーズに行った場合、あなたが期待する正確に何である enter image description here

は、画面ごとに異なります。だから私は完全に黒いイメージを試みました、このバリエーションを顔なしでもっとはっきりと見たいと思っていました。私がこれをしたとき、私は再び2つの三角形でイメージを得ました。いくつかのより多くのそれで遊んでた後、私は左上の画素を除いて透明完全に黒のイメージを持っている場合は、私が得ることが判明し、この:最後に私が期待される画像である

enter image description here

滑らかに変化する座標。これは完全に私を困らせました。なぜテクスチャルックアップは正しく動作しますが、実際の座標をレンダリングすると私はほとんど迷惑になりますか?

編集:
私が投稿した解決策を見つけましたが、なぜ最初にバグが存在するのかまだ分かりません。私は興味深いテストケースに出くわしました。これはなぜこれが起こっているのかについてもう少し詳しい情報を提供するかもしれません。

フラグメントシェーダ:

varying vec2 vertTexCoord; 
void main(void) { 
    gl_FragColor = vec4(vertTexCoord, 0, 0.5); 
} 

結果:
enter image description here

+0

あなたはgfxカードとドライバを持っていますか(ドライバ側のバグか「機能」)? 'size'は何のためですか?テクスチャへのアクセスを使用しないときに、ドライバがテクスチャ座標のいくつかの補間を最適化するのが私の賭けです。フレーク座標が助けになると '0,0'ならば' texture2D(image、vertTexCoord) 'を使ってください。 – Spektre

+0

以前のいくつかのテストで、同じ動作をしていたかどうかを調べるために、texCoordsの代わりにgl_FragCoord/sizeを使用していました。私はそれを残して、それらのテストの間で4位と4位を切り替えて比較することができました。私はあなたの例とそれの他のバリエーションを試して、私はまだ2つの三角形でイメージを得ました。私は、しかし、私が投稿した特に困惑の解決策を見つけました。バグの原因がProcessingの内部APIにあり、GLSLではないことを示しているようですが、バグの性質がパイプラインの途中でどのように変化するかはわかりません。 –

答えて

0

私は2つの異なる解決策を発見しました。両方とも処理コードの変更を伴います。私はこれらの変更がどのように、なぜそれを動作させるのか、全く知らない。

解決策1:
画面スペースをダウン渡しクリップ空間座標の代わりに座標と頂点シェーダでクリップ空間にそれらを変換する処理によって生成された変換行列を使用します。
処理コード:

PGraphics test; 
PShader testShader; 
PImage testImage; 

void setup() { 
    size(400, 400, P2D); 
    testShader = loadShader("test.frag", "vert2D.vert"); 
    testImage = loadImage("test.png"); 
    testShader.set("image", testImage); 
    testShader.set("size", testImage.width); 
    shader(testShader); 
} 

void draw() { 
    background(0, 0, 0); 
    shader(testShader); 
    beginShape(TRIANGLES); 
    //Pass down screen space coordinates instead. 
    vertex(0, 400, 0, 1); 
    vertex(400, 400, 1, 1); 
    vertex(0, 0, 0, 0); 
    vertex(400, 400, 1, 1); 
    vertex(0, 0, 0, 0); 
    vertex(400, 0, 1, 0); 
    endShape(); 
} 

バーテックスシェーダ:

attribute vec2 vertex; 
attribute vec2 texCoord; 
uniform mat4 transform; 
varying vec2 vertTexCoord; 
void main() { 
    //Multiply transform matrix. 
    gl_Position = transform * vec4(vertex, 0, 1); 
    vertTexCoord = texCoord; 
} 

結果:
enter image description here
お知らせ画面の中央を通る線。これは、処理コード内でnoStroke()を呼び出していないためです。それでも、テクスチャ座標は適切に補間されます。

解決方法2:
私達はちょうどセットアップでnoStroke()を呼び出した場合、我々はクリップ空間を渡すことができますが何の問題もなくダウン座標と予想されるようにすべてが正確に動作します。シェーダの変更は必要ありません。

PGraphics test; 
PShader testShader; 
PImage testImage; 

void setup() { 
    size(400, 400, P2D); 
    //Call noStroke() 
    noStroke(); 
    testShader = loadShader("test.frag", "vert2D.vert"); 
    testImage = loadImage("test.png"); 
    testShader.set("image", testImage); 
    testShader.set("size", testImage.width); 
    shader(testShader); 
} 

void draw() { 
    background(0, 0, 0); 
    shader(testShader); 
    beginShape(TRIANGLES); 
    vertex(-1, -1, 0, 1); 
    vertex(1, -1, 1, 1); 
    vertex(-1, 1, 0, 0); 
    vertex(1, -1, 1, 1); 
    vertex(-1, 1, 0, 0); 
    vertex(1, 1, 1, 0); 
    endShape(); 
} 

結果:
enter image description here
かなり簡単に修正。この変更がどのようにして、テクスチャ座標が補間されるか、またはフラグメントシェーダで補間されないかに影響するように管理する方法は、私を超えています。

これらのバグがなぜ存在するのかについての洞察を持っている可能性があるOpenGLを処理する方法をもう少し詳しく知っている人なら、私は知りたいと思うでしょう。

関連する問題