notion image
元素界王 - 徐文轩​
本文中所有美术图片,模型资源等版权归任天堂所有,这里只做学习和研究交流使用,侵删。
其中要包含很多朋友提供的美术资源,相关版权归创作者所有,这里只做学习交流使用。
塞尔达荒野之息始终是我玩过的最有趣的游戏,是各种技术与艺术达到均衡的典型。
如果能自由去做一些游戏技术研究,我首选塞尔达,它充满了魅力与智慧。
塞尔达很庞大,也很复杂,触及到各个领域,图形学等领域的应用更是开了很多业内先河
这里记录一下局部的荒野之息在效果方面的研究和复现
notion image

角色渲染

塞尔达卡通渲染角色并没有太多特殊性,都是常见的卡通 shader 光照模型
除了最基本的赛璐璐卡渲,NDL 明暗,RampMap blinn 高光色块化外
notion image
notion image
notion image
notion image
最主要的其他特性有
1 - 适应各种不同的环境和时间段,间接光照随时被环境影响
2 - 完全在投影内,如完全处于山体的阴影内,要做双层明暗,而不是就完全处于投影内
3 - 金属材质的特殊性 ramp
4 - 角色相互的投影对金属材质的影响
5 - 逆光内描边
6-boss,守护者等特殊化处理
notion image
notion image
notion image
notion image

武器效果

notion image
notion image
notion image
武器是常规消耗品,是很常见的,但在元素属性武器充能方面可算有足够的特色和交互性
常规属性武器大致有 4 个特殊的通道和游戏的玩法体验 I 相关
用来控制
1 - 充能的形状
2 - 充能的进度
3 - 满能量状态的动画效果
4 - 能量涌动的随机噪波感
notion image
notion image
notion image
notion image
notion image
属性武器和远古武器是很类似的,但有部分特殊性
远古武器的出现过程,是一个符合动画
既有骨骼动画的控制也有材质动画的控制 + 少量粒子
远古武器散发诡异能量的颜色外,快速的反溶解也有一定视觉看点
其中 远古大剑,电锯是一个特例,用 UV 滚动模拟电锯
notion image
NPC - 怪物
notion image
notion image
notion image
守护者有这么多版本,我也没想到啊
notion image
notion image

攀爬动画系统

动画系统绝对是塞尔达有特点,且是难点的系统
他的复杂不仅在于动画的状态机系统,也包含在关卡场景碰撞体的工业化生产管线中
场景会因为这套系统,设计需要在规则下严谨设计制作,也需要高精度碰撞体生成的方案,也可能和 LOD 是同一套模型
动画系统是一个巨大的工程量,不断游玩,不断测试,不断改进
动画系统和场景的交互主要可以区分为主动交互和被动交互
notion image
notion image
notion image
主动交互就是玩家刻意操作触发的交互体验
被动交互是让玩家无须特殊操作,林克就可以很协调的与场景发生肢体关系
比如移动的时候自动翻过阈值低于一定高度的障碍物
比如四肢手脚去适配场景的各个模型表面
还原的时候我们先从 unity 商店的一个 climb 系统开始修改,有了一个不错的基础框架比一切从头来要容易很多
但细节几乎都不同,做了研究分析后再逐步往塞尔达的特性和动画节奏靠近。
notion image
notion image
notion image
这里的重点就是动画状态其实是由对环境的测算决定的
按键,环境,被攻击,武器类型,地形材质,攻击硬直,重力,坡度,飞行海拔
甚至温度都可以是外部输送给状态机的 trigger 变量
大概几十个外部状态参数决定当前的角色应该处于什么状态机
notion image
notion image
notion image
notion image
状态机的整理和动画参数的控制主要是小林和荣华同学研究的,在此感谢。

特效效果

从用途分为,特效大致可以分为环境特效与战斗特效
从交互分,可以分为交互性与非交互性,交互性就是。比如点火,风力吹动等
战斗技能特效应该是网上有很多人做过类似的效果了,比如盾反,爆炸箭等
这里也主要展示下技能效果,特效 shader 并没有多么深的技术点,
最大的难点可能就是全局环境的影响,比如支持全局风力,比如下雨天闪点加强,火减弱等
ASE + 一点点代码基本就可以全部搞定。
notion image
基础粒子效果,所有引擎都差不多,随生命周期做各种常规属性衰减,或自定义曲线衰减
notion image
notion image
notion image
notion image
塞尔达基本都是 UV 动画噪波控制溶解形状变换,基本不可能用帧序列。
子弹时间缩放等必须保证特效可以减速到 10 分之一,没有跳帧现象,必须是平滑的溶解和高清晰度的轮廓

场景 24 小时环境

开放大地图场景,无论是工作量和技术含量都是一个巨大的门槛
很难去实现一片完整区域的交互和精确关卡的
只做了少量的研究实践,肯定先确定是 24 小时的实时光照系统为基础
所以的设计和渲染要以此为前提,环境色和灯光强调,角度无论如何变化都要把 shader 输出控制在一个合理的范围内
notion image
notion image
360 度光照与明暗交替对角色的影响
notion image

草海

草海等 GPU instance 的案例很多,其中有难点与特点的地方应该是和地表,阴影的融合
无论地形如何丰富多变,草始终处于无地面接缝的状态
草的根本和地表公用一个随机扰动色,可以在 SD 里很容易做到。
草的顶部再加入一个自己的扰动噪波色,高光只做顶部,不做根部。
notion image
另外风力随天气会有巨大变化,要体现出在微风到强风中的不同扰动感。
notion image
优化是个大问题,数据量真的太大了,做小地图还可以,大地图光草的坐标信息估计都是几十 M。
我推测任天堂可能不是用坐标去记录每一株草的三维模型,应该用一个 mask 图对应到地表区域和密度,实时创建生成
所以这个 mask 图记录了整个大世界的所有草的分布密度,不然以荒野窒息的密度和规模来说,草坐标就得几十 G 的数据。
树相对很简单,可以用 ramp 图,也可以自定义不同明暗层级的颜色,为保证团簇感,法线转化呢肯定是要有的。
notion image

天气效果雨水溅落

塞尔达的这个溅落雨滴处理是很惊艳,也很合适,因为植物被无法去做类似涟漪或者流下的表现。
仔细观察才发现是个后处理,只在有深度差且一定距离的范围内会溅起水花,往上偏移出一个区间。
水花的小点很随机,很乱序,把握好密度节奏,SD 生成一个噪点或者重复乱点序列,就会有不错的效果。
notion image
复现如下
notion image

瀑布效果

在一个叫 rime 的游戏技术分享中,学到了不少技巧,在它的基础上稍微改动即可控制各类瀑布的造型与风格
这里和塞尔达并不是很一致,而更加的吉卜力。
notion image
瀑布最多分成 6 个部分
1 - 流水主体 2 层错位
2 - 顶部的衔接与高光
3 - 末端白色顶点偏移段落
4 - 溅起的白色水体,粒子发射置换模型,和水下部分也可以做在这个部分
5 - 扩散并逐渐溶解断裂的涟漪
6 - 粒子水花,更细致可以做粒子泡沫与水下翻腾的气泡
目前瀑布对水面本身的流向起伏,流速完全没有影响。理论上应该有一些影响会更好
notion image
还有很多场景物件效果可以去研究,场景资源的规格,贴图的用法也是相当灵活,各种组合,各种技巧都用上了。
但没什么特别,看看各类通道的做法,基本可以逆向。
notion image
notion image
notion image
notion image
开放世界大地图 和 神庙,场景特效,交互细节还有很多很多值得用心研究的点,等未来研究后,继续更新笔记
之后会交互性效果上和开放世界程序化生成上做更多研究与实践。
最后感谢给予支持的小伙伴,和一起探讨问题的同事!
notion image
凯丁
notion image
主要的思路: LOD,Instancing,拉长的 Quad
蓝色 (包括蓝绿色) 部分是随风动的草,红色是不动的草体贴片,蓝绿色更接近相机
notion image
草体 mesh 会根据多张 TerrianInfo 相关 texture 来生成,所以需要 VTF 支持,比如交互用了一张固定频率更新的 NormalMap,高度用 HeightMap
由于所有草体颜色和 Terrain 颜色很接近,所以红色草和蓝色草之间的切换 (也就是 LOD 切换) 相当自然
根本不需要 Geomerty Shader,根本没用细分
没有太多神奇的技术,但是有很多神奇的经验!
其他细节就不说了,看汇编太累
但看完就觉得 很多细节上就能体现:老任做游戏,真的是完全是从用户角度和游戏性出发!

很多人问是用什么工具分析的,这边大概说一下,以后得空了在慢慢补全:
WiiU 模拟器 Cemu 已经很完善了,有兴趣可以自己截一帧看,不过 Cemu 渲染底层采用的是 OpenGL,所以 GPA 是看不了的,可以用 Nsight 来看;不过由于是模拟器,Shader、Mesh 以及 Uniform Variable 都是按 int 保存读取,需要一些技巧和耐心,尤其是 Shader,截取一段各位看看
以上只是整个 VertexShader 量的 1/5 左右
基本上是逐条从汇编直译成 GLSL,数据都是 Int<->Float 互转,有耐心和好学的同学可以一看
notion image
李喆​
最近正好在思考这个细节,我罗列一下我的一些想法吧,准备动手用 unity 试试:
首先做一个草的 diffuse 材质,要能接收阴影,不需要 alpha cut,因为荒野之息里面的单根草就是两个三角形的一个 quad,上下两个尖,中间一条线,然后要加上 instancing;
沿着地形生成一个多随机顶点的 mesh;
然后做一个 geometry shader,在需要产生草的顶点上生成单根的草;
哪里产生草,哪里不产生草,可以在 v2g 的参数上里传入,这个值可以在 vert 函数里采样一张 mask 图;
然后随风摇摆,可以通过 perlin noise 函数来移动地面以上的几个顶点;
关键的是人物和小怪踩倒的交互这里我没有想出什么好方法。目前的方法是把人物的世界坐标传入 geometry shader,然后根据草的顶点和人物坐标的距离来计算压倒的强度和方向,这样做的问题是,如果有很多小怪和宝箱,就要实时传入一个坐标数组,性能会比较差,另外也解决不了延迟抬起的问题;
还有一个思路是用正交相机,拍摄一个 render texture,可以在 compute shader 里做纹理淡出,类似雪地轨迹那种做法,这样可以支持多物体同时计算,延迟抬起,不过这个问题是这个正交相机怎么才能实现开放场景大地图的同步?还是把整个场景地面分块,用多个正交相机同时工作,因为远处可以不用工作,所以极限情况是地块的交界处,有四个正交相机在同时工作,当然也可以通过优化,不让这些交界处有连续的草地,可以节约很多 cpu 性能。
这个草地分块的思路来自于 flower 的技术分享,整个场景切分为 256 个地块,在 ps3 的 spu 上产生草和物理数据。
目前思考到的一些实现思路,目测 pc 能跑起来,但是性能不会特别好,求大师指点。

▎本文由 简悦 SimpRead 转码。