在GLSL中进行NULL检查

Ivo*_*ius 1 opengl macos 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'
Run Code Online (Sandbox Code Playgroud)

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

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; 
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我在开始时对gl_FragColor进行了0/NULL检查,因为有些图形卡会在那里传递有价值的信息,但有些则没有.现在,在那个特殊的mac上,它没有用.我做了一些研究,但找不到有关如何在GLSL中进行正确的NULL检查的任何信息.有没有,或者我真的需要在这里制作单独的着色器吗?

dat*_*olf 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);
Run Code Online (Sandbox Code Playgroud)

你要做的第一件事就是阅读gl_FragColor.所述GLSL说明书明确规定,即一个的值输出varialbe作为gl_FragColor当片段着色器级被输入(点,是未定义1):

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

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

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

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


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