为啥 gl_Color 不是片段着色器的内置变量?

Posted

技术标签:

【中文标题】为啥 gl_Color 不是片段着色器的内置变量?【英文标题】:Why gl_Color is not a built-in variable for the fragment shader?为什么 gl_Color 不是片段着色器的内置变量? 【发布时间】:2013-11-29 12:43:54 【问题描述】:

顶点着色器应该输出裁剪空间中的顶点位置:

顶点着色器,顾名思义,对顶点进行操作。 具体来说,顶点着色器的每次调用都在单个 顶点。这些着色器必须输出,以及任何其他用户定义的 输出,该顶点的剪辑空间位置。 (来源:Learning Modern 3D Graphics Programming, by Jason L. McKesson)

它有一个名为 gl_Position 的内置变量。

同样,片段着色器也期望输出颜色:

片段着色器用于计算一个片段的输出颜色 分段。 [...]片段着色器执行后,片段 输出颜色写入输出图像。 (来源:Learning Modern 3D Graphics Programming, by Jason L. McKesson)

但没有为此定义gl_Color 内置变量,如下所述:opengl44-quick-reference-card.pdf

为什么 OpenGL API 会出现(明显的)不一致?

【问题讨论】:

因为剪辑空间位置很特殊,它必须在管道内部以非常特殊的方式处理,这与任何其他用户定义的顶点输出不同。但是从片段着色器输出的值与从它输出的任何其他值没有什么不同。特殊的是从片段着色器(如果有的话)输出的深度和模板值,对于那些有一个特殊的输出变量。 ... 因为着色器 可以 输出多个值(使用多个渲染目标等)。所以没有单一的“gl_Color”值。只是用户定义的输出。请参阅 glDrawBuffers 及其 GL_COLOR_ATTACHMENTn 参数。 该教程不再有效,并且曾经是 Stack Overflow 常客的作者 Nicol Bolas 已经两年没有出现了。我真的希望他一切都好。 【参考方案1】:

那是因为 OpenGL 管道使用gl_Position 来执行多个任务。 The manual says: "写入 gl_Position 的值将被基元组装、裁剪、剔除和其他固定功能操作(如果存在)使用,这些操作在发生顶点处理后对基元进行操作。"

相比之下,流水线逻辑不依赖于最终的像素颜色。

【讨论】:

所以这是一个设计选择,强制用户设置 gl_Position 因为管道需要它,而实际上不需要颜色?任何历史原因或技术原因? 根据this,您不必设置值。它的默认值为 0。但是,我认为这可能已经过时了。最简单的方法:试试看! 如果您觉得我留下了未回答的问题,请随时私下问我或修改您的问题。 谢谢。这主要是一个 API 设计问题,我理解这种明显不一致背后的想法;) @Korchkidu:实际上,如果您在片段着色器中不输出任何内容,那么无论您是否意识到,您都会隐式输出深度。您可以通过写信给gl_FragDepth 来指定您自己的深度,或者让GLSL 自动为gl_FragDepth 分配在光栅化期间生成的值。颜色不能以这种方式工作,但只有深度。【参考方案2】:

接受的答案并不能充分解释真实情况:

         gl_Color 曾经 已经使用过一次,但它始终被定义为输入值。 p>

在兼容性 GLSL 中,gl_Color 是顶点着色器中的颜色顶点指针,它采用 gl_FrontColorgl_BackColor 的值,具体取决于您在片段着色器中对多边形的哪一侧进行着色。

但是,新版本的 GLSL 中不存在这种行为。您必须提供您自己的顶点属性、您自己的变量,并使用gl_FrontFacing 的值在颜色之间进行选择。我实际上explained this in more detail 在另一个与 OpenGL ES 2.0 相关的问题中,但基本原理是相同的。

事实上,由于gl_Color 已经被用作输入变量,这就是为什么片段着色器的输出被称为gl_FragColor 的原因。您不能在同一阶段将变量同时用作输入和输出。 inout 存储限定符的存在可能会让您不相信,但这仅适用于函数参数

【讨论】:

以上是关于为啥 gl_Color 不是片段着色器的内置变量?的主要内容,如果未能解决你的问题,请参考以下文章

片段着色器是不是处理来自顶点着色器的所有像素?

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

跨多个着色器的 OpenGL 统一

传递给片段着色器的纹理坐标全部为 0

使用制服时 Xamarin OpenGL 片段着色器的奇怪行为

为啥 OSX Mavericks 不能编译我的 GLSL 着色器?