Ich kaufte vor kurzem das "opengl Schattierungssprache Kochbuch". Ich versuche eines der Beispiele zu kodieren: speziell die Reflektions-Cubemap.OpenGL Shader: wenn Zustand falsch zu falsch bewertet
Wie es jetzt ist, stürzt meine Software ab.
Ich könnte das Problem auf eine if-Bedingung eingrenzen, die vermutlich wahr ist, aber der "falsche" Teil wird scheinbar ausgeführt (weitere Details folgen).
Das Ziel ist:
- eine Skybox zeichnen.
- zeichnen Sie ein Objekt (eine Teekanne), die die Skybox widerspiegelt.
Umwelt-Entwicklung: Ich habe versucht, auf 2 PCs (Arbeits Laptop und Home-Gaming-rig) mit QT5.6.0 und auf meinem Laptop PC mit QT 5.3.0. QT 5.6.0 ist die 32-Bit-Version kompiliert mit mingw, nicht sicher über die Version 5.3.0.
Beide PCs haben eine NVIDIA-Karte. Ich werde nicht mehr ins Detail gehen, da ich nicht glaube, dass das Problem dort liegt (sofern in den Antworten nicht anders angegeben).
Ich habe die Teekanne drawcall entfernt. Ich zeichne derzeit nur die Skybox. Das bedeutet die boolesche "DrawSkyBox" Uniform ist immer wahr. Das ist wichtig.
Der Vertex Shader ist, wo das Problem liegt (oder zumindest die, die den Absturz provoziert). Der Code hier ist (dies ist der Code/Projekt aus dem Buch, nicht meint, die ohnehin eine copy/paste ist):
#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);
}
Die Fragment-Shader hier:
#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);
}
Also, was ich tat, um das Problem zu erforschen:
1) im Fragment Shader ich nicht holen die Cubemap Textur aber Farben (innerhalb der If/sonst). Ich sehe deutlich die Skybox in rot und die Teekanne in grün (in diesem Test zeichne ich immer noch beides) -> die Zeichnungsaufrufe und Objektdaten sind korrekt.
2) Ich habe versucht mit einem "Standard" 2D-Textur. Ich habe die Standard-Textur-Koordinaten übergeben und der Fragment-Shader hat einfach die Textur abgerufen (no if/else) -> funktioniert perfekt.
3) Ich fand heraus, dass einige Treiber/APIs die boolean in einen int verwandeln konnte (es ist wahrscheinlich ein Problem der alten Zeiten, aber ich entfernt auch diese Möglichkeit): Ich habe versucht, durch einen int Senden und den Zustand zu ändern wenn bis (DrawSkyBox> 0) {...} und 1 auf die Uniform vorbei:
mProgram->setUniformValue("DrawSkyBox", 1);
sogar mit Typumwandlung:
mProgram->setUniformValue("DrawSkyBox", (int) 1);
der Shader noch wurde die Ausführung der "else" Teil.
4) Ich habe die Ausführungsteile in bestimmten Funktionen verschoben, das gleiche Ergebnis.
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);
}
Warum sage ich, dass es den "else" -Teil von Anfang an ausführt? Nun ...:
Am Ende fand ich heraus, dass durch die Änderung "ReflectDir" im else Teil des Vertex-Shader (->ReflectDir = reflect(-worldView, worldNorm);
ersetzt durch ReflectDir = VertexPosition;
) dann funktioniert es perfekt! (Ich meine keinen Absturz und die Skybox wird angezeigt).
So neu formulieren ich die Frage: warum wird der Shader die sonst Teil der Ausführung?
Imarion
PS: ist es ein lange so Vielen Dank im Voraus lesen, wenn Sie diesen Punkt erreicht und für jede Antwort.
Wenn durch „* Absturz *“ Sie „die Anwendung Schließkraft“ bedeutet dann, was in der Core-Dump oder den Debugger Ihrer IDE gefunden (wenn Sie verwenden)? –
Danke für die Bearbeitung :). Ich benutze QT Creator. Es heißt "Die Anwendung hat aufgehört zu arbeiten", ja, es ist eine Art Kraftschluss. Dies ist ein Segmentierungsfehler beim Zeichenaufruf. (In meinem cpp: glDrawElements (...) -> In qopenglfunctions.h: d_ptr-> DrawElements (Modus, Anzahl, Typ, Indizes); Beachten Sie, dass d_ptr korrekt initialisiert wurde (DrawElements \t 0x58790c60 \t void (GLenum, GLsizei, GLenum, const GLvoid *)) Qt ist ganz in einem instabilen Zustand, ich kann nicht eine Core-Dump erhalten. –
Imarion
einen neuen Test gemacht, siehe 4 in meiner ursprünglichen Nachricht. – Imarion