片段着色器会覆盖光栅化生成的片段颜色吗?

Posted

技术标签:

【中文标题】片段着色器会覆盖光栅化生成的片段颜色吗?【英文标题】:Fragment shader will overwrite the fragment color generated from rasterization? 【发布时间】:2016-12-06 17:23:07 【问题描述】:

据我了解,片段着色器采用光栅化的结果。但是,根据Computer Graphics: Principles and Practice (3rd Edition),光栅化会根据各个方向的光照计算片段颜色:

for each pixel position (x, y):
closest[x, y] = ∞
for each triangle T:
   for each pixel position (x, y):
   let R be the ray through (x, y) from the eye
   let P be the intersection of R and T
   if P exists:
      sum = 0
      for each direction:
          sum += . . .
          if the distance to P is less than closest[x, y]:
             pixel[x, y] = sum
             closest[x, y] = |P − O|

所以片段颜色像素[x, y] 是根据场景中的光照计算的。因此,在此之后,片段着色器将对每个片段应用颜色、纹理等。片段着色器或纹理中的颜色如何与光栅化计算的颜色混合?

【问题讨论】:

【参考方案1】:

片段着色器是您对光栅化过程的实现,描述的光栅化由固定管道中的着色器完成,灵活管道使用您提供的着色器程序代替。

来自 opengl 文档: 片段着色器是将光栅化生成的片段处理为一组颜色和单个深度值的着色器阶段。

片段着色器是图元光栅化后的 OpenGL 管道阶段。对于图元覆盖的每个像素样本,都会生成一个“片段”。每个片段都有一个窗口空间位置和一些其他值,它包含来自最后一个顶点处理阶段的所有插值的每个顶点输出值。

片段着色器的输出是一个深度值、一个可能的模板值(未由片段着色器修改)以及零个或多个可能写入当前帧缓冲区中的缓冲区的颜色值。

如果不提供片段着色器,片段中像素的颜色将保持不变

【讨论】:

“片段着色器的输出是一个深度值”。据我了解,深度值是在光栅化期间计算的。 片段着色器是你实现的光栅化过程吗?我认为片段着色器是在管道中的光栅化之后出现的。 @lightrek:这并不完全准确。可以在光栅化期间计算深度,但片段着色器拥有最终决定权。如果片段着色器从不写入深度,则可以使用光栅化值,并且硬件被设计为进行早期深度测试并跳过在这种情况下失败的任何片段的着色。但如果片段着色器向gl_FragDepth 写入任何内容,则必须在着色后执行深度测试。出于同样的原因,也可以提前进行模板测试;有一整类“早期片段测试”。 @Andon M. Coleman:但是光栅化过程中生成的深度缓冲区,对吧? 同样,这取决于片段着色器是否将值写入gl_FragDepth。如果着色器写入自己的值,则在着色之前无法写入深度(因为光栅化生成的值不是片段的最终深度)。一般来说,最好不要考虑这些优化,只考虑在着色后才写入深度缓冲区。【参考方案2】:

你的理解是正确的,阴影是在光栅化之后发生的。

这是光栅化和输出合并(混合)之间的可编程步骤。光栅化对每个顶点的属性进行插值(非平面),并使用它计算的值为每个片段生成一个或多个样本。

在光栅化期间计算的值被传递到片段着色器阶段,该阶段决定如何处理它们(例如在特定坐标处对纹理进行采样)以产生颜色和深度。着色后,通过深度/模板测试的片段根据设置混合方程与帧缓冲区中已经存在的任何内容合并(混合)以生成像素。

【讨论】:

以上是关于片段着色器会覆盖光栅化生成的片段颜色吗?的主要内容,如果未能解决你的问题,请参考以下文章

渲染管道光栅阶段一“总览”

为啥保守光栅化无法为某些三角形调用片段着色器?

渲染管道光栅阶段四“片元着色器”

渲染管道光栅阶段四“片元着色器”

如何在渲染之间更改片段着色器颜色?

OpenGL 片段着色器未写入 fbo 颜色缓冲区