rain.gg
rain.gg

虽然我们进入了起源 2 的 CS2 时代,但 CS:GO 仍然具有很大的惯性,我们对 CS:GO 的部分疑问还没有解除。那就是画质菜单选项的 “启用 Uber 着色器” 是啥意思?

包括很多起源开发者也认为,这是 V 社专门为 CS:GO 开发的一款新的着色器。

其实不对,或者说 “说对了一半”,Uber Shader 并不是指哪个具体的着色器,而是一个庞大的着色器管理系统,它的外在形式也确实是个着色器。

虽然是 CS:GO 这样的老游戏了,但是具体的着色器数量还真不一定少。别看材质就那寥寥几种类型,但是如果我的材质参数有一丁点变化,还有更多的,例如反射,折射,光照,置换,法线甚至是透明度等等,哪怕是着色算法一样,也得编译个新着色器,这样一来就有上千个着色器变体了。

这么多着色器,肯定是不便于管理的。你想,如果我这么多着色器里有一个出了问题,那怎么改?一个一个找吗?

没关系,就算是你找到了也可能会改错,因为一个渲染对象可能不止有一个 shader,可能得由几个 shader 组合起来,并且更大的可能是这个组合导致的问题。而这个组合是最难寻找的。

Uber 着色器的思路就是,把可能的着色器变体全部分出来,并且整合在一个超级大的着色器,根据具体情况在游戏中再进行具体运行。Uber Shader 的一个最标准的解释就是 “unified shader template”,即统一的着色器模板

Uber 超级大着色器就是用条件分支定义了非常多个具体的着色器,shader 组合是自动生成的,假使哪里出了故障可以很轻松地直接在 Uber 着色器里纠正,不需要很麻烦地去找。

仅作参考,这复杂度其实已经是离线渲染级别的了

然而,GPU 是十分讨厌分支这个东西的,因为我们知道 GPU 是一个高度并行化的硬件,我们用 GPU 执行一批着色器当然希望它们能同时执行完,没有什么 if 语句打断一致性。但 Uber 着色器全都是分支,不可能游戏运行的时候直接嗯造这么庞大的 shader,于是 Uber 着色器需要为运行时的游戏生成出具体着色器,举个例子,Unity 约 100 个 Uber Shader 能够在游戏运行时生成约 100000 个具体的 Shader。

降低性能是起源引擎的问题,它不太经受得起一些新东西。Uber 着色器被广泛使用应该也是 UE4 时代了,然而这东西是九十年代末就出现了,可能一开始也只是用在离线渲染器上。

总而言之,Uber 着色器就是个超级着色器,它会根据具体需要变出众多具体着色器。