选择性地绘制着色器中的某些输出

时间:2018-09-28 07:09:15

标签: opengl glsl shader framebuffer

我有一个带有2个输出的帧缓冲对象:

layout(location = 0) out vec4 color;
layout(location = 1) out uint object_id;

在我的着色器中,我还收到一个布尔值,该值告诉我是否应该写入第二个输出。

color = some_color;
if (condition) {
    object_id = value;
}

这有可能实现吗?

我以为我可以使用glBlendEquation(1,GL_MAX)做到这一点,并且只需在if的else部分中写入0,但这似乎不适用于r32ui纹理。

1 个答案:

答案 0 :(得分:2)

  

在我的着色器中,我还收到一个布尔值,该值告诉我是否应该写入第二个输出。

     

什么情况?统一?着色器会计算出什么吗?

     

它是顶点着色器输入。

如果不写用户定义的片段着色器输出变量之一,则这是未定义的行为,并且存储到帧缓冲区的结果也是未定义的。


请参见OpenGL 4.6 API Core Profile Specification; 17.4. WHOLE FRAMEBUFFER OPERATIONS; page 516

  

如果片段着色器不写入用户定义的输出变量,则着色器执行后片段颜色的值是不确定的,并且每种片段颜色可能有所不同。 如果写入了一些但不是全部的用户定义的输出变量,则与未写入的变量相对应的片段颜色的值同样也未定义。

请参见OpenGL 4.6 API Core Profile Specification; 15.2. SHADER EXECUTION; page 492

  

片段着色器终止时,每个活动的用户定义输出变量的值都将写入到其绑定到的片段颜色输出的组件中。



  

我以为我可以用glBlendEquation(1, GL_MAX)做到这一点,并且只需在if的else部分中写入0,但这似乎不适用于r32ui纹理。

这是不可能的,因为混合操作不适用于整数格式的缓冲区。


OpenGL 4.6 API Core Profile Specification; 17.3.6 Blending; page 502

  

仅当颜色缓冲区具有定点或浮点时才适用混合   格式。如果颜色缓冲区具有整数格式,请继续执行下一个操作。



您可以做的是对帧缓冲区数据存储使用定点格式,例如GL_R16GL_R16有16位存储从0.0到1.0的值,并提供了混合功能。还为纹理和渲染缓冲区提供了GL_R16。相应的数据类型为float
您可以通过将值除以2 ^ 16-1来“标准化”该值,以将无符号整数存储到该值:

layout(location = 1) out vec4 object_id;

object_id.r = float(value) / (exp2(16.0)-1.0);