如今,几乎所有的游戏都会从零开始渲染新帧,这意味着这些游戏不会使用该帧之前的任何计算(除非使用随机采样抗锯齿)。但在大部分游戏中,就像在现实世界中一样,帧与帧之间的变化相对较小。如果看向窗外,玩家可能会看到树木在风中摇曳,行人走过窗口,鸟儿在远处飞翔。但绝大部分场景都是“静态” 或固定不变的。主要变化在于玩家的视角。
现在,随着玩家的视角发生改变,所看到的一些物体的外观实际上也会发生改变,特别是有光泽或闪光的物体。但在玩家移动头部时,大多数物体的外观其实只会发生很小的变化,因此,重新一帧一帧地计算构成这些物体相同的精确颜色会造成 GPU 宝贵单元的浪费。对这些物体以较低帧率(如每三帧或更低)来着色,和重复使用过去算过的物体颜色(或者可能还指“纹理元素”)则更为有效。这种工作重用概念在光线追踪中尤为重要,特别是在全局照明的情况下,这是表明缓慢变化和昂贵着色计算的一个常用示例。
这项技术又称纹理空间着色,因为计算并没有在屏幕空间逐帧(即从游戏者的角度)进行,而是在纹理空间通过不同着色率来计算的(主要从物体本身视角来看)。为什么是纹理空间?因为当今游戏中的所有物体均有纹理,且这些纹理独立于玩家视角,使其成为存储着色物体的理想选择,并得以从一帧“搬至”另一帧。
此项也可有效用于 VR:因为我们的眼睛相当靠近,一只眼能够看到的绝大部分物体也会被另一只眼看到。主要区别不在于这些物体的着色(如通过左眼看到的黄色铅笔,与通过右眼看到的黄色铅笔在着色上完全相同),而在于物体的方向。这样一来,借助纹理空间着色,玩家便可“借用”一只眼的着色计算,并将其用于另一只眼,从而将着色工作量减半。如果玩家表现受制于游戏中的像素着色,则理论上纹理空间着色可让帧率加倍。
借助纹理空间着色,游戏引擎不会立即为所有光栅化像素着色。相反,游戏引擎会首先识别光栅化像素所引用的纹素。此操作非常类似于纹理单元在针对给定纹理操作找到所需纹理元素时会执行的操作。稍后会让这组纹理元素排队等候着色。请注意,在此过程中,相同纹素可能会被多个像素所引用,但为了提高效率,我们当然不希望纹理着色出现冗余。因此,游戏引擎必须执行所谓的删除重复着色请求,隔离出唯一可引用的纹理元素,并确保每个纹理元素仅被着一次色。
一旦找到该组唯一可引用的纹理元素,游戏便会针对这些纹理元素进行着色,并将结果存储在相应纹理中以便后续重复利用。这与像素着色类似,不同之处在于着色对象不是屏幕上的像素,而是纹理中的纹理元素。
最后,所计算的纹理元素可用于计算与之对应像素的颜色,与今天使用的静态纹理完全相同。这一步通常价格低廉,因其仅执行单个纹理操作。
而寻找可见纹理元素组并隔离唯一纹理元素在计算方面比较昂贵。因此,应用程序过去承担不起提供纹理空间着色的成本。Turing 架构通过为这一关键步骤引入硬件加速措施来解决这一问题:Turing 的纹理单元现在可直接向着色器提供纹理元素地址信息,而新数据并行内联函数也促使过程中的删除重复步骤非常有效。
尽管纹理空间着色可能看起来非常简单,且合乎逻辑,但因为一些“陷阱”的存在,导致这一技术没能成为主流。
首先,现代游戏对很多对象都进行了重复利用,包括纹理。如果游戏中出现森林,那么很可能很难保证每个树叶都有其独特纹理。很有可能所有树叶均来自同一小组树叶模型和纹理。这些物体不适用于纹理空间着色,因为所有可见对象都必须具有自己的纹理,不允许共享!想象一下,如果玩家没有强制执行此项操作,树上的所有树叶继续共享相同的纹理,然后如果您用手将其中一个放入阴影中,会发生什么。树上的所有树叶都会同时进入阴影。所以,这是开发人员首先需要解决的问题,以确保所有物体都有其自己的纹理,可独立于所有其他物体,单独着色。
因此,纹理空间着色需要对游戏引擎的构建方式彻底重新思考,但只要完成这一操作,便可塑造无限可能,一个全新的渲染方式将会开启,同时可基于光线追踪和光栅化的优势,通过高帧率生成照片般逼真的图像,且无需做出任何妥协。Turing 架构对纹理空间着色的硬件支持让这种混合方法最终得以投入使用。