2017-06-03 68 views
2

我正在用OpenGL進行以下操作。我的屏幕尺寸爲512 * 512。我有一個與屏幕尺寸相同的紋理。我想繪製一個覆蓋整個屏幕的四邊形,並在像素和紋理元素之間建立一對一映射,以便我可以在着色器中使用屏幕座標texelFetchOpenGL中紋理像素和屏幕像素之間的一對一映射

首先,如果我設置類似下面的四邊形的四角:

(-1, 1)+-----------+(1,1) 
     |   | 
     |   | 
     |   | 
     |   | 
     |   | 
(-1,-1)+-----------+(1,-1) 

,並設置其對應的紋理座標爲:

(0,511)+-----------+(511,511) 
     |   | 
     |   | 
     |   | 
     |   | 
     |   | 
(0, 0)+-----------+(511,0) 

我只是用下面的代碼片段有一個白色屏幕着色器,它試圖爲其四個邊界分配不同的顏色:

#version 330 

in vec2 fUV;        // sent from vertex shader 

out vec4 color; 

void main() { 
    if (fUV.x == 0)      // leftmost 
     color = vec4(1.0, 0.0, 0.0, 1.0); 
    else if (fUV.y == 0)     // bottom 
     color = vec4(0.0, 1.0, 0.0, 1.0); 
    else if (fUV.x == 511)    // rightmost 
     color = vec4(0.0, 0.0, 1.0, 1.0); 
    else if (fUV.y == 511)    // top 
     color = vec4(1.0, 0.0, 1.0, 1.0); 
    else         // otherwise 
     color = vec4(1.0, 1.0, 1.0, 1.0); 

    // check if uv equals an integer 
    if (fUV.y == 100) 
     color = vec4(0.0, 0.0, 0.0, 1.0); 
} 

這意味着所有的平等測試都失敗了。

其次,如果我添加一個半像素寬度偏移d= 1.0/512所有-1座標:

(-1+d, 1)+-----------+(1,1) 
      |   | 
      |   | 
      |   | 
      |   | 
      |   | 
(-1+d,-1+d)+-----------+(1,-1+d) 

保持其他事情不變,我在屏幕上繪製的最左邊的紅線。

我得到的上述結果非常混亂。爲什麼只有最底部的一列沒有被繪製出來?

我想知道我應該如何繪製一個四邊形並設置它們的座標,以便我可以建立像素與像素之間的一對一映射。

+0

您不應該使用'=='運算符進行浮點比較。使用'abs(fUV.x - 511)<0.001' –

回答

2

你誤解像素爲點。默認情況下,OpenGL將它們視爲在中心處具有半整數座標的正方形。這意味着,如果你提交如下紋理座標:

(0,511)+-----------+(511,511) 
     |   | 
     |   | 
     |   | 
     |   | 
     |   | 
(0, 0)+-----------+(511,0) 

然後在屏幕右下角的片段座標(511, 0)將在(511.5, 0.5)進行採樣,並且將得到紋理座標進行插值給(510.501, 0.499023)

有幾種方法可以實現您的目標。

  1. 使用下面的紋理座標和截斷:

    (0,512)+-----------+(512,512) 
         |   | 
         |   | 
         |   | 
         |   | 
         |   | 
    (0, 0)+-----------+(512,0) 
    

    現在在(511.5, 0.5)插值座標給出(511.5, 0.5),並截斷爲整數給人(511, 0),這是texelFetch像素的座標。使用gl_FragCoord.xy代替紋理座標。它包含與先前項目中的插值紋理座標相同的數字。

  2. 使用標準化的[0,1]紋理座標和texture而不是texelFetch進行查找:

    (0,1)+-----------+(1,1) 
        |   | 
        |   | 
        |   | 
        |   | 
        |   | 
    (0,0)+-----------+(1,0) 
    

    如果你的視口是完全一樣大小的紋理,然後這將建立一個精確映射像素和紋素之間。

    這種方法是最靈活的,我強烈推薦給其他人。