最近「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:あなたはこの点に達し、すべての答えを場合には事前に長いので、読みのおかげです。
"* crash *"とは、コアダンプにあるwhats、またはIDEのデバッガ(使用している場合)です。 –
ありがとうございました。私はQT Creatorを使用しています。それはsais "アプリケーションが動作を停止"ので、それは強制終了の一種です。これは、ドローコール時のセグメンテーションフォルトです。 d_ptrが正しく初期化されていることに注意してください(DrawElements \t 0x58790c60 \t void(GLenum、 GLsizei、GLenum、const GLvoid *))Qtは非常に不安定な状態です。コアダンプを取得できません。 –
Imarion
新しいテストを作成しました。元のメッセージの4を参照してください。 – Imarion