2014-06-18 37 views
5

我真的很奇怪的問題,我現在不能pin down。我正在製作一個簡單的每頂點照明,它在Nvidia上正常工作,但不會在AMD/ATI上渲染任何陰影。我追蹤了這個問題與屬性有關 - 特別是顏色屬性。
這是我的頂點着色器:GLSL着色器不適用於AMD/ATI,但適用於NVIDIA

#version 140 
uniform mat4 modelViewProjectionMatrix; 
in vec3 in_Position;     // (x,y,z) 
in vec4 in_Color;     // (r,g,b,a) 
in vec2 in_TextureCoord;    // (u,v) 

out vec2 v_TextureCoord; 
out vec4 v_Color; 

uniform bool en_ColorEnabled; 
uniform bool en_LightingEnabled; 

void main() 
{ 
    if (en_LightingEnabled == true){ 
     v_Color = vec4(0.0,1.0,0.0,1.0); 
    }else{ 
     if (en_ColorEnabled == true){ 
     v_Color = in_Color; 
     }else{ 
     v_Color = vec4(0.0,0.0,1.0,1.0); 
     } 
    } 
    gl_Position = modelViewProjectionMatrix * vec4(in_Position.xyz, 1.0); 

    v_TextureCoord = in_TextureCoord; 
} 

這是像素着色器:

#version 140 
uniform sampler2D en_TexSampler; 
uniform bool en_TexturingEnabled; 
uniform bool en_ColorEnabled; 
uniform vec4 en_bound_color; 
in vec2 v_TextureCoord; 
in vec4 v_Color; 
out vec4 out_FragColor; 

void main() 
{ 
    vec4 TexColor; 
    if (en_TexturingEnabled == true){ 
     TexColor = texture2D(en_TexSampler, v_TextureCoord.st) * v_Color; 
    }else if (en_ColorEnabled == true){ 
     TexColor = v_Color; 
    }else{ 
     TexColor = en_bound_color; 
    } 
    out_FragColor = TexColor; 
} 

所以這個着色器允許3個狀態 - 當我使用燈光,當我不使用燈,但使用每頂點顏色和當我使用單一顏色的所有頂點。我刪除了所有的光計算代碼,因爲我將問題追蹤到一個屬性。這是來自着色器的輸出:
Shader with bug 正如你所看到的,一切都是藍色的(所以它呈現所有沒有陰影或顏色的東西(en_LightingEnabled == false and en_ColorEnabled == false))。

當我將這段代碼在頂點着色器:

if (en_ColorEnabled == true){ 
    v_Color = in_Color; 
}else{ 

與此:

if (en_ColorEnabled == true){ 
    v_Color = vec4(1.0,0.0,0.0,1.0); 
}else{ 

我得到如下:
Without in_Color attribute
所以,你可以看到它呈現的一切沒有陰影仍然是藍色,但現在它也渲染了所有使用燈光(en_LightingEnabled == true)的綠色。這是應該的。問題是in_Color屬性不應該干涉燈光,因爲如果啓用燈光,它甚至不會運行。你也可以看到圖像中沒有任何東西是紅色的,這意味着在這個場景中en_ColorEnabled總是false。所以in_Color在這裏完全沒用,但它在邏輯上不應該引起的地方引起錯誤。在Nvidia它工作正常,綠地面積有或沒有in_Color。我是否在使用AMD不支持?我是否在GLSL規範之外使用某些東西?我知道AMD嚴格與GL規範比Nvidia,所以這是可能的,我做了一些未定義。我讓代碼儘可能簡單,但仍然存在問題,所以我沒有看到它。
此外,我注意到如果in_Color頂點屬性被禁用(不是glEnableVertexAttribArray),它將不會在屏幕上繪製任何東西(即使是藍色區域),但是爲什麼?我甚至不使用這種顏色。禁用的屬性需要返回(0,0,0,1)的規格權?我嘗試使用glVertexAttrib4f來改變顏色,但仍然變黑。編譯器和鏈接器不會返回任何錯誤或警告。屬性in_Color在glGetAttribLocation中找到。但正如我所說,這不應該很重要,因爲該分支從未在我的代碼中執行過。有任何想法嗎?

測試Nvidia660Ti和工作正常,在ATImobility radeon HD 5000筆記本電腦上測試,並有此錯誤。我唯一的想法是,也許我超過了GPU(太多屬性等)的功能,但是當我將代碼縮減到這個時候,我不再相信這一點。我在這裏只使用3個屬性。
此外,我的一些朋友測試了更新的AMD卡,並得到同樣的問題。

更新1

頂點屬性綁定像這樣:同樣

if (useColors){ 
    glUniform1i(uni_colorEnable,1); 
    glEnableVertexAttribArray(att_color); 
    glVertexAttribPointer(att_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, STRIDE, OFFSET(offset)); 
}else{ 
    glUniform1i(uni_colorEnable,0); 
} 

,我發現如何顯示怪事更容易 - 利用這個頂點着色器:

void main() 
{ 
    v_Color = clamp(vec4(1.,1.,1.,1.) * vec4(0.5,0.5,0.25,1.),0.0,1.0) + in_Color; 

    gl_Position = modelViewProjectionMatrix * vec4(in_Position.xyz, 1.0); 

    v_TextureCoord = in_TextureCoord; 
} 

所以沒有分支。而我得到這個: Without branching there is still that bug 如果我通過像這樣除去in_Color更改代碼:

void main() 
{ 
    v_Color = clamp(vec4(1.,1.,1.,1.) * vec4(0.5,0.5,0.25,1.),0.0,1.0); 

    gl_Position = modelViewProjectionMatrix * vec4(in_Position.xyz, 1.0); 

    v_TextureCoord = in_TextureCoord; 
} 

我得到這個: Without branching as expected

這最後一個是我所期望的,但前一個沒有按」即使我做加法(+)而不是其他任何東西,也不會畫任何東西。因此,如果attrib未被綁定,並且(0,0,0,0)或(0,0,0,1)被給出,那麼它不應該做任何事情。但它仍然失敗。

此外,所有日誌都是空的 - 編譯,鏈接和驗證。沒有錯誤或警告。雖然我注意到着色器調試信息AMD/ATI給出的是遠遠低於Nvidia給出的。

更新2

唯一的解決方法,我發現是使所有的情況(所以沒有啓用顏色的時候基本上發送垃圾到GPUattribarray,但我使用統一的檢查顏色,那我就不用它了。所以它是這樣的:

if (useColors){ 
    glUniform1i(uni_colorEnable,1); 
}else{ 
    glUniform1i(uni_colorEnable,0); 
} 
glEnableVertexAttribArray(att_color); 
glVertexAttribPointer(att_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, STRIDE, OFFSET(offset)); 

我不知道爲什麼發生這種情況或爲什麼我需要使用它。我不需要Nvidia。所以我猜這是慢的,我浪費帶寬?但至少它的作品...幫助如何更好地做到這一點將是有益的,但。

+0

顯示如何綁定頂點屬性。還要嘗試驗證您的程序並顯示驗證日誌。 – sbabbi

+1

嘗試重寫沒有條件...(切換程序代替)...我剛碰到與英特爾驅動程序和條件的bonkers問題:http://stackoverflow.com/questions/24222343/glsl-boolean-evaluation-wackiness –

+0

我更新了這個話題。所以即使沒有分支我仍然遇到問題。 – user1214513

回答

1

這可能是因爲您爲着色器(in_Position,in_Color和in_TextureCoord)指定了3個輸入值,但您的頂點數據並不總是包含全部3.當頂點屬性完全不匹配此格式時,進入未定義的行爲領域,每個實現都可以做到自己想做的事情。

它看起來好像Nvidia驅動程序將它所做的事情綁定到適當的頂點屬性並使用它進行渲染。

也就是說,你的數據看起來像裝置下方着色器:

in_Position  = Position.xyz 
in_Color   = ??? 
in_TextureCoords = TextureCoords.xy 

AMD的驅動程序可能正試圖解釋頂點數據,即使不包括顏色的所有3個屬性。在第一個頂點之後,該位置與數據數組中的位置不同步,這會導致它在任何地方渲染。我懷疑當你移除in_Color屬性的使用時,它在AMD上工作的原因是因爲着色器編譯器認爲它沒有被使用並且優化了你指定它的事實。

in_Position  = Position[0].xyz 
in_Color   = TextureCoords[0].xy,Position[1].xy 
in_TextureCoords = Position[1].z,TextureCoords[1].x 

可能的解決辦法是做你已經做了什麼,並指定顏色的垃圾數據時,你不需要它,或者你可以在你的頂點着色器分成2成獨立的人用不同的頂點屬性並綁定相應的一個依據關於你是否有頂點顏色數據。

相關問題