片段着色器如何知道用于像素颜色的变量?


82

我看到了很多不同的片段着色器,

#version 130

out vec4 flatColor;

void main(void)
{
    flatColor = vec4(0.0,1.0,0.0,0.5);
}

它们都为“输出颜色”使用了一个不同的变量(在这种情况下flatColor)。那么OpenGL如何知道您要做什么?

我猜这行得通,因为flatColor唯一的变量定义为out,但是您可以添加更多out变量,不是吗?还是会崩溃?


实际上,作为测试,我只是运行了此命令:

#version 330

in vec2 TexCoord0;

uniform sampler2D TexSampler;

out vec4 x;
out vec4 y;

void main()
{
    y = texture2D(TexSampler, TexCoord0.xy);
}

无论我使用x还是,效果都很好y


此外,我们有一个预定义的gl_FragColor。有什么区别,为什么人们通常坚持使用自己的变量?

Answers:


142

此外,我们有一个预定义的gl_FragColor。

让我们从这个开始。不,您没有预定义的gl_FragColor。该功能已从核心OpenGL 3.1及更高版本中删除。除非您使用兼容性(在这种情况下,您的3.30着色器应#version 330 compatibility在顶部显示),否则切勿使用此功能。

现在,返回到用户定义的片段着色器输出。但是首先,快速类比。

还记得顶点着色器中的输入吗?而这些投入表示顶点属性索引,你传递给数字glVertexAttribPointerglEnableVertexAttribArray等等?您可以设置从哪个属性提取哪个输入。在GLSL 3.30中,您使用以下语法:

layout(location = 2) in color;

color会将顶点着色器输入设置为来自属性位置2。在3.30之前(或没有ARB_explicit_attrib_location的情况下),您必须glBindAttrbLocation在连接之前显式设置此属性,或者使用来向程序查询属性索引glGetAttribLocation。如果您未明确提供属性位置,则GLSL将任意分配位置(即:以实现定义的方式)。

在着色器中设置它几乎总是更好的选择。

无论如何,片段着色器输出的工作方式几乎完全相同。片段着色器可以写入多种输出颜色,它们本身会映射到帧缓冲区中的多个缓冲区。因此,您需要指示哪个输出转到哪个片段输出颜色。

此过程从片段输出位置值开始。它与顶点着色器输入位置的设置非常相似:

layout(location = 1) out secColor;

还有API函数glBindFragDataLocationglGetFragDataLocation,与glBindAttribLocation和类似glGetAttribLocation

如果您不执行任何显式分配,则实现通常会将输出变量之一分配给位置0。但是,OpenGL标准不需要此行为,因此也不应依赖于此。

现在公平地说,当您使用两个没有获得不同输出位置的输出时,您的程序应该无法链接。可能发生的是您的编译器优化了您没有写出的那个,因此在检查链接器错误时有点忘记了。


4
希望我能多给+1。壮观的答案。我想知道片段输出位置如何工作。:)
kevintodisco'2

啊..所以他们弃用了gl_FragColor,是让您有更大的灵活性来选择要写入哪个缓冲区?说得通。再次感谢!
mpen 2012年

3
@Mark:“不赞成使用”表示“您仍然可以使用它,但是在以后的版本中可能会删除它”。“已删除”是指已删除。它们是有区别的。在GL 3.0中标记为不推荐使用的内容在3.1中删除(另存为几件事)。
Nicol Bolas'2

3
@NicolBolas:“ GL 3.3及更高版本(与以前的版本有所不同)会将它们全部分配到位置0”。我想知道规格在哪里保证。3.3说:“在链接程序时,任何没有在着色器文本中指定或明确设置绑定的可变变量将由GL自动绑定到片段颜色和索引。所有此类分配将使用的颜色索引零。”。最后一句不在3.2中。但是,索引不涉及色号,而仅涉及双源混合索引(在3.3中添加)。
derhass 2013年

1
谢谢@NicolBolas,好答案!所以我还没有完全理解它,只是想“毫无疑问”地使它。在我们的着色器中,我们总是指定layout (location = 0) out vec4 outColor何时绘制到绑定的对象(通常是“屏幕”而不是FBO)。因此,默认情况下,如果我们没有使用glDrawBuffers绑定FBO(或其他缓冲区),而是指定location = 0,它将始终正确绘制到屏幕上?
AzP

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.