本文转载自知乎文章《<原神>部分效果的个人理解》,作者Lucifer
地址:https://zhuanlan.zhihu.com/p/246531456
声明:《原神》系上海米哈游影铁科技有限公司版权所有。本文仅对游戏内出现的部分效果进行个人理解上的技术分享。本文并不涉及任何资源破解,解包等任何对该游戏的hack行为,因此并不保证与游戏中的实现方式一致。请自觉维护原著者版权。
以上!!!!
一、光与影
游戏中的影子大致可以区分为以下几类:
1.场景的静态烘焙阴影
游戏中的场景应该主要还是基于lightmap实现的静态阴影。对于植被并没有计算lightmap,其实我感觉可以在草等植被的下方利用AO去改善以下草等植被的光影效果的。
因为开放世界的超远视距,我猜测,游戏的lightmap是分3个级别的。近距离高精度的lightmap,中距离低精度lightmap,远距离烘焙顶点色lightmap。
诸如草这种植被,是不进行lightmap的烘焙的
近距离下,灌木丛还是有lightmap的
中距离下,灌木植被阴影消失
这种超远距离下的lightmap可能就直接烘焙到低模顶点色上了
这里顺便补充一点,因为时间有限,随便看了几个相关视频,所以并不清楚游戏中是不是有实时的场景光影,所以静态烘焙这部分也只是猜测。如果有实时的光影变化的话,我可以再提供几个思路,一个是distanceShadowMask的思路,就是远距离烘焙与近距离实时结合。另一个是预烘焙多角度lightmap思路,就是提前将阳光多个角度的lightmap进行预烘焙,通过插值进行过度。我记得哪个游戏好像用过,我有空找一下,后面补上。
2.静态物件模拟实时投影
因为草是不烘焙lightmap的,但阴影下的草又如何变暗呢?还有角色走到阴影下面,又是如何处理的呢?应该是使用的lightprobe,就是光照探针。
使用光照探针实现明暗处角色的区别,草也一样
光照探针沿着阴影边缘里外布置两排(保证暗部小球可以被阴影遮挡,有时候,可能会根据光照角度稍微倾斜,而不是上图的直上直下)即可实现这种效果
3.实时阴影
这部分主要用来实现可动物件对场景的实时投影。从我的观察来看,游戏中的可动物件的实时阴影是使用的ProjectShadow实现的。就是设置一个与光照角度一致的正交相机跟随角色进行拍摄,设定一定的拍摄范围,并在边缘进行阴影过度。然后使用Project将渲染的图投影到地面即可。好处是投影的距离可控,投影的物体和接收阴影的物体可控,阴影分辨率高,且不进行灯光深度绘制的草上也可以绘制阴影,一句话就是性能较好。
缺点自然是无法实现真实的阴影投射和在阴影下会产生双重阴影的问题。
因为阴影接收体仅包含地面和部分地表物体,因此,可动物件之间是不会相互投影的
游戏对双阴影进行了修复(其实也简单,接收阴影体设置好阴影最低阈值即可),细看还是能看到角色投到墙体上的更深的阴影。
PS:却产生了一个意外效果,模拟了AO,哈哈
4.体积阴影——云影
目前游戏中我看到的相关的体积阴影只有云的影子。说体积阴影貌似也不确切,毕竟云也是粒子面片,不是体积模拟。做法倒是也简单,所有非特效物体的材质中内置一张明暗噪波图,然后以世界坐标的xz进行采样,并添加UV动画,来模拟云投射到地面的影子。就是说与天上的云其实没啥相关性。
嗯,对于室内呢,肯定是不会受云的影子影响的,所以还需要增加一个判断。例如跟随角色增加一个垂直照射的相机采样当前位置的深度,采样云影的时候,计算以下顶点距离垂直相机的距离与深度比较即可(诸如雨雪等的垂直遮挡也是这么做)。或者更简单粗暴点儿的话,就是无视就好了,毕竟就算是现实中,大片云飘过,屋里也是会暗一下的。
5.角色脸部卡通明暗
米哈游的卡通渲染,在国内一直是做的很牛逼的了。尤其是脸部非常舒服的明暗过度以及鼻翼、三角区的特殊阴影表现。这部分因为比较特殊,我这里就详细介绍一下其相关原理。
这部分的实现,其实知道原理的话,也非常简单。
首先,卡通渲染的光照修正主要通过两种手段进行。
(1)最早期的日本的模型法线修正法。在3dsmax或其他三维制作软件中,对模型的法线进行修正,例如将脸部按照球面将法线整平。这部分可以通过脚本进行自动实现,从而提高效率。
(2)从罪恶装备X开始兴起的AO图修正法,这方法,崩坏3也采用了。就是通过绘制AO图的方式,对光照的数值进行修正。
这是我目前知道的主要的两种手段,一般来说,两种方法会混合使用。法线修正可以提供比较整体的卡通光照效果,而AO修正,则可以实现更加细节上的调整。
而诸如游戏中这种细节上的修正,更大的可能就是使用了AO图进行修正。将脸部三角区这种会更久的受光部分绘制浅色,将鼻翼这种更早进入暗部的部分绘制暗色,就能实现上图的效果。
但是,但是这里产生了一个问题。因为鼻翼一旦绘制了深色,虽然从受光进入背光时,会更快的进入,是对的。但当从背光进入受光时,因为鼻翼的角度,应该更快的进入受光才对,但这里,仍然会因为AO的问题,延迟了变亮的时间。三角区的问题也一样。从背光进入受光时,提前受光是对的。但从受光进入背光时,因为角度,是应该提前背光的,但浅色却让三角区的变暗延后了。
注:这里我从网上下载了《崩坏3》的部分模型,进行了相关测试。《崩坏3》系上海米哈游影铁科技有限公司版权所有。以下部分展示均基于该模型,仅作为技术交流分享。如侵权,我会接到通知后删除并替换为其他模型。
所以,这样简单的绘制一个颜色显然是不行的。道理这里也已经很明了了,光影的绘制,是需要基于受光和背光两种的。受光时,鼻翼更早进入亮部,背光时,鼻翼则首先变暗。三角区则相反。所以,可以绘制两张图,一张绘制受光情况,一张绘制背光情况,如下:
而判断是否受光,只需要判断相对于脸部的朝向,灯光的朝向向左还是向右即可来决定。
嗯,鉴于米哈游官方并没有进行相关解密,且我们项目也在使用我的方法实现该效果,所以这里就不进行更详细的说明了。
目前我本人实现的效果图
嗯,主要的光影部分就说到这里。下面说物理(模拟物理)。
这里主要说一些类似物理相关的东西,例如:IK,水纹,地表属性
1.脚步IK(反向动力学)
最早知道IK这东西,还是我在昱泉国际的时候,有幸参与了流星和射雕三部曲的相关开发。之后很久,在国内游戏中就几乎再也没见过相关的效果,直到今天的原神。它的效果就是如下:
这部分的实现,是通过检测玩家脚部的地面高度位置和法线,自动对脚部进行位置的修正。
据我所知,IK的调节是通过对新位置的多次迭代来进行修正的。
当然,游戏中,对地面的信息获取,可不止于高度和法线,还有其他东西,后面会说。
后来看到还有爬墙,还以为做了类似爬梯子的抓取位置定位功能呢。这样,手部,脚步IK就全了。不过结果并不是,只是墙面的UV进行了对齐。
2.水纹
当角色从水里移动时,水面产生的涟漪。不过游戏中只是播放了粒子动画,且涟漪也是正圆型的简单涟漪。
其实也可以试试,实现一下三角型的涟漪,不是更有感觉吗?
美术绘制三角形涟漪纹理,做类似圆形涟漪相同的扩散粒子效果(或者用UV序列帧实现)。然后程序端,根据角色的移动与否,播放原型或三角形粒子特效。如果是移动的话,还得在播放三角涟漪效果时,根据上一帧的位置,对粒子特效进行一定角度的旋转,让三角涟漪的顶点一直朝向运动方向。
3.地表属性
游戏中,地面是分为很多种类的,且人在上面会有不同的属性或行为。例如水面会潮湿,湿地会有脚印,干地跑动会有尘土,草地会有碎草等。
这部分实现其实不难,主要在于工具流的实现。
这里说下我的方案:在刷地形纹理的时候,将地表的纹理属性绘制到纹理的A通道,例如:像素颜色0~10表示湿地,30~40表示干地。然后正常进行地表纹理的刷制。shader中使用开关进行地面A通道值的绘制,并根据混合纹理的权重,取最高权重的纹理A通道值作为地面A通道的主属性。并根据权重值,对属性值进行0~10的衰减。例如:该位置通过湿地和干地纹理进行混合,混合值为湿地0.8,干地0.2。则该位置的A通道主属性值就是0~10的湿地。再假设权重值从0~1对应属性值进行10~0的衰减。则这个位置的属性值就是8。
地表制作完成之后,就可以使用工具,将地表A通道的值烘焙到地表顶点色上了。
然后,游戏中就可以在修正IK的同时,返回角色位置的顶点颜色,来进行对应地面属性的表现了。
当然还有很多办法进行实现,例如摆放属性标识面片等。
下面说一下游戏中的植被——草。
游戏场景中是存在大面积,很密集的草地表现的。这部分如果使用通常的渲染方式,消耗是很大的。要实现甚至在手机上也能运行的效果,只可能使用ES3.2才可以使用的GPU实例化渲染了。
目前Unity一共支持三种GPU实例化渲染接口,
Graphics.DrawMesh
(https://link.zhihu.com/?target=https%3A//docs.unity3d.com/ScriptReference/Graphics.DrawMesh.html)
Graphics.DrawMeshInstanced
(https://link.zhihu.com/?target=https%3A//docs.unity3d.com/560/Documentation/ScriptReference/Graphics.DrawMeshInstanced.html)
Graphics.DrawMeshInstancedIndirect。
(https://link.zhihu.com/?target=https%3A//docs.unity3d.com/560/Documentation/ScriptReference/Graphics.DrawMeshInstancedIndirect.html)
相比来说,Graphics.DrawMesh实现最简单,unity内置的材质instance就是这种。但相对来说,性能也最差。
Graphics.DrawMeshInstanced相对来说实现比较复杂,需要手动传入各种渲染信息,且存在同批渲染上限,但性能比Graphics.DrawMesh要好出不少。
Graphics.DrawMeshInstancedIndirect的实现最为复杂,需要自己申请参数缓冲区进行传参。但优势就是没有同批上限,性能最好。
几年前我对三种草进行测试的时候,数据如下:
我机器显卡1060,40000颗草不进行裁剪,开启实时阴影,且实现与人的交互。Graphics.DrawMesh是4帧左右,Graphics.DrawMeshInstanced为57帧左右,最高性能的Graphics.DrawMeshInstancedIndirect为90帧左右运行。
然后再回到游戏中。
貌似游戏中的草和角色的交互表现比较弱,也可能是我没看出来。然后说一下草的燃烧效果。
这个效果的实现原理上来说其实也比较简单。火焰其实和草并没有真实的交互。燃烧效果是技能释放位置和半径区域内,固定间隔的随机位置摆放火焰特效。如果该位置有草,就播放燃烧粒子特效,没有就不添加特效(如何判断是否有草可以参考地表属性部分)。
然后草的燃烧枯萎效果,其实就是在草的shader中,添加一个宏开关,当需要播放燃烧枯萎效果时,将开关打开,然后根据传入的技能范围,判断草是否处于该位置,来在普通草纹理和枯萎纹理(或乘上枯萎颜色)中进行权重过度即可。消失过程,可以使用UV从上往下的根据时间的discard。追求效果,还可以在切口处叠加一个锐利的噪波来实现燃烧狗牙效果。
1.地面属性互动
说起地面属性互动玩法,原神刚爆出这个玩法的时候,一堆人说抄袭塞尔达巴拉巴拉,云云的。
嗯,怎么说呢,项目组肯定是很大程度上参考了塞尔达的各种效果和玩法,但这并不应该是抨击游戏的一个点不是?
说句不好听的,就这种地面属性互动的玩法,我也可以说塞尔达(2017)抄袭神界3原罪(2015),神界3原罪抄袭激战2(2013),激战2抄袭深渊传说(2005),深渊传说抄袭重装机兵(1991)呢。玩法嘛,咱就没必要追根溯源了,用自己游戏的方式呈现给玩家,让玩家能乐于其中,这就够了啊。
回到实现上,这里说一下最常见的冰效果。玩家释放冰属性技能以后,在水面上会结冰,玩家可以站在上面。特效表现上,这里使用的是Mesh面片贴地的方式实现的,而不是投影或decalMesh。
贴地的面片会和其他物体产生穿插
嗯,既然是Mesh嘛,那冰上的一些效果就可以通过检测Mesh的方式去各种实现了。
2.深度和扭曲
游戏中是开启了相机深度的,这样,就可以实现诸如水边和粒子交界边缘的柔和过度了。
且采用了GrabPass(或RT方式)实现了水下的扭曲和散焦光斑。
3.云海和雾
原神沿用了崩坏3的一贯做法,使用粒子面片的方式来实现云海的效果。
估计项目组应该也尝试过光线步进的做法,不过要实现这种卡通风格的效果的话,可能就不太理想了。
游戏中的雾应该也是采用的距离+高度雾,叠加粒子雾效的扰动。不过整体使用了大气散射的效果,所以空间感和颜色及光感上表现的更好。
最后,说一下开放世界
策划相关的开放世界,可以参看我之前的帖子,这里就不说了。
简单说一下开放世界的渲染和技术实现的一些东西。
1.加载
开放世界的游戏不同与传统的关卡类的游戏,它并没有场景加载单元的存在。换句话说,游戏展现在玩家面前的就是整个游戏的世界,几乎所有可视资源都要进行加载。这种体量按照普通的方式进行实现,显然很不现实。米哈游从崩坏3开始,就在尝试做开放世界的相关东西。而其中的大头我估计就在资源的如何合理加载上。
一般来说,大世界游戏,会将地表进行切块处理,并将地表块上相关的资源(物件,纹理,光照等等)进行绑定。然后根据玩家所在区块,以九宫格方式进行加载(就是会预先加载除玩家所在区域外的周围几个区域)。再根据视锥,对前方额外的可视区域进行低精度加载。
虽然说起来很简单,但里面真正的细节很难处理。例如:区域交界的光照,阴影纹理如何生成,如何消除接缝,如何进行距离的Lod过度。加载和卸载的策略又如何,Lod策略又如何。相关的美术制程和工具流又如何实现,等等。或许只有经历过的人才会清楚其中的痛苦了。
2.性能
除了加载能搞定的一部分外,还有加载后的超视距的渲染压力是需要处理的。别的不说,Unity的整个地形系统就要重写。地形Mesh需要根据距离进行自动Lod,材质和纹理也需要进行相应的Lod处理。
然后就是各种Lod的优化策略。例如传统的减面Lod,各种遮挡剔除(设置Collider,设置Area和Potal),远距离的imposter策略等等。
这些每一个系统,Unity都没有很好的解决方案,都需要自己去实现或者优化。而这些还都需要配套的美术工具让美术进行最优的设置。
所以,开放世界的游戏,可真的不是想做就能做的啊。
先这些吧,后面想起什么再进行补充。
还是那句话,以上都是我基于视频效果的个人解析。并能不保证和官方一致甚至是正确性。还请谨慎参考。
最后,尊重原著,尊重知识产权,不要对游戏进行违规操作和讨论。感谢。
下面我补充一些评论中的问题:
1.为什么反编译、解包别人游戏这么普遍了,我这里却禁止讨论。
我不会评价这种行为的对错好坏,国家之间尚存在信息谍战,我当然知道这种行为的普遍。但普遍并不表示就合理,就像996。
当游戏开发商们的所有技术,所有经验都不再称为技术壁垒的时候,只会产生两种结果:
投入产出不成比,不会再有公司花精力去研究新东西,技术裹足不前。
天下一统,没有了多样性,失去了未来进化的可能。
所有的恶果,最后会毫无保留的奉还给整个游戏业。
我这里都是基于我自己的知识和游戏视频中的效果进行的猜测,自然和他们原本做法会有偏差,甚至大相径庭。但却产生出了更多实现的可行性猜测。
最后,我是基于别人的作品,分析别人的作品,相互的尊重应该是我起码的底线。
2.移动平台效果会怎样,如何看待多端。
其实这个游戏多平台的意义并不在于或者是说重点不在于多平台上的美术表现上,而是它打通了不同平台之间的网络壁垒,为多平台游戏模式协作提供了可能性。
举个简单栗子,我在PC平台上爽战斗,在移动平台上看剧情做养成,在游戏机平台上多手柄的家庭互联,一个游戏,N种模式,彻底霸占你的所有时间,哈哈。
3.如何评价原神中,米哈游的技术实力体现。
首先,卡通渲染的效果,目前来看,在经历了无光,受光,描边,法线,3S,pbr,多材质混合,大气等效果的进化后,也逐渐进入了一个瓶颈期了。
后面大概率会往两个方向走。一是更风格化的美术,例如柔和油画,国画,厚涂等效果风格。二则是基于pbr理论的风格化材质,例如卡通毛发,卡通丝绸塑料等材质区分表现。而米哈游应该是精于第二条路,但会更多的受限于平台性能。
其次,本游戏既然多端互联,又是开放世界。所以,美术效果上必然进行了妥协。不能充分体现米哈游的技术实力。
要说的话,这个游戏可能更多的体现了米哈游对新游戏模式的快速吸收实现,美术工具流的完善和对引擎开发改造上的能力了。
投稿邮箱:[email protected]
商务合作:Amber(微信:lcxk6876767)
其他合作:老林(微信:sea_bug)