我最近買了「opengl着色語言食譜」。 我想編碼的例子之一:特別是反射立方體貼圖。Opengl着色器:如果條件錯誤評估爲false
就像現在這樣,我的軟件崩潰了。
我可以將問題的範圍縮小到假設條件,假設是真實的,但是「假」部分看起來是被執行的(更多細節來了)。
的目標是:
- 繪製天空盒。
- 繪製一個反映天空盒的物體(茶壺)。
開發環境: 我試了2臺電腦(筆記本電腦工作和家庭遊戲平臺)與QT5.6.0我與QT 5.3.0筆記本電腦上。 QT 5.6.0是使用mingw編譯的32位版本,不確定5.3.0版本。
這兩款電腦都有nvidia卡。我不會更詳細地討論細節問題,因爲我認爲問題不在於此(除非在答案中另有說明)。
我已經刪除了茶壺drawcall。 我目前只畫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:這是一個很長看了這麼感謝提前,如果你走到今天這一步,併爲任何回答。
如果用「* crash *」表示「應用程序強制關閉」,那麼核心轉儲或IDE的調試器(如果使用的話)中找到了什麼? –
感謝您的編輯:)。我使用QT Creator。它是「應用程序停止工作」,所以是這是一種力量關閉。這是繪製調用時的分段錯誤。 (在我的cpp:glDrawElements(...) - >在qopenglfunctions.h中:d_ptr-> DrawElements(模式,計數,類型,索引);請注意,d_ptr正確initialized(DrawElements \t 0x58790c60 \t void(GLenum, GLsizei,GLenum,const GLvoid *))Qt處於不穩定狀態,我無法獲得核心轉儲 –
Imarion
做了一個新測試,請參見我的原始消息中的4。 – Imarion