优化片段和顶点着色器之间的操作

Optimize operation between fragment and vertex shader

我正在学习使用 OpenGL 制作图形引擎。我想知道,是否应该将重复操作从顶点着色器移动到片段着色器,因为据我了解,顶点着色器每个顶点只有 运行 一次?

例如,在对光线方向的矢量进行归一化时,由于该光线在整个顶点中都是相同的,是否应该将其移至顶点着色器,而不是为每个像素计算它?是否有特殊原因将其保留在片段着色器中?

如果计算完全相同:是的,通常在顶点着色器中比片段着色器更有效。在某些情况下它可能效率不高:

  • 在绘制导致着色像素少于可变换顶点的几何图形时 -- 由于几何图形密集或极端 discards/occlusion。如果是这种情况,通常您会希望通过切换到较低的 level-of-detail 几何或更智能的几何剔除来解决它。

  • 当在顶点着色器中进行计算时,需要您向片段着色器发送更多数据才能使用计算结果。发送更多数据可能会更慢,因为它需要更多内存操作,并且因为光栅化器需要在每个多边形上插入更多 "varying" 值。

对于光照计算,请特别注意将计算从片段着色器转移到顶点着色器会影响渲染质量。特别是,每个顶点的归一化方向向量在 "varying" 插值后会变短,如果直接使用而不进行重新归一化,这会使三角形内部稍微变暗。当然,将整个光照计算移至顶点着色器会产生更剧烈的效果。

但是这些效果的可见程度取决于纹理的频率、几何体的分辨率、屏幕上的尺寸、灯光的距离等等——在某些情况下,quality/performance 权衡可能有道理。