OpenGL/glsl:预处理器出现特定指令问题



我在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必须存在。

最新更新