我在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
您可以在此处看到此错误。
这很奇怪,因为在C语言中,这种语法是允许的,但更奇怪的是,LibGDX框架在这里使用了这种语法,并且与LibGDX一起工作!我第一次想到的是编码错误,但我的着色器是UTF-8,这不是问题所在。
你知道如何使用这种语法吗?
WebGL使用GLSL ES 1.0。其规范在第3.4节中规定:
#if、#ifdef、#ifndef、#else、#elif和#endif被定义为与C++一样操作,但以下情况除外:
•未由
defined
运算符使用的未定义标识符不会默认为"0"。使用此类标识符会导致错误。
问题是numDirectionalLights
是一个未定义的标识符,defined
运算符没有使用它。在C++(或C)中,它的值为0。在GLSL ES中,它的使用是一个错误。规范提供了短路评估,但编译器在解析行时会犹豫不决,甚至在评估行的#if defined
部分之前。
要么把你的测试分成两部分:
#if defined(numDirectionalLights)
#if (numDirectionalLights > 0)
或者明确地将CCD_ 5定义为CCD_。
基于LibGDX是为完整的OpenGL构建的假设,规范中有一个细微的区别:在ES下,程序员在预处理器访问的行上使用未定义的标识符是错误的。在全尺寸OpenGL中,让预处理器评估包含未定义标识符的#if子句只是一个错误。考虑到短路评估,这就是#if defined(x) && ...
模式在那里工作的原因。
以下是LibGDX着色器工作的原因:
LibGDX在此处预处理#define
。
如果renderable.environment
不为空,则添加#define numDirectionalLights XX
(可能为0)。
如果renderable.environment
为null,则不会将#define lightingFlag
添加到着色器,也不会在着色器中调用#if defined(numDirectionalLights) && (numDirectionalLights > 0)
。它运行良好。
所以我们可以看到,在LibGDX着色器中,它应该只有#if numDirectionalLights > 0
,因为numDirectionalLights
必须存在。