OpenGL/glsl:特定指令的预处理器问题
OpenGL/glsl : Preprocessor issue with specific directive
我的 glsl 着色器中有一个非常具体的指令有问题。
我想使用这样的指令:
#if defined(numDirectionalLights) && (numDirectionalLights > 0)
struct DirectionalLight
{
vec3 color;
vec3 direction;
};
uniform DirectionalLight u_dirLights[numDirectionalLights];
#endif
当我编译 glsl 程序时,我得到这个错误:
ERROR: 0:6: '' : syntax error: incorrect preprocessor directive
WARNING: 0:6: unexpected tokens following the preprocessor directive - expected a newline
你可以看到这个错误here。
这很奇怪,因为在 C 语言中,这种语法是允许的,但更奇怪的是,LibGDX 框架使用这种语法 here 并且与 LibGDX 一起工作!我首先想到的是编码错误,但我的着色器是 UTF-8,这不是问题。
你知道如何使这个语法有效吗?
WebGL 使用 GLSL ES 1.0。它的specification在第3.4节中规定:
#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.
问题是 numDirectionalLights
是 defined
运算符未使用的未定义标识符。在 C++(或 C)中,它的值为 0。在 GLSL ES 中,它的使用是错误的。规范提供了短路评估,但编译器在解析该行时犹豫不决,甚至在评估您的行的 #if defined
部分之前。
要么将你的测试分成两部分:
#if defined(numDirectionalLights)
#if (numDirectionalLights > 0)
... 或者明确定义 numDirectionalLights
为 0
.
基于 LibGDX 为全脂 OpenGL 构建的假设,the spec 中有一个细微的区别:在 ES 下,程序员在一行中使用未定义的标识符是错误的预处理器访问。在全尺寸 OpenGL 中,让预处理器评估包含未定义标识符的 #if 子句只是一个错误。考虑到短路评估,这就是 #if defined(x) && ...
模式在那里起作用的原因。
这是 LibGDX 着色器工作的原因:
LibGDX 前置 #define
here.
如果renderable.environment
不为空,则添加#define numDirectionalLights XX
(可能为0)。
如果 renderable.environment
为 null ,则 #define lightingFlag
不会添加到 shader 并且 #if defined(numDirectionalLights) && (numDirectionalLights > 0)
不会在着色器中调用。效果很好。
所以我们可以看到,在LibGDX着色器中,应该只有#if numDirectionalLights > 0
,因为numDirectionalLights
必须存在。
我的 glsl 着色器中有一个非常具体的指令有问题。
我想使用这样的指令:
#if defined(numDirectionalLights) && (numDirectionalLights > 0)
struct DirectionalLight
{
vec3 color;
vec3 direction;
};
uniform DirectionalLight u_dirLights[numDirectionalLights];
#endif
当我编译 glsl 程序时,我得到这个错误:
ERROR: 0:6: '' : syntax error: incorrect preprocessor directive
WARNING: 0:6: unexpected tokens following the preprocessor directive - expected a newline
你可以看到这个错误here。
这很奇怪,因为在 C 语言中,这种语法是允许的,但更奇怪的是,LibGDX 框架使用这种语法 here 并且与 LibGDX 一起工作!我首先想到的是编码错误,但我的着色器是 UTF-8,这不是问题。
你知道如何使这个语法有效吗?
WebGL 使用 GLSL ES 1.0。它的specification在第3.4节中规定:
#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.
问题是 numDirectionalLights
是 defined
运算符未使用的未定义标识符。在 C++(或 C)中,它的值为 0。在 GLSL ES 中,它的使用是错误的。规范提供了短路评估,但编译器在解析该行时犹豫不决,甚至在评估您的行的 #if defined
部分之前。
要么将你的测试分成两部分:
#if defined(numDirectionalLights)
#if (numDirectionalLights > 0)
... 或者明确定义 numDirectionalLights
为 0
.
基于 LibGDX 为全脂 OpenGL 构建的假设,the spec 中有一个细微的区别:在 ES 下,程序员在一行中使用未定义的标识符是错误的预处理器访问。在全尺寸 OpenGL 中,让预处理器评估包含未定义标识符的 #if 子句只是一个错误。考虑到短路评估,这就是 #if defined(x) && ...
模式在那里起作用的原因。
这是 LibGDX 着色器工作的原因:
LibGDX 前置 #define
here.
如果renderable.environment
不为空,则添加#define numDirectionalLights XX
(可能为0)。
如果 renderable.environment
为 null ,则 #define lightingFlag
不会添加到 shader 并且 #if defined(numDirectionalLights) && (numDirectionalLights > 0)
不会在着色器中调用。效果很好。
所以我们可以看到,在LibGDX着色器中,应该只有#if numDirectionalLights > 0
,因为numDirectionalLights
必须存在。