1

如果我的 vec4 为 NULL,我正在尝试检查着色器 (GLSL) 内部。我需要这个有几个原因,主要是为了让特定的显卡兼容,因为其中一些在 gl_FragColor 中传递了以前的颜色,而另一些则没有(提供需要覆盖的空 vec4)。好吧,在一台相当新的 Mac 上,有人收到了这个错误:

java.lang.RuntimeException: Error creating shader: ERROR: 0:107: '==' does not operate on 'vec4' and 'int'
ERROR: 0:208: '!=' does not operate on 'mat3' and 'int'

这是我在片段着色器中的代码:

void main()
{
    if(gl_FragColor == 0) gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); //Line 107
    vec4 newColor = vec4(0.0, 0.0, 0.0, 0.0);

    [...]

    if(inverseViewMatrix != 0) //Line 208
    {
        [do stuff with it; though I can replace this NULL check with a boolean]
    }

    [...]

    gl_FragColor.rgb = mix(gl_FragColor.rgb, newColor.rgb, newColor.a);
    gl_FragColor.a += newColor.a; 
}

如您所见,我在开始时对 gl_FragColor 进行了 0/NULL 检查,因为有些显卡会在那里传递有价值的信息,但有些则不会。现在,在那台特殊的 Mac 上,它不起作用。我做了一些研究,但找不到有关如何在 GLSL 中进行正确 NULL 检查的任何信息。甚至有一个,还是我真的需要在这里制作单独的着色器?

4

3 回答 3

9

所有用于读取的变量,即输入变量总是提供合理的值。作为输出变量,gl_FragColor不是这些变量之一!

在这段代码中

void main()
{
    if(gl_FragColor == 0) gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); //Line 107
    vec4 newColor = vec4(0.0, 0.0, 0.0, 0.0);

您要做的第一件事就是从gl_FragColor. GLSL 规范明确指出,当进入片段着色器阶段时(第1点),输出变量的值是未定义的:gl_FragColor

在以下三种情况中的任何一种情况下,输出变量的值都将是未定义的:

  1. 在执行开始时。
  2. 在每个同步点,除非
    • 该值在上一个同步点之后定义明确,并且此后没有被任何调用写入,或者
    • 该值是由自上一个同步点以来的一个着色器调用写入的,或者
    • 自上一个同步点以来,该值由多个着色器调用写入,并且所有此类调用执行的最后一次写入写入相同的值。
  3. 当被着色器调用读取时,如果
    • 该值在上一个同步点处未定义,并且此后未由相同的着色器调用写入,或者
    • 输出变量由前一个和下一个同步点之间的任何其他着色器调用写入,即使该分配发生在读取之后的代码中。

只有在第一次写入输出变量的元素后,它的值才被定义。所以你在那里做的所有事情都是没有意义的。它“不起作用”是完全允许的,并且是您的错误。

您正在调用未定义的行为,从技术上讲,您的计算机可以变得有意识,在街上追赶您并擦除您的所有数据作为对此的替代反应。


在 GLSL 中,vec4是一种常规数据类型,就像 int 一样。它不是某种指向可能是空指针的数组的指针。充其量它有一些默认值不会被调用glUniform覆盖。

于 2013-01-13T15:35:47.320 回答
1

GLSL 着色器中的变量总是被定义的(否则,你会得到一个链接器错误)。如果您不为这些值提供数据(通过不加载适当的统一,或将属性绑定到in属性变量),则这些变量中的值将是未定义的(即垃圾),但存在。

于 2013-01-13T15:40:01.043 回答
1

即使你不能有空值,你也可以测试未定义的变量。这是我用来调试着色器的技巧:

  ...
  /* First we test for lower range */
  if(suspect_variable.x < 0.5) {
      outColour = vec4(0,1,0,0); /* Green if in lower range*/
  } else if(suspect_variable.x >= 0.5) { /*Then for the higher range */
      outColour = vec4(1,0,0,0); /* Red if in higher range */
  } else {
      /* Now we have tested for all real values.
         If we end up here we know that the value must be undefined */
      outColour = vec4(0,0,1,0); /* Blue if it's undefined */
  }

您可能会问,什么会使变量未定义?数组的超出范围访问将导致它未定义;

const int numberOfLights = 2;
uniform vec3 lightColour[numberOfLights];
...
for(int i = 0; i < 100; i++) {
   /* When i bigger than 1 the suspect_variable would be undefined */
   suspect_variable = suspect_variable * lightColour[i];
}

当您无法访问真正的调试工具时,这是一个简单易用的技巧。

于 2016-06-04T02:13:32.197 回答