2016-03-25 10 views
0

Ich habe ein Problem mit einer sehr spezifischen Direktive in meinem Glsl-Shader.OpenGL/GLSL: Preprocessor Problem mit bestimmten Direktive

Ich mag eine Richtlinie so verwenden:

#if defined(numDirectionalLights) && (numDirectionalLights > 0) 
struct DirectionalLight 
{ 
vec3 color; 
vec3 direction; 
}; 
uniform DirectionalLight u_dirLights[numDirectionalLights]; 
#endif 

Wenn ich das GLSL-Programm zu kompilieren, bekomme ich diesen Fehler:

ERROR: 0:6: '' : syntax error: incorrect preprocessor directive 
WARNING: 0:6: unexpected tokens following the preprocessor directive - expected a newline 

Sie here diese Fehler sehen.

Es ist seltsam, weil in C-Sprache diese Syntax erlaubt ist, aber es ist seltsamer, das LibGDX Framework verwendet diese Syntax here und mit LibGDX, es funktioniert! Ich habe zuerst über einen Kodierungsfehler nachgedacht, aber meine Shader sind in UTF-8 und das ist nicht das Problem.

Wissen Sie, wie diese Syntax funktioniert?

+2

Geht es um OpenGL-ES oder OpenGL? Welche Version liefern Sie in Ihrem Shader? – BDL

Antwort

2

WebGL verwendet GLSL ES 1.0. Seine specification schreibt vor, in Abschnitt 3.4, dass:

#if, #ifdef, #ifndef, #else, #elif, and #endif are defined to operate as for C++ except for the following:

...

• Undefined identifiers not consumed by the defined operator do not default to '0'. Use of such identifiers causes an error.

Das Problem ist, dass numDirectionalLights ist eine nicht definierter Kennung nicht vom Betreiber defined verbraucht. In C++ (oder C) würde das den Wert 0 haben. In GLSL ES ist seine Verwendung ein Fehler. Eine Kurzschlussauswertung wird von der Spezifikation bereitgestellt, aber der Compiler stört die Analyse der Linie, noch bevor der #if defined Teil Ihrer Linie ausgewertet wird.

Entweder brechen Ihren Test in zwei:

#if defined(numDirectionalLights) 
#if (numDirectionalLights > 0) 

... oder auch explizit numDirectionalLights als 0 definieren.

Basierend auf der Annahme, dass LibGDX für Vollfett-OpenGL erstellt, gibt es eine feine Unterscheidung in the spec: unter ES ist es ein Fehler für den Programmierer, einen undefinierten Bezeichner in einer Zeile zu verwenden, die der Präprozessor besucht. In OpenGL in voller Größe ist es nur ein Fehler, den Präprozessor dazu zu bringen, eine #if-Klausel auszuwerten, die einen nicht definierten Bezeichner enthält. Was bei der Kurzschlussauswertung der Grund dafür ist, dass das #if defined(x) && ... Muster dort funktioniert. Hier

+0

Danke für Ihre Antwort, Sie haben völlig Recht! Und ich weiß, warum es auf LibGDX funktioniert, fügte ich die Erklärung hinzu. – realitix

1

ist der Grund, warum Libgdx Shader funktioniert:

Libgdx prepends #definehere.

Wenn renderable.environment nicht null ist, dann fügt es #define numDirectionalLights XX hinzu (es kann 0 sein).

Wenn renderable.environment null ist, dann wird #define lightingFlag nicht hinzugefügt, um die shader und #if defined(numDirectionalLights) && (numDirectionalLights > 0) ist nicht im Shader genannt. Es läuft gut.

So können wir sehen, dass im LibGDX-Shader, sollte es nur #if numDirectionalLights > 0 sein, weil numDirectionalLights muss existieren.