我正在阅读Frank D. Luna的DirectX 11 3D游戏编程简介,似乎无法理解我们为什么要在Pixel Shader中实现照明?如果你能给我发一些关于这个主题的参考页,我将不胜感激。
谢谢。
答案 0 :(得分:6)
照明可以通过多种方式完成。关于这个主题有数百篇SIGGRAPH论文。
对于游戏,有一些常见的方法(或者更常见的是,游戏会采用这些方法的混合方式)
静态照明或光照贴图:照明是离线计算的,通常使用全局照明解算器,并将结果烘焙到纹理中。这些lightmaps在运行时与基础漫反射贴图混合,以创建复杂阴影和微妙光照的感觉,但它们实际上都没有变化。关于光照贴图的好处在于,您可以捕获非常有趣和复杂的照明技术,这些技术的计算成本非常高,然后非常便宜地“重放”它们。限制是您无法移动灯光,尽管有一些技术可以在顶部分层数量有限的动态灯光。
延迟光照:在此方法中,场景被渲染多次以将信息编码到屏幕外纹理中,然后进行额外的传递以计算最终图像。这里场景中每个灯通常有一个渲染通道。见deferred shading。延迟着色的好处在于,使用艺术驱动的内容很容易使渲染器缩放而没有那么多硬限制 - 你可以为更多的光进行更多的传递,例如简单的添加。延迟着色的问题在于每次传递往往几乎没有计算,并且许多传递真的很难推动现代GPU的内存带宽,而现代GPU的计算能力远远高于带宽。
每面向前照明:这通常称为平面shading。这里使用面法线每三角形/多边形执行一次照明。在现代GPU上,这通常在可编程顶点着色器上完成,但也可以使用几何着色器来计算每面法线而不必在顶点中复制它。结果不太现实,但绘画非常便宜,因为每张脸的颜色是不变的。这实际上只有在您使用“Tron外观”或其他non-photorealistic rendering技术时才会使用。
顶点向前照明:这是经典照明,其中每个顶点执行光计算,每个顶点法线。然后,在三角形/多边形(Gouraud shading)的面上插入每个顶点的颜色。这种照明很便宜,在现代GPU上可以在顶点着色器中完成,但对于许多复杂的材质来说,结果可能太平滑,任何镜面高光都会变得模糊或错过。
每像素前向照明:这是您问题的核心:此处每个像素计算一次光照。这可以是经典Phong或Blinn/Phong着色,其中法线在顶点之间插值,或normal maps,其中第二个纹理提供表面的法线信息。在现代GPU中,这是在像素着色器中完成的,并且可以在更昂贵的像素着色器计算中提供更多的表面信息,更好的镜面高光,粗糙度等。在现代GPU上,它们往往具有相对于内存带宽的大量计算能力,因此与过去相比,每像素照明非常实惠。实际上,Physically Based Rendering技术在现代游戏中非常流行,并且这些技术往往具有非常长而复杂的像素着色器,可以为场景中每个表面上的每个像素组合6到8个纹理的数据。
这是一个非常粗略的调查,正如我所说,这个主题有大量的书籍,文章和背景。
您问题的简短回答是: 因为我们可以!