我一直在研究实现多种阴影的方法,并且我注意到Unity使用多次传递来实现它。它执行基本传递,以应用最亮的方向性像素光+ 4个顶点光+ SH,并为每个像素光附加传递一次,直到用户在编辑器上定义的限制为止。

想知道,既然我以前知道我需要遮挡多少像素的灯光,为什么不像顶点灯光那样单步完成呢?这样做有什么问题?

#1 楼

通过遍历数组,完全有可能在片段着色器中进行所有像素照明(或者一次执行4次)。但是,这要付出巨大的性能代价:即使场景的几何形状实际上不受灯光的影响,您仍将为场景中每个片段的每个灯光计算照明。

我怀疑这是Unity为何不这样做的原因:它可能会剔除对象并仅在每次通过时仅提交可能受相应光线影响的几何形状,这意味着仅在可能具有光线的片段中评估光线的阴影效果。这是在处理更少的片段但增加了几何成本之间的权衡。

评论


$ \ begingroup $
既然您提到了淘汰,这很有意义。我刚刚检查了一下,在轻型对象中有一个剔除遮罩属性,以控制受其影响的(层中的)网格。
$ \ endgroup $
–Felipe Lira
15年8月20日在21:39

#2 楼

如果要一次性完成所有照明,则需要遍历着色器中的所有照明。您还需要同时将所有信息获取到GPU。

GPU可以传递给调用的统一数量有限。 UBO和SSBO减少了此限制。

但是,您仍然可以绑定多少纹理以进行阴影映射。

灯光通常只影响其中一小部分。屏幕,因此引擎只能渲染接近灯光的几何图形,也可以调整视口以仅渲染灯光会影响的区域。