在GLSL中进行NULL检查

时间:2013-01-13 14:12:49

标签: macos opengl null glsl fragment-shader

如果我的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检查的任何信息。是否有一个,或者我真的需要在这里制作单独的着色器吗?

3 个答案:

答案 0 :(得分: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 )时,输出varialbe 的值为gl_FragColor是未定义的:< / p>

  

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

     
      
  1. 执行开始时。
  2.   
  3. 在每个同步点,除非   
        
    • 在上一次同步后,该值已明确定义   点,并且不是由任何调用写的,或
    •   
    • 该值仅由一个着色器调用写入   上一个同步点,或
    •   
    • 该值是由多个着色器调用写的   先前的同步点,以及上次执行的写入   所有这些调用都写了相同的值。
    •   
  4.   
  5. 通过着色器调用读取时,如果   
        
    • 在前一次同步时未定义该值   点,并且从未被相同的着色器调用写入,或
    •   
    • 输出变量由任何其他着色器写入   上一个和下一个同步点之间的调用,   即使该分配发生在阅读后的代码中。
    •   
  6.   

只有在第一次写入输出变量的元素之后才定义其值。所以你在那里做的所有事情毫无意义。它“不起作用”是完全允许的,并且在你的结束时出错。

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


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

答案 1 :(得分:1)

总是定义GLSL着色器中的变量(否则,您将收到链接器错误)。如果您不为这些值提供数据(通过不将相应的统一或绑定属性加载到或属性变量中的),那么这些变量中的值将是未定义的(即垃圾),但现在。

答案 2 :(得分:0)

即使您不能拥有 null 值,也可以测试 undefined 变量。这是我用来调试着色器的技巧:

  ...
  /* 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];
}

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