为什么视频游戏图形仍然是一个挑战?

2020-12-29 04:45:08

这篇文章将涵盖创建新的渲染/图形技术和算法时要考虑的挑战和生产方面,尤其是在实时渲染的应用研究中。我将基于我的个人经验,在《巫师2》,《刺客信条4:黑旗》,《孤岛惊魂4》和《战神》中工作。

这些挑战中有许多很容易被忽略-它们是生产中的实际问题,但只有当您仅了解这些技术,或者您从事纯研究,撰写论文或创建技术演示时,并不一定存在。

我看到过这样的陈述:“为什么这种出色的研究技术X不在生产中使用?”既来自游戏玩家,也来自具有学术背景的同事。总是有一些很好的理由!

这篇文章还受到我前段时间在我的玩笑推文中的启发,该推文是通过“取消”大多数渲染技术来使他们成为图形程序员而变得聪明成熟的,因为这些渲染技术不会在叶子上起作用。 yes是的,在这篇文章中我将再次回到植被渲染。

当我听到有关“摄影测量,光线追踪,神经渲染,[插入任何其他新主题”将如何成为渲染和替换所有内容的通用答案”的讨论时,我也会想到这个主题。剧透警报:不会(很快)发生。

渲染工程师,尤其是在职业生涯早期的工程师,他们还没有建立直觉,

那些对游戏图形(或一般来说是实时图形)感到兴奋和关心的人,并且想了解一点“香肠的制作方法”。有些概念可能太技术性,但是可以随时跳过这些概念。

请注意,我没有将“纯粹的”学术研究人员放在上面的列表中-因为我不认为纯粹的研究应该考虑太多的障碍。基础研究的作用是启发和创造理论,这些理论以后可以由生产专家来生产。

但是,如果您是一个纯粹的研究人员并且以某种方式来到了这里,如果您对从构思或论文到产品的漫长过程中可能会遇到哪些问题感兴趣,以及为什么大多数新的真正优秀的研究永远不会找到它在产品中的位置)。

非常重要的说明–我要描述的“障碍”都不是破坏交易的因素。

远非如此-成为最先进技术的最成功的技术违反了许多限制!这仅意味着这些挑战将需要以某种方式加以克服-手动解决方法,功能独占,忽略问题或仅在特定情况下应用。

我将首先描述用例-技术的潜在用途以及它们如何影响潜在的需求和约束。

“用例”类别应对其约束的“严重性”进行一些解释和描述。

技术演示是最简单的类别。如果您的整个产品都是给定技术的演示(无论是用于基准测试,展示一些新研究,艺术演示),则大多数考虑都将消失。

实际上,您可以进行所有改装:从演示概念,艺术品本身,照相机轨迹到最佳展示技术,避免出现任何问题。

主要考虑因素将围绕性能(不稳定的技术演示可被视为技术失败),并与能够进行展示的艺术家紧密合作。

其余的部分?轻松完成,编写一次性代码–只是不期望将技术演示转换为可用于生产的功能既简单又容易(更像是剩余的99%的工作)。

难度的下一个“提升”是创建一些一次性的特殊功能。可能是某些视觉特殊效果发生在单个场景,游戏介绍或与其他场景不同的单个关卡中。在这种情况下,功能不必太“健壮”,而通常可以替代许多其他功能。

例如,我在《刺客信条4:黑旗》中丛林中的照明。

丛林通过特殊的水流走廊与其他开放世界“隔离”,我们完全替换了其中的整个照明!我们没有依赖树影地图和全局照明,而是创建了伪造的“焦散”,看起来更柔和,并且在我们的体积照明/大气系统中表现得非常好。它们不仅看起来更好,而且速度更快-显然仅由于这些特殊条件而起作用。

稍微有点苛刻的功能是仅电影功能。电影技术有点不同,因为它们可以由电影艺术家严格控制,并且它们在照明,角色放置或动画等大多数方面都是伪造的,就像在常规电影院一样!电影通常具有快速的摄像机剪切功能(可用于隐藏任何过渡/弹出窗口),并且由于具有更可预测的性质而具有更多的计算预算(甚至在以30fps渲染的60fps控制台游戏中)。

“常规”功能-照明,粒子,几何体渲染-是最难的类别。他们需要要么非常易于实施(大多数障碍/问题就很容易解决),要么提供远远超过现有技术的巨大收益(以解决采用难题),要么让一些非常激动的团队为之奋斗(永远不要低估推动力)真正想看到某些事情发生的工程师或艺术家!)。

矛盾的是,如果某项是关键或与众不同的功能,则可以减轻许多困难。让我们以虚拟现实为例–立体声,性能(低延迟)和完美的AA而不会弄脏(宁可不用TAA),它们是功能,绝对是体验​​的核心。这意味着您可以完全忽略例如渲染树叶或某些看起来令人讨厌的动画–因为沉浸和在那里的VR体验更为重要!

让我们看一下新开发的功能与其他一些常见“功能”的兼容性(“功能”之间的区别,以及下一个较大的“管道”部分是模糊的)。

功能并不是挑战中最重要的-可以说我最后要讨论的类别(“过程”)是。但是这些很有趣,而且很容易看!

密集的几何形状(例如树叶)是激发这篇文章的“特征”,是大多数渲染算法的敌人。

主要问题是,由于几何形状非常密集(大量重叠和小三角形),许多“优化”和假设变得不可能。

可以看到的密集几何体(例如草叶)与许多技术不兼容,例如,光照贴图(每个草叶texel存储一个预先计算的照明会非常昂贵)。

如果游戏在这里到处都有树,或者放在城市中,那么这可能不是问题。但是对于任何“自然”环境,任何功能的大量生产都将结合起来使其与树叶很好地共存。

Alpha测试是上述功能的扩展,因为它禁用了更多硬件功能/优化。

阿尔法测试是一种技术,当像素从纹理或像素着色器计算中评估“阿尔法”值,并且基于某个固定阈值时,不会渲染/写入该值。

它比alpha混合快得多,但是例如禁用了早期的z写操作(早期的z测试是可以的),并且需要光线跟踪命中着色器并读取纹理来确定纹理像素是否不透明。

这也使抗锯齿变得非常具有挑战性(忘了常规的MSAA,您必须模拟alpha覆盖)。

有关某些问题的描述和直观的视觉解释,请参阅Ben Golus的此博客文章。

大多数动画师都使用“骨骼动画”。创建装备,蒙皮网格,为骨骼设置动画。当您创建一种新的渲染网格的技术时,它依赖于一些繁琐的预计算,动画师是否能够对其“变形”?他们能够将其插入复杂的动画混合系统中吗?它如何适合他们的工作流程?

请注意,它也可能意味着刚性变形,例如旋转的轮子–将复杂的对象作为蒙皮的整体进行渲染要比拆分它们便宜得多。

下一类动画是“过程性的”和非刚性的。程序动画对于“无休止”,相对简单且不应太明显地循环的动画很有用。最常见的例子是叶片微光和树枝运动。

观看有关中间件Speedtree运动的视频-那里的所有运动都是由一些数学公式描述的,而不是“手工制作”的动画,看上去奇妙而合理。

一种适用于树叶(再次!)等元素的良好渲染技术需要支持以任意方式(从简单的微光到大弯角)进行替换的选项–否则世界将看起来“死”。

非刚性动画,修改顶点位置,甚至流式传输整个顶点缓冲区都会导致光线跟踪的麻烦-因为它需要每帧重新调整空间加速度结构(对于RT至关重要),这是不切实际的。

动画的另一种类型是在对象表面上设置纹理动画。这不仅用于模拟霓虹灯或电视,还用于例如雨滴和雨水波纹。技术人员和FX艺术家那里有许多惊人的技巧,从滑动和缩放UV,具有流程图到直接为“动画书”纹理设置动画。

假设摄像机的视点相对固定,许多技术都可以很好地工作。从艺术家的技巧和骇客,到冒名顶替者渲染之类的技术。

一些渲染加速技术针对半约束视图进行了优化(例如我的同事从事的Project Seurat项目)。适应任何技术时都应考虑相机自由度。基于广告牌的树从远处看可能不错,但是如果您离得很近,或者可以从更高的角度看到场景,则树会完全断裂。

另外–想像一下早期的摄影测量法,将镜面反射捕获为纹理,当您稍微改变视点时,看起来绝对是错误的。

照明的动态程度如何?有一天的动态时间吗?天气系统?用户可以打开/关闭灯吗?特殊效果会投射灯光吗?是否有动态阴影投射对象?

对于大多数当代实时渲染产品(如游戏),答案将是“很多”。特别是倾向于创造更大的生活世界。

这并不一定排除预先计算/烘焙的解决方案(例如我们支持AC4的动态计算的GI预先计算的GI解决方案!),但需要额外考虑。

仍然有许多新出版物发表,描述了解决这些问题的新方法和解决方案(结合了光传输和动态照明的预计算)。

阴影,另一个永无止境的话题和未解决的问题。大多数游戏仍然使用预先计算的阴影和阴影贴图的混合物,有些游戏开始尝试使用光线跟踪阴影。

每当您要插入要渲染的新型对象时,都需要考虑:它是否能够接收来自其他对象的阴影?它会在其他物体上投射阴影吗?

对于粒子或体积,答案可能并不容易(因为阴影贴图不支持部分透射率),但是像网格细分或视差遮挡贴图这样的“简单”技术也会在阴影投射器和接收器之间造成不匹配。造成阴影伪影!

最后,如果环境是动态的(通过强制更改,销毁游戏故事,或者在极端情况下通过创建用户内容),则依赖脱机预计算的任何技术都将面临挑战。

从依靠预计算的照明/全球照明系统的角度来看,在战神破火山口湖和桥梁上,水位和桥梁旋转的移动是整个生产过程中最大的问题之一。没有“通用”解决方案,它全部依靠手动工作以及流式传输/管理加载的数据…

最后,还有透明的对象和粒子–一个非常特殊且与众不同的类别。

他们不编写深度或运动矢量(稍后会详细介绍),需要从头到尾进行排序,需要对每个最终输出的批处理进行许多评估,包括昂贵的计算和纹理采样器,通常以更简单的方式点亮,需要对阴影...由于过度绘制,它们也非常昂贵-一个输出像素可以对alpha混合粒子的像素着色器进行许多评估。

历时数年的工作(在我从事的大多数项目中,有N位专业的FX艺术家以及至少一位专业的FX和粒子渲染工程师)不能被新引入的技术丢弃或忽略。

以上是要考虑的一些产品功能和要求。但是,一些更深层次,更底层的含义呢?渲染单个帧需要数十个离散通道,这些通道被设计为可以相互配合工作,需要数十个中间输出和缓冲区。让我们看一下要考虑的部分渲染管道。

我在上面提到了alpha测试,alpha混合,排序和粒子方面的一些挑战。但是,当您意识到许多功能需要每个对象的深度缓冲区中的精确Z缓冲区值时,挑战就变得更大了!

那种奶油般的景深效果和许多其他相机效果?大多数需要深度缓冲区。老派深度迷雾?需要深度缓冲区!

好的,这看起来像是一个交易突破,因为我们知道Alpha混合对象不会写这些对象,并且不能有对应于它们的单个深度值……但是游戏精通烟雾,镜子和伪造。 🙂如果您真的很在意,可以手动创建深度代理,手动对一些东西进行排序和重新排序,alpha混合深度(错误,但看起来可以),调整景深,直到工件不会分散注意力……很多手动工作和难题”哪种妥协还不错”!

一个相关的流水线组件是运动矢量的写入。虽然深度对于许多上述基于深度的效果,适当的遮挡,屏幕空间折射,雾等至关重要,但运动矢量仅用于“两件事情”:运动模糊和时间抗锯齿(请参见下文)。

运动模糊似乎只是“一种效果”,但是减少运动模糊和减少通常的廉价感觉至关重要(请参阅电影24fps半快门运动模糊)。

(有些吹牛/圣诞节的怀旧之情:对运动模糊的思考使我感到怀旧-运动模糊是我被媒体采访的第一个功能-我仍然对23岁的我生活在东欧感到自豪,但事实并非如此。甚至完成了大学的感觉!)

产生准确的运动矢量并非易事-对于每个像素,您都需要估计对象的这一部分在上一帧中的位置。这可能意味着再次重新计算一些动画数据,将其存储到前一帧(额外使用的内存),或者可能太困难/不可能(处理遮挡,阴影或纹理动画)。

在AC4上,我们几乎对所有事物都实现了它-除了海洋,它忽略了TAA和上面的运动模糊问题……

临时抗锯齿…是过去几年渲染引擎的最大成就之一,但也是问题和工件的最大来源之一。在这里不讨论是否有替代方法,或者它是否是一个好主意,但这将在这里停留一段时间-不仅用于抗锯齿,而且还用于蒙特卡洛技术,超级采样,随机渲染中的样本时间分布,并允许缓慢的事情变为可能或实时获得更高的质量。

对于许多新的渲染技术而言,这可能是一个问题–不仅是因为需要非常好的运动矢量,而且它的性质还可能导致产生一些拖尾的伪影,甚至抵消诸如闪闪发光的雪(闪烁,火花,枪口闪光)的视觉效果等等)。

大多数引擎使用延迟着色(是的,有很多例外,它们看起来和表现都很棒)。它具有许多理想的属性,并且可以“提升” /解耦渲染的各个部分,简化了贴花之类的事情,可以很好地减少透支。

但是,以GBuffer形式出现“瓶颈”,并且照明无法访问任何其他数据可能会非常受限制。

新的阴影模型?新的查询表?预计算/预烘焙并存储在顶点或纹理中的新数据?需要将它们压缩到GBuffer中!

现代GPU可以轻松处理分支和发散(前提是存在“某种”一致性),但它会使管道复杂化并导致“专有”功能。

例如,在《战神》中,您不能与布料/反射镜面模型同时使用次表面散射,因为它们(重新)使用了GBuffer中的相同插槽。无论如何,GBuffer本身都占用大量内存,并且还有更多互斥的功能–我在笔记本中写了许多可能的组合(IIRC有6位仅用于编码材料类型及其功能),并“协商”有不同用途和需求的不同艺术家。

在大多数电影中,始终会有大量的摄像机镜头剪辑以显示不同的角色,不同的场景视角,或者可能同时发生动作。这是一种广泛用于各种电影院的工具(也许Dogme 95或Birdman except除外),如果电影艺术家想要使用它,则需要对其进行支持。

但是,当相机使用TAA /时间超采样的所有每个像素的时间累积历史记录进行剪切时,会发生什么?突然看到全新视图的所有纹理流如何处理?与视图相关的摊销渲染,例如阴影映射缓存?所有这些都可以解决,但也需要大量工作,否则可能会导致新框架的延迟/弹出/成本过高。我的一位同事还指出,这是物理或动画方面的问题–通常当相机切割并且动画师调整了某些位置时,您会看到物理物体“沉入其中”,例如项链在角色上移动。另一个浸入式断路器需要另一系列的自定义“ hacks”。

相反,缺乏镜头的裁剪也很困难(例如在《战神》中),尤其是对于电影照明,良好的动画,转场等。无论如何,这两者都需要解决/解决。甚至值得在渲染器中添加标志“相机被剪切”。

游戏通常不会呈现您在摄像机视锥中看不到的内容-这显然是可取的,因为为什么您会浪费时间呢?

现在,它变得更加复杂!为什么要设置不可见对象的动画?不这样做可以节省大量CPU时间。

但是,在主视图中可见的内容只是故事的一部分–反射,阴影……我不能指望在“ T姿势”(默认姿势为角色没有动画)。可以“触摸”任何物体的光线追踪在这里提出了新的挑战!

截锥剔除是平截头剔除之后的下一步。您不想在相机外部渲染物体吗?当然。但是,如果在镜头前有一个巨大的建筑物,那么您也不想在其后面渲染整个城市!

健壮的遮挡剔除(连同下面的LOD,流等)在许多方面都是无法解决的问题-所有现有解决方案都需要折衷,预先计算或极其复杂的管道。

在某种程度上,遮挡剔除系统是一项新的渲染功能,必须经过我在本文中列出的所有步骤! 🙂但是,鉴于其复杂性和许多解决方案的总体脆弱性-需要考虑的另一个方面,我们不想使其变得更加困难。

任何需要一些计算预算来渲染和占用内存的技术都需要随距离适当地“缩放”。当渲染的对象在100m之外且占用几个像素时,您不希望它占用100MB的内存或它的渲染/

......