2016-05-27 53 views
1

我最近買了「opengl着色語言食譜」。 我想編碼的例子之一:特別是反射立方體貼圖。Opengl着色器:如果條件錯誤評估爲false

就像現在這樣,我的軟件崩潰了。

我可以將問題的範圍縮小到假設條件,假設是真實的,但是「假」部分看起來是被執行的(更多細節來了)。

的目標是:

  • 繪製天空盒。
  • 繪製一個反映天空盒的物體(茶壺)。

開發環境: 我試了2臺電腦(筆記本電腦工作和家庭遊戲平臺)與QT5.6.0我與QT 5.3.0筆記本電腦上。 QT 5.6.0是使用mingw編譯的32位版本,不確定5.3.0版本。

這兩款電腦都有nvidia卡。我不會更詳細地討論細節問題,因爲我認爲問題不在於此(除非在答案中另有說明)。

我已經刪除了茶壺d​​rawcall。 我目前只畫Skybox。這意味着「DrawSkyBox」布爾均勻性始終爲真。這很重要。

頂點着色器是問題所在的地方(或者至少是引發崩潰的地方)。 的代碼是在這裏(這是一本書的代碼/項目,不是我這是無論如何複製/粘貼):

#version 430 

layout (location = 0) in vec3 VertexPosition; 
layout (location = 1) in vec3 VertexNormal; 
layout (location = 2) in vec2 VertexTexCoord; 

out vec3 ReflectDir; 

uniform bool DrawSkyBox; 
uniform vec3 WorldCameraPosition; 

uniform mat4 ModelViewMatrix; 
uniform mat4 ModelMatrix; 
uniform mat3 NormalMatrix; 
uniform mat4 ProjectionMatrix; 
uniform mat4 MVP; 

void main() 
{ 
    if(DrawSkyBox) { 
     ReflectDir = VertexPosition; 
    } else { 
     vec3 worldPos = vec3(ModelMatrix * vec4(VertexPosition,1.0)); 
     vec3 worldNorm = vec3(ModelMatrix * vec4(VertexNormal, 0.0)); 
     vec3 worldView = normalize(WorldCameraPosition - worldPos); 

     ReflectDir = reflect(-worldView, worldNorm); 
    } 

    gl_Position = MVP * vec4(VertexPosition,1.0); 
} 

片段着色器是在這裏:

#version 430 

in vec3 ReflectDir; 

layout(binding=0) uniform samplerCube CubeMapTex; 

uniform bool DrawSkyBox; 
uniform float ReflectFactor; 
uniform vec4 MaterialColor; 

layout(location = 0) out vec4 FragColor; 

void main() { 
    // Access the cube map texture 
    vec4 cubeMapColor = texture(CubeMapTex, ReflectDir); 

    if(DrawSkyBox) 
     FragColor = cubeMapColor; 
    else 
     FragColor = mix(MaterialColor, cubeMapColor, ReflectFactor); 
} 

所以我做了研究的問題:

1)在片段着色器中我不提取立方體貼圖紋理但設置顏色(在if/else內)。 我清楚地看到紅色的天空盒和綠色的茶壺(在這個測試中我仍然畫了兩個) - >繪製調用和對象數據是正確的。

2)我嘗試了一個「標準」2D紋理。我通過了標準的紋理座標,片段着色器只是簡單地獲取紋理(no if/else) - >完美地工作。我發現一些驅動程序/ API可以將布爾轉換爲int(這可能是舊時代的問題,但我也刪除了這種可能性): 我試着發送一個int並更改條件到如果(DrawSkyBox> 0){...}和通過1至均勻:

mProgram->setUniformValue("DrawSkyBox", 1); 
與類型轉換

甚至:

mProgram->setUniformValue("DrawSkyBox", (int) 1); 

着色器仍然執行 「else」 部分。

4)我移動了執行部分的特定功能,結果相同。

void CalcSkyBox() 
{ 
    ReflectDir = VertexPosition; 
} 

void ObjReflect() 
{ 
    vec3 worldPos = vec3(ModelMatrix * vec4(VertexPosition, 1.0)); 
    vec3 worldNorm = vec3(ModelMatrix * vec4(VertexNormal, 0.0)); 
    vec3 worldView = normalize(WorldCameraPosition - worldPos); 

    ReflectDir = reflect(-worldView, worldNorm);  
} 

void main() 
{ 

    if (DrawSkyBox) { 
     CalcSkyBox(); 
    } else { 
     ObjReflect(); 
    } 

    gl_Position = MVP * vec4(VertexPosition, 1.0); 
} 

爲什麼我說從一開始就執行「else」部分?嗯......:

最後我發現通過修改頂點着色器的else部分中的「ReflectDir」( - >ReflectDir = reflect(-worldView, worldNorm);替換爲ReflectDir = VertexPosition;),那麼它完美地工作! (我的意思是沒有崩潰,並顯示天空盒)。

所以我重申的問題是: 爲什麼着色器執行else部分?

Imarion

PS:這是一個很長看了這麼感謝提前,如果你走到今天這一步,併爲任何回答。

+0

如果用「* crash *」表示「應用程序強制關閉」,那麼核心轉儲或IDE的調試器(如果使用的話)中找到了什麼? –

+0

感謝您的編輯:)。我使用QT Creator。它是「應用程序停止工作」,所以是這是一種力量關閉。這是繪製調用時的分段錯誤。 (在我的cpp:glDrawElements(...) - >在qopenglfunctions.h中:d_ptr-> DrawElements(模式,計數,類型,索引);請注意,d_ptr正確initialized(DrawElements \t 0x58790c60 \t void(GLenum, GLsizei,GLenum,const GLvoid *))Qt處於不穩定狀態,我無法獲得核心轉儲 – Imarion

+0

做了一個新測試,請參見我的原始消息中的4。 – Imarion

回答

0

某些GPU可能評估分支的兩側,然後丟棄一個分支。請參閱:http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter34.html

這並不能解釋您爲什麼會崩潰。您正常化的矢量是否爲零,以便歸一化導致除以零?

+0

我喜歡某種優化。我修改了這樣的計算:ReflectDir = reflect(-worldView,vec3(0.0,1.0,0.0));它不會崩潰,我稍後將深入調查,我現在沒有時間了。無論如何謝謝你:)說,它不應該執行這部分。有這個問題,因爲對於Skybox這些向量沒有通過......他們沒有被使用。 – Imarion

0

我創建了2個程序來擺脫頂點着色器中的「if」。 我使用具有「if」的完全相同的片段着色器。

然後一切正常。

考慮到這是來自Nvidia頂點着色器編譯器的優化錯誤,我很想關閉這個問題。