GLSL片段着色器输出类型

4
假设我有这样的问题:现在我有一个帧缓冲区和一个只包含一种颜色组件(例如GL_RED)的纹理已经绑定到它上面。那么片段着色器会是什么样子?我猜答案是:
``` ... out float ex_color; ex_color = ...; ```
这里有个问题:着色器会自动检测帧缓冲区的格式并向其中写入值吗?如果片段着色器输出浮点数,但帧缓冲区格式为GL_RGBA,会发生什么?
顺便问一下,创建只有一个组件的纹理的正确方法是什么?我读了来自g-truc的示例,其中有一个这样的示例:
```glTexImage2D(GL_TEXTURE_2D, 0, GL_RED,GLsizei(Texture.dimensions().x), GLsizei(Texture.dimensions().y), 0,GL_RGB, GL_UNSIGNED_BYTE, 0);```
将GL_RGB分配为像素数据格式的含义是什么?

我认为GL_RED不是一个有效的内部格式。你需要一个真正具有大小的内部格式(很可能是GL_R8)。 - Christian Rau
所以这就是我困惑的地方。但是当我运行它时,这个示例确实可以正常工作。你能否更详细地解释一下函数glTexImage2D中的内部格式、格式和类型? - user2310794
“所以这就是我困惑的地方。” - 实际上,你并不只在这个问题上感到困惑。但我现在没有时间为所有那些东西提供一个好的大规模解释,所以我希望 Nicol Bolasdatenwolf 或其他人能够介入并给出所有这些问题的真正答案。 - Christian Rau
@ChristianRau:注意,GL_RED是一个有效的内部格式。只是不是一个好的格式;您应该始终使用具有显式大小的内部格式。 - Nicol Bolas
@NicolBolas 噢,我原以为在非大小通用格式已经被认为是一个不好的想法并且不愿意引入通用的RG格式时引入了RG纹理(即使那时我也会认为它是GL_R而不是GL_RED)。我认为GL_RED仅适用于客户端像素格式。感谢您的澄清。 - Christian Rau
2个回答

8
就像顶点着色器输入不必完全匹配glVertexAttribPointer指定的数据大小一样,片段着色器输出也不必与写入的图像大小完全匹配。如果输出提供的分量比目标图像格式多,则多余的分量将被忽略。如果提供的数量较少,则其他分量具有未定义的值(不像顶点输入,未指定的值具有明确定义的值)。

将GL_RGB指定为像素数据格式的含义是什么?

那是像素传输格式。它描述了您向OpenGL提供的像素格式,而不是OpenGL将其存储为的格式。
您应该始终使用有大小的内部格式,而不是像GL_RED这样的无大小格式。

那么,glTexImage2D函数的“internal format”参数表示颜色组件在内存中的存储方式,“format”参数仅表示从用户内存中选择组件的顺序。我可以认为OpenGL总是以“internal format”存储颜色,并且您可以通过指定像素传输格式告诉Opengl如何解释数据并将其复制到内存中吗? - user2310794
@user2310794: "OpenGL总是以四个组件存储颜色" 纹理存储您告诉它们要存储的内容。 - Nicol Bolas
是的,那是我犯的错误... 现在对我来说非常清楚了,非常感谢! - user2310794

3

关于内部格式和格式的详细解释,请参考:

http://opengl.org/wiki/Image_Formathttp://opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml

通常,您需要使用GL_RED作为格式,并且可能需要使用GL_R8(无符号标准化的8位定点数)作为内部格式。

很久以前,亮度纹理是单通道的规范格式,但在现代GL中,它已被弃用,现在红色是单通道的逻辑“可绘制”纹理格式,就像红/绿是最合适的两通道格式一样。

至于着色器,核心规范定义了组件扩展的规则。如果您有一个输入为1个通道的纹理,但将其作为vec4进行取样,则等效于:vec4(RED,0.0,0.0,1.0)。

写入纹理略有不同。

来自OpenGL 4.4规范,第15.2节(着色器执行),pp.441 -- http://www.opengl.org/registry/doc/glspec44.core.pdf

当片段着色器终止时,每个活动用户定义的输出变量的值都会被写入到其绑定的片段颜色输出的组件中。根据变量的数据类型和组件索引绑定,使用表11.1中的映射确定所写入的片段颜色组件集[pp.341]。

默认情况下,如果您的片元着色器输出为float,则它将写入纹理的x(红色)分量。您可以使用布局限定符(例如,layout(component = 1)out float color;)指定它应该写入y(绿色),z(蓝色)或w(Alpha)(假设您有一个RGBA纹理)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接