【发布时间】:2014-08-25 00:32:40
【问题描述】:
我看过很多关于 OpenGL ES2.0 照明的不同教程。
有些人使用顶点着色器来完成所有的光照和变换,然后将最终颜色传递给片段着色器。
其他人从顶点着色器传递位置和其他变量,然后在片段着色器中完成所有照明。
根据我的经验,我一直认为应该在片段着色器中完成光照。谁能告诉我为什么一个比另一个?
【问题讨论】:
标签: android opengl-es opengl-es-2.0 lighting
我看过很多关于 OpenGL ES2.0 照明的不同教程。
有些人使用顶点着色器来完成所有的光照和变换,然后将最终颜色传递给片段着色器。
其他人从顶点着色器传递位置和其他变量,然后在片段着色器中完成所有照明。
根据我的经验,我一直认为应该在片段着色器中完成光照。谁能告诉我为什么一个比另一个?
【问题讨论】:
标签: android opengl-es opengl-es-2.0 lighting
传统的、固定管线的 OpenGL 在顶点处进行光照,并且仅对每个片段进行插值。所以它往往会沿着边缘显示出可见的接缝:
然而,这被认为是一个可以接受的折衷方案,因为照明太成本太高而无法按像素进行。现在硬件更好了,但每个像素的照明仍然更多昂贵。所以我想那里有一个潜在的争论。另外我猜如果你试图模拟旧的固定管道,你可能会故意不准确地进行照明。
但是,我很难想出任何可以接受的特别复杂的算法。您看到的示例是否可能只是在做一些事情,比如计算每个顶点的切线和余切向量,或者其他类似的昂贵步骤,然后对每个像素进行插值并在那里进行绝对的最终计算?
【讨论】:
照明计算可能相当昂贵。由于在渲染典型模型时片段比顶点多得多,因此在顶点着色器中进行光照计算并在片段中插入结果通常更有效。除了纯粹的着色器执行次数之外,在片段着色器中执行典型的光照计算也可能需要更多操作,因为插值法线需要重新归一化,这需要相对昂贵的sqrt 操作。
逐顶点光照的缺点是,如果光照值在表面上快速变化,它的效果会很差。这很有意义,因为这些值是跨三角形线性插值的。如果所需值在三角形上没有近似线性变化,则会引入伪影。
典型的例子是镜面高光。如果您定义具有相对尖锐/较小的镜面高光的闪亮材质,您可以轻松地看到高光的亮度在对象动画时发生变化。看起来高光似乎在物体上“徘徊”。例如,如果您旋转一个带有高光围绕其中心的球体,则高光应该保持完全相同。但是使用逐顶点光照时,高光的亮度会增加和减少,并且会轻微晃动。
有两种主要方法可以避免这些影响,或者至少将它们降低到它们看起来不再令人不安的水平:
需要根据具体情况决定哪种解决方案更好。当然,使用更精细的细分会增加几何处理方面的开销,而使用逐片段照明会增加片段着色器的开销。
当您想要应用凹凸贴图等效果时,逐顶点光照会变得更加成问题,其中光照值在整个表面上变化非常快。在这些情况下,几乎无法使用逐片段照明。
我看到有人建议 GPU 速度如此之快,以至于不应再使用逐顶点光照。我认为这是一个严重的简化。即使您可以通过按片段照明获得所需的性能,但如今大多数计算机/设备都是电池供电的。为了节能,尽可能提高渲染效率与以往一样重要。而且我相信仍有一些用例表明逐顶点光照是最有效的方法。
【讨论】: