2014-06-15 209 views
2

你好,對於問這樣一個具體問題感到抱歉。OpenGL,爲什麼此代碼不能按我的預期工作?

我有以下GLSL頂點着色器:

#version 140 

uniform vec2 viewport_size; 

in vec2 vertex_position; 

in vec2 in_texture_uv; 
varying vec2 texture_uv; 


void main(void) 
{ 
    texture_uv = in_texture_uv; 

    gl_Position = vec4(vertex_position/viewport_size, 0, 1); 
} 

和相應的片段着色器:

#version 140 

uniform sampler2D texture_image; 

out vec4 out_frag_color; 

varying vec2 texture_uv; 


void main(void) 
{ 
    out_frag_color = texture(texture_image, texture_uv); 
} 

產生此輸出(注意左下角的小藍點): output_actual

奇怪的是,如果我替換

texture_uv = in_texture_uv; 

texture_uv = vertex_position; 

輸出變爲:output_vertpos(注意在底部和左側的邊界)。

最後,如果我寫:

texture_uv = vertex_position; 
texture_uv = in_texture_uv; 

輸出是正確的:output_correct,這沒有任何意義,我...

有人能解釋爲什麼這種事情發生?謝謝你的時間!


相關代碼片段:

float[] positionVboData = new float[] { 
    // X  Y  U  V 
    0.0f, 0.0f, 0f,  0f, 
    50.0f, 0.0f, 1f,  0f, 
    50.0f, 25.0f, 1f, .5f, 
    0.0f, 50.0f, 0f,  1f, 
}; 

// vertices 
GL.GenBuffers(1, out verticesHandle); 
GL.BindBuffer(BufferTarget.ArrayBuffer, verticesHandle); 
GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw); 

// vertices: vertex_position 
GL.EnableVertexAttribArray(0); 
GL.BindAttribLocation(program, 0, "vertex_position"); 
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, sizeof(float)*4, 0); 

// vertices: texture_uv 
GL.EnableVertexAttribArray(1); 
GL.BindAttribLocation(program, 1, "in_texture_uv"); 
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float)*4, sizeof(float) * 2); 

質地:

sample_texture

+1

我不認爲這應該是問題,但你應該避免混合'變化'/'屬性'(_deprecated_)和'in' /'出' –

+0

好吧,我只是試圖用「出「在頂點着色器中,並在片段着色器中使用」in「。 沒有變化。 –

+1

你想用'vertex_position/viewport_size'完成什麼?這不是轉換爲窗口空間的正確方法。 –

回答

2

你的主要問題是最有可能是您的BindAttribLocation()通話來得晚:

GL.BindAttribLocation(program, 0, "vertex_position"); 
... 
GL.BindAttribLocation(program, 1, "in_texture_uv"); 

我們沒有看到你在哪裏以及如何構建着色器程序,但是基於上下文,我懷疑你已經在此時構建了着色器程序。在連接着色器程序之前,您需要調用BindAttribLocation()調用。否則這些位置將不會生效。

如果將着色器版本增加到330還可以,則還可以使用layout (location=...)指令在着色器代碼本身中指定頂點着色器輸入的位置。

+0

非常感謝,你解決了一個讓我的頭痛一整天的問題! –

+0

請注意,即使着色器版本爲「150」,某些平臺(即OSX)也具有'GL_ARB_explicit_attrib_location'擴展名,以便您可以使用'layout(location = ...) –

3

需要一個比我在評論更多的空間......


假設GL.Viewport實際上是glViewport的包裝,然後

GL.Viewport(-Width, -Height, Width*2, Height*2) 

沒有什麼意義,因爲它會將3/4視口帶到窗口外部。 只需通過(0, 0, width, height)即可在整個窗口上繪畫,0,0位於左下角。如果要限制GL輸出到窗口的子集,請相應地調整參數。

技術上,glViewport定義標準化設備座標窗口座標轉化爲X和Y,瞭解OpenGL的空間是很重要的。花點時間吧。

剛纔說過,頂點着色器的輸出也很奇怪。如果你想與你的polygon¹以「填補你的窗口」,你不需要做怪

vertex_position/viewport_size 

師在你的頂點着色器。

請記住,在剪輯中的頂點着色器輸出座標,在這之後的OpenGL帶來規格化設備座標的通過將X座標,Y,Z由W.歸一化裝置在所有三個座標範圍從-1到1尺寸。只落在這個2x2x2立方體內的點將被實際光柵化。

還記得我說的關於glViewport

那麼,有什麼訣竅?只需輸出W = 1的座標,以便它們已經在NDC中有效。所以,如果你想有一個四邊形在由GL繪製你的窗口的整個區域跨越,只是建立類似

float coords[] = { -1, -1, 
        1, -1, 
        1, 1, 
        -1, 1 }; 

或者,根據您的原代碼,如果你想有一個梯形,使用類似

float coords[] = { -1, -1, 
        1, -1, 
        1, 0, 
        -1, 1 }; 

然後通過頂點着色器將它們傳遞:

in vec2 position; 

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

結果:

result


¹請,請即是GL_TRIANGLE_FAN,而不是一個GL_QUAD也不是GL_POLYGON

+0

'假設GL.Viewport實際上是glViewport的包裝器是的,我使用託管代碼,但是包裝是直接的。 我正在使用這些數字,因爲我來自喜歡整數而不是浮動的軟件圖形界面,而且我實際上只希望該圖像只有50px寬。 我會將這些計算委託給GPU,並避免無效的'uniform vec2 viewport_size;'然後。 感謝您的好解釋! –

相關問題