Skip to main content

3.3 光源分配

针对延迟着色方法的高带宽占用,我们在上一节中介绍了第一种方法,即通过减少光源循环内每个像素读写G-buffer中缓存数据量的大小来减少带宽的占用,这主要是通过第3.2.1节式(2)来实现。

降低带宽占用的另(也是最重要的)一个方法是改变传统延迟着色中的循环结构,使像素的遍历处于外循环,而光源的遍历处于内循环,这样将使得G-buffer中的材质参数只被读写一次,调整后的伪代码如下所示:

for each pixel 
read G-buffer
for each affecting light
compute shading
write frame buffer

然而这样的循环结构调整带来了渲染流程的巨大变化,首先,我们不能再以一个个光源的包围盒几何体为绘制单元进行绘制,而只能使用一个覆盖全屏区域的四边形进行绘制,这意味着所有光源类型都必须使用同一个着色器,特殊光源不能再使用独立的着色器,所以着色器的管理变得更加复杂,这部分的内容参见第(3.4)节。

其次,在处理每个像素的时候,必须知道每个像素受哪些光源影响。我们不能使用一个全局的包含全部光源的一个列表,因为这个列表可能包含上千个光源,这将会导致巨大的计算资源的浪费。考虑到通常场景中的局部区域只受少量的光源的照射(有些游戏引擎还会限制每个物体或者某些区域受影响的最大光源数量。),所以针对每个像素点的光源分配(light assignment)变得非常重要(光源分配可以说是实时渲染非常重要的一个话题,现代很多具有复杂场景的游戏往往都有大量的各种类型的光源,即使场景中没有那么多真实的光源,有些渲染技术也可能包含大量虚拟的光源(例如本书后面将会讲述的即时辐射度方法就可能包含上千个虚拟点光源),因此光源分配几乎是现代游戏引擎必然会涉及的内容。),接下来我们将会讨论两种重要的光源分配方案。