首页 > 解决方案 > 将负值混合到帧缓冲区 0 opengl

问题描述

该程序将一堆东西渲染到一个中间帧缓冲区中,该缓冲区使用无符号规范化纹理来存储数据。中间帧缓冲区与默认帧缓冲区混合。用于渲染与帧缓冲区 0 混合的中间体的像素着色器如下:

#version 300 es

precision mediump float;

out vec4 fragColor;

in vec2 texCoords;

uniform sampler2D textureToDraw;

void main()
{
    vec4 sampleColor = texture(textureToDraw, texCoords);
    fragColor = vec4(sampleColor.rgb * -1.0, sampleColor.a);
}

设置绘制到帧缓冲区 0 的代码如下:

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

// Draw the intermediate using the pixel shader above and a quad

的 rgb 分量fragColor将在 [-1, 0] 范围内。预期的结果是从先前的帧缓冲区内容中减去中间颜色。实际结果是黑色与帧缓冲区 0 的正确 alpha 混合,这表明它fragColor在某处被钳制到 [0, 1] 并且负部分被丢弃。

有没有办法禁用片段着色器输出到 [0, 1] 的钳位?

我知道没有办法渲染到签名的规范化纹理,所以也许有一个 OpenGL 限制可以防止这种情况发生。我正在考虑的替代方案是进行两次渲染,一次将负位渲染到中间,另一个将正位渲染到另一个中间。最后,将正面与GL_FUNC_ADD负面与混合GL_FUNC_REVERSE_SUBTRACT。维护起来既慢又麻烦。还有其他方法吗?

标签: opengl-esframebufferblending

解决方案


有没有办法禁用片段着色器输出到 [0, 1] 的钳位?

让我引用OpenGL 4.6 Core Profile Specification的第17.3.6节(强调我的):

如果颜色缓冲区是定点的,则在评估之前,对于无符号归一化或有符号归一化颜色缓冲区,值和目标值以及混合因子的分量分别被钳制为 [0, 1] 或 [-1, 1]混合方程。如果颜色缓冲区是浮点数,则不会发生钳位。产生的四个值被发送到下一个操作。

因此,您可以使用其中一种*16F*32F格式来摆脱钳制。

我知道没有办法渲染到签名的规范化纹理,所以也许有一个 OpenGL 限制可以防止这种情况发生。

该规范将各种标记_SNORMcolor-renderable。但是,与此同时,规范并没有将这些格式标记为渲染目标需要支持,因此实现可以允许您使用这种格式,但它们不是必须的,所以是的,您不能以任何方式依赖它...


推荐阅读