2016-05-27 14 views
1

最近「openglシェーディング言語料理書」を購入しました。 私は例の1つをコーディングしようとしています。具体的には反射キューブマップです。OpenGLシェーダ:条件が間違って偽に評価された場合

今のところ私のソフトウェアはクラッシュします。

私はこの問題をsupposidlyのtrue条件に絞り込むことができましたが、 "偽の"部分は一見実行されました(詳細はこちら)。

目標は次のとおりです。

  • は、スカイボックスを描画します。
  • skyboxを反映するオブジェクト(ティーポット)を描画します。

開発環境: 私はQT5.6.0と2のPC(仕事のラップトップとホームゲームのリグ)上およびQT 5.3.0と私のラップトップPC上で試してみました。 QT 5.6.0はmingwでコンパイルされた32ビットバージョンで、5.3.0バージョンについてはわかりません。

両方のPCには、nvidiaカードがあります。私は問題がそこにあるとは思わないので詳細には触れません(答えに別途明記されていない限り)。

私はティーポットドローコールを取り外しました。 私は現在Skyboxを描いているだけです。つまり、"DrawSkyBox"ブールの統一は常にtrueです。これは重要です。

頂点シェーダは、問題が存在する場所(または少なくともクラッシュを引き起こす場所)です。 コード(これは私はとにかくコピー/ペーストである、ブックからのコード/プロジェクトではありません)ここにある:

#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内)。 私はskyboxが赤く、緑色のティーポットが(このテストではまだ両方を描いています) - 描画呼び出しとオブジェクトデータが正しいことをはっきりと見ています。

2)私は「標準的な」2Dのテクニックを試しました。私は標準的なテクスチャ座標を渡しました。フラグメントシェーダは単純にテクスチャを取得していました(if/elseはありません) - >完全に動作しています。

3)私はいくつかのドライバ/ APIがブール値をintに変換する可能性があることを知りました(これはおそらく昔の問題ですが、私もこの可能性を削除しました)。 intを送信し、 (DrawSkyBox> 0){...}とが均一に1を通過する場合に:型キャストとも

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

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

シェーダは依然として "他" の部分を実行していました。

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」部分を実行すると言いますか?まあ...:がReflectDir = VertexPosition;に置き換えられていれば、頂点シェーダのelse部分の "ReflectDir"を変更することで、完全に動作することがわかりました。 (私はクラッシュしないことを意味し、スカイボックスが表示されます)。

私は質問を再現します: なぜシェーダはelse部分を実行していますか?

Imarion

PS:あなたはこの点に達し、すべての答えを場合には事前に長いので、読みのおかげです。

+0

"* crash *"とは、コアダンプにあるwhats、またはIDEのデバッガ(使用している場合)です。 –

+0

ありがとうございました。私はQT Creatorを使用しています。それはsais "アプリケーションが動作を停止"ので、それは強制終了の一種です。これは、ドローコール時のセグメンテーションフォルトです。 d_ptrが正しく初期化されていることに注意してください(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));そしてそれはクラッシュしない。私は後でもっと深く調べるだろう、今は時間がないとにかくありがとう:)それは、この部分を実行してはならないと言った。スカイボックスの場合、これらのベクトルは渡されないので、この問題があります。それらは使用されません。 – Imarion

0

頂点シェーダで「if」を取り除くために2つのプログラムを作成しました。 "if"を持つ全く同じフラグメントシェーダを使用します。

すべてうまくいきます。

これはNvidia頂点シェーダコンパイラの最適化のバグであると考えて、この問題を解決したいと思っています。

関連する問題