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

Posted

技术标签:

【中文标题】有选择地绘制到着色器中的某些输出【英文标题】:Selectively drawing to some outputs in shaders 【发布时间】:2018-09-28 07:09:15 【问题描述】:

我有一个带有 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 纹理。

【问题讨论】:

好的,所以在你的顶点着色器中你有这两个输出,你不想写第二个。我能问为什么吗?您要解决的问题是什么?如果片段着色器未能满足某些条件,您是否可以只忽略片段着色器中的对象 ID? “我有一个帧缓冲对象”,这些是我在片段着色器中的输出。并且忽略片段着色器中的输出不起作用,因为它们随后变得未定义。 什么是条件?统一?着色器计算的东西? 它作为顶点着色器输入。 【参考方案1】:

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

什么是条件?统一?着色器计算的东西?

它作为顶点着色器输入。

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

见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);

【讨论】:

以上是关于有选择地绘制到着色器中的某些输出的主要内容,如果未能解决你的问题,请参考以下文章

GL_POINTS 着色器中的示例纹理

在片段着色器中绘制别名像素完美线?

此顶点着色器中的统一浮动不起作用

为啥我的着色器中的 GLSL 纹理坐标不是线性的?

OpenGL 计算着色器中的样本深度缓冲区

在 vertexShader 中使用 OpenGl 未声明的标识符,我在顶点着色器中绘制三角形时遇到问题