如何在照明着色器中跳过天空?

我最近在延期渲染的游戏中实现了一个天空。 这是一个应用了纹理的程序计算球体。 不幸的是,所有的照明着色器(光源,环境遮挡)也适用于该天空穹顶几何。

所以天空是完全黑暗的,没有一个巨大的光源水平。 如果有的话,那个球体的三角形之间的边缘会被环境遮挡着色器弄脏。

我的快速和肮脏的修复是读取深度纹理,以确定是否应用照明效果。 例如,视图距离为1000.0f ,深度大于900.0f每个像素不再被遮挡。 这在一定程度上起作用,因为天空的每个像素都在900.0f1000.0f之间。

但是这种方法有一些问题。 例如,远离900.0f水平几何体900.0f阴影。 此外,深度值来自投影在飞机,屏幕上的场景。 这意味着从玩家的世界位置到所有方向的天空距离在图像上是不同的。 屏幕两侧看到的天空比屏幕中央看到的天空像素更近。 该效果因视野设定而异。 与此相关的问题是,对于每个视野设置,我将需要不同的深度阈值阴影。

有没有一种常见的方式,不,或不同的方式,阴影图像的一些像素? 就我而言,我不需要着色天空像素。 如果我可以确定哪个像素来自天空,我可以将其存储在缓冲区中,并在光照着色器中读取以跳过这些像素。 但我不知道如何解决这个问题。

您可以轻松使用Z缓冲区渲染天空盒/光线过程中重要的像素。

我最后渲染天空盒(在所有灯之后)。 渲染天空盒时,确保深度缓冲区仍然完好,并使用GL_GEQUAL作为深度函数。 然后在天空盒的vertext着色器中,将gl_Position的z值设置为它的w值。 这确保天空盒被渲染到远处的平面上。

如果要在渲染光栅期间跳过天空盒像素的渲染,可以将z-clear值设置为1,并在光通过期间使用GL_LEQUAL进行深度比较。

我结束了使用模板缓冲区。 基本上,这是我的应用程序通过每一帧的步骤。

  • 绘制几何graphics除外天空和设置模具缓冲区为1
  • 禁用深度遮罩不会使深度缓冲区变形。
  • 在模板仍然是0地方画天线。
  • 使用模板testing只计算模板为1照明和其他着色器计算,因此在几何体的位置。
  • 禁用包含天空的计算的模板testing,如抗锯齿和用户界面。

我建议使用颜色缓冲区的alpha通道来存储“光照因子”,然后用它在几何graphics的点亮和不点亮的版本之间进行线性插值。 另外,使用最大似乎也很有吸引力 – 计算可能是这样的:

 max (litColor * unlitColor.a, unlitColor) 

之所以会吸引人,是因为你也可以将其用于其他效果,例如纹理上的发光区域,或闪电照亮你的天空中的云彩。 这也意味着你的模板缓冲区保持不被使用,因此如果你还想用其他的东西来使用它。