经常有朋友在后台留言问自己的硬件配置超过3A大作的推荐配置很多了,但是steam上一旦出现了一个大版本更新,进入游戏后开一局就会发现卡顿非常明显。这是为什么?这就是因为更新游戏后,往往还要进行一个shader编译,即着色器(渲染器)编译。
1、什么是着色器?
着色器,又称渲染器,英文名是shader。
着色器是在GPU上运行的一个代码段,通常用于在游戏和其他图形密集型应用程序中渲染图形。着色器可以用于实时控制3D场景的颜色、纹理、照明和其他视觉方面。
具体来说,着色器是在GPU上为3D模型中的每个顶点或像素渲染执行的程序。着色器可以用专门的编程语言编写,如OpenGL着色语言(GLSL)或高级着色语言(HLSL),并在运行时在GPU上编译和执行。
着色器有几种类型,包括顶点着色器、片段着色器、几何着色器、镶嵌着色器和计算着色器。每种着色器都有自己独特的功能,可以对传递给它的数据执行不同的操作。
总的来说,GPU上的着色器是如今3D图形渲染的关键组件,负责产生我们在视频游戏、CG电影和其他视觉媒体中看到的惊人视觉效果。
在比较复杂的N卡资源监控窗口中,你能看到游戏的每帧都涉及各种类型的着色器工作
从本质上讲,着色器只是一些代码块。在图形和三维渲染的世界里,每一个都是一个小程序,旨在产生一个非常具体的输出。它可能是转换一个三角形的形状或位置,将一个纹理映射到一个形状,或计算一组其他着色器所需的值。
当诸如Direct3D和OpenGL等API首次支持着色器时,它们的大小和范围都非常有限。例如,20多年前,当像素着色器首次出现在PC上时,只有4条涉及纹理的指令和8条做数学运算的指令。
今天,在所有着色器的最新版本中,对代码中可容纳的指令数量实际上没有限制。这也就为后面我们所说的“卡顿”埋下了伏笔。
尽管开发者使用的各种API有不同的术语,但有七类着色器。顶点(Vertex)、几何(Geometry)、外壳(Hull)和域(Domain)着色器都是处理三角形(多边形)的顶点的——在三维世界被着色之前创建和塑造。
这项任务由像素着色器(以及最近的射线着色器,即光追着色器)处理,它处理涉及照明和纹理的数学运算。最后,计算着色器都是做通用的算术和逻辑处理,而不是任何特定的图形。
现代3D游戏使用成千上万的着色器来计算屏幕上显示的图像。有些是非常短和简单的,其他的可能是非常长和高度复杂的,吸走了GPU可以提供的所有资源。
而每一个着色器都需要在GPU对其进行处理之前进行处理。
2、着色器编译:渲染预处理的“预处理”
那么我们再来看看游戏中着色器是如何起作用的。
像素着色器用于控制屏幕上单个像素的颜色和阴影,它们可用于创建各种效果。例如,用来模拟光与场景中不同表面相互作用的方式,比如光从闪亮的金属物体上反射的方式,或者阴影被移动物体投射的方式。
在第一人称射击游戏中,动态灯光效果可以为玩家创造更具沉浸感和真实感的体验。例如,像素着色器可以用来模拟火炬的闪烁光或枪口的闪光,或者为爆炸或其他特殊效果创建逼真的照明效果。
总的来说,着色器在现代PC游戏中扮演着至关重要的角色,帮助玩家创造出他们最喜欢的游戏所期待的令人惊叹的视觉效果。
不同优化的着色器对画质可以起到比较大的改变
由于着色器本质是在GPU上执行的代码,因此也少不了编译的过程。
编译是将源代码转变为机器可执行代码的过程。源代码可以用任何编程语言编写,然后变成二进制,由硬件执行。着色器也不例外,它们是用某种语言着色器语言编写的,也需要编译。
这里大家有兴趣的话,可以去下载一个著名的免费着色器制作软件ShaderToy(https://www.shadertoy.com/)试试,也可以直接在官网查看一个样例着色器的代码和实际效果。
小A使用这个工具的在线版本,着色器样例(https://www.shadertoy.com/view/7dSGW1)代码是用GLSL(OpenGL着色语言)和用于渲染的图形API WebGL编写的。
在页面上,你可以通过观看这个预览视频来了解这一切是如何创建的。
即使你不知道这些代码意味着什么,也没有关系。你的图形芯片也不知道。它可以执行所有的计算,但它需要得到二进制的指令。这些代码需要从WebGL编译成GPU指令,在任何使用GPU获得最终结果的情况下,编译工作由GPU驱动完成,CPU负责处理这一工作负荷。
这个ShaderToy的例子只使用了2个着色器,一个普通的桌面CPU只需要万分之一秒的时间来编译所有的着色器,而且只需要做一次,就是在你开始看演示的时候。
然而,把这个简单的着色器例子放到任何现代3D游戏,就完全是一个不同的故事。在庞大的开放世界中旅行,进入不同的关卡,或者与新的敌人作战,都需要游戏从存储驱动器中加载新的着色器,然后进行编译,再由GPU执行渲染工作。
一个3A大作的一帧画面,可能就会有上万个着色器在共同起作用。例如《赛博朋克2077》这种3A光追大作,就不得不使用了多层shader等极为耗费算力的新着色器技术。
一件《赛博朋克2077》游戏中的衣服,你能数清右边着色器视图中它使用了多少着色器吗?
游戏机上的游戏,如PS5或Xbox系列,通常都有预先编译好的所有可用着色器(尽管并不总是如此)。这是因为游戏机作为单一硬件,配置是非常固定的,而游戏机的开发规范使用的着色器也非常固定。因此游戏机上很少会出现一个游戏更新后会重新编译所有着色器的过程。
然而,PC在这方面是个大麻烦,因为有成千上万种操作系统、显卡以及驱动程序、着色器编写语言之间组成的着色器的组合。不可能为所有这些组合预先编译着色器,因此开发人员使用各种方法来解决这个难题。
它们必须现编译各种着色器。而这种编译方法的不同就导致了更新游戏后,编译过程占用资源情况下,对游戏体验的不同影响。
3、围绕着色器编译的问题
好了,假设你现在新装了一个3A大作,或者你的吃鸡游戏刚更新了维寒迪新地图。此时着色器就需要重新编译了。
着色器编译一种常见的方法是在游戏加载时转换所有将被游戏使用的着色器,这个过程有时是在游戏启动序列中,有时是在主菜单界面中,或者在初始关卡加载时使用。
最近大热的《霍格沃兹的遗产》游戏就是着色器编译的反面教材:它每次启动游戏时都要进行一次着色器编译
如果一个游戏有数以万计的着色器,在开始时编译它们可能会使这些加载时间过长。在游戏制作过程中,对着色器库的管理不善,只会使这个问题变得更加复杂,因为时间和存储空间将被浪费在编译那些永远不会被使用的东西上。
与此相反的方法是避免在一开始就转换它们,而是在游戏过程中需要它们的时候再进行转换。这显然会加快游戏的加载速度,但实时编译可能会在图形处理链中产生卡顿,因为CPU会突然同时运行着色器编译转换过程。如果你的CPU同时资源已经紧张或者本身性能不足,那么卡顿就非常明显。
这通常表现为游戏的平均帧率突然下降,这个问题的范围可以从单一的、瞬间的打嗝式卡顿到场景中长时间的卡顿,从而给玩家的游戏体验造成可怕的混乱。
例如小A有时候晚上也会和同事们开黑吃鸡,经常发现版本大更新了以后,在冲楼关键时候突然卡顿,变成了盒子。
而有许多游戏对着色器的编译采取了中间方法,在加载过程中或在主菜单界面中处理主要的着色器,并在需要时在游戏过程中处理其余的。但是,在PC平台上要做到这一点,本身就是一个挑战。
例如,《地平线零之曙光》和《死亡搁浅》的PC版,都是使用专有的Decima引擎制作的,它们的推出日期被不断的着色器卡顿现象所推迟,最后还不得不在上市后通过好几个补丁完成优化。
最精明的开发者(例如Infinity Ward,CoD的开发工作室之一)在从现代战争第一作开始就使用了很多技巧来防止代码转换中断渲染的流程,方法是将很多重要着色器编译工作隐藏在菜单、剪接场景、中层加载阶段等等。比如著名的雪橇追逐战,其实根本就没渲染雪橇的实体,只渲染了雪橇的车头部分。
另外,在UE4中制作游戏时,每个物体和环境部分的表面外观都是由称为材料的项目生成的。默认情况下,创建这些材料反过来会产生大量的着色器,其中许多可能是不必要的——比如某大逃*类游戏。
3、怎么解决着色器卡顿?
不幸的是,对于游戏玩家来说,你能做的并不多。由于是CPU在处理编译任务,尽量减少后台同时进行的其他任务量可能会有帮助,降低游戏的图形质量设置也是如此,但这几乎是用户能做的全部。
当然,也有少数小窍门:对于那些喜欢在标题界面进行着色器编译的3A大作,不妨在初次安装游戏或进行了游戏的大版本更新后,进入游戏后先别忙着开始游戏,而是在主菜单界面停留一段时间,可能会对着色器卡顿现象有所缓解。
很少有游戏提供一个选项来改变着色器编译的管理方式。前面提到的《地平线零之曙光》在最新的补丁更新后,将在主菜单中进行着色器编译,但如果编译时间过长,设置界面中有选项可以让你跳过它,或者在低端硬件上默认会这样。
另外,还有一种在线着色器缓存策略,在原则上是很好的,但在实践中却不那么好:
你可能也在想,某种在线服务,为自己每个游戏、硬件和驱动配置存储编译的着色器。Valve确实提供了这样的服务,作为Steam的缓存服务,但只针对使用OpenGL或Vulkan的游戏。但很多的时候,缓存总是显示为空。
steam可以设置打开或关闭着色器预缓存以及后台处理着色器功能
这是因为显卡制造商在这里也扮演了一个角色,是他们的软件在进行编译。AMD和NVIDIA的驱动程序将把经常玩的游戏中编译的着色器存储在电脑的一个文件夹中,但是当游戏或驱动程序更新时,这个过程需要重复。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved