关于原神沙漠痕迹效果的踩坑记录

本文详细记录了实现原神沙漠中角色行走留下的轨迹效果的技术过程,包括轨迹体积的置换贴图和曲面细分实现,以及轨迹动态绘制的Graphics.Blit方法和与地形的联动。在曲面细分部分,介绍了顶点阶段数据接收、细分规则配置、插值权重计算和细分后的顶点属性计算等关键步骤。此外,还探讨了动态绘制、时间淡化、细节优化和性能优化策略,如位移离散化、边缘遮罩和ARGB64颜色格式。提供了完整的Unity工程链接供读者参考和学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

——因为个人之前活动的平台缺乏有营养的可以促进双方思考与进步的评论(毕竟平台的主打内容和用户群体不同),所以思考(与自己的懒惰做斗争)过后,技术相关的文章以后还是来知乎或CSDN之类专业性比较强的平台发吧- -

——之前个人主要在B站和半次元活动,名字统一【伊底_1D】,如果对我的黑历史感兴趣的可以移步(虽然也没多长的历史),而这边之后视情况可能也会把已有的一些技术方面的文慢慢搬过来。

——下面的正文其实是之前在B站写好的一版直接粘过来后微调的,有些排版或者个人的习惯措辞可能会有些诡异- -大可不必在意。

目录

前言

一、流程分析

1.1、轨迹体积的分析

1.2、轨迹的动态绘制分析

二、轨迹体积的实现

2.1、置换贴图

2.2、曲面细分

2.2.1、顶点阶段数据接收

2.2.2、细分规则配置

2.2.3、计算插值权重

2.2.4、细分后的顶点属性计算

2.2.5、一点补充

2.3、置换贴图+曲面细分

三、轨迹的动态绘制

3.1、Graphics.Blit

3.2、笔刷绘制shader

3.3、与地形的联动

3.3.1、局部绘制轨迹

3.3.2、绘制区域动态跟随

3.3.3、混乱的开端

四、混乱的平息

4.1、位移离散化

4.2、边缘遮罩

​4.3、小误差截断

五、时间淡化

5.1、全局匀速衰减

5.2、ARGB64

六、细节优化

6.1、基于距离的局部曲面细分

6.2、基于视差算法的轨迹实现

​七、项目工程链接


前言

——这次应该是开备忘录系列以来综合性最强的一次效果开发了- -因为是“踩坑记录”,所以在专业人士来看废话可能会比较多?然后因为代码量较大,且涉及多个shader和C#脚本联动的情况,所以在结尾就不贴完整代码了,而是会提供完整的U3D工程链接。

——当时须弥版本刚开就看到一些肝帝已经跑到了沙漠(而自己连化城郭都还没出去···),然后就发现,欸,这个轨迹的效果有点意思,之前也在怪猎冰原里见过相似的效果。再加上如今的自己大致能想到实现方法,于是就做了做试试。经过小半个月的各种踩坑后可谓收获颇丰,并有了现在这篇文章。(下面是提瓦特车神早柚的表演时间)

​——然后,下面是本文实现的效果。沙漠材质是用的这个

——稍微换波贴图调调参就是原神6.0至冬预定(乐)

​——可以看出,在一些像是轨迹的形状以及淡化消失的方式上还是和原神中的效果存在差别的,这是高度混合的算法不同导致的(后面会讲)。至于原神中的高度混合算法,以后有机会再单独开一篇文来分析。

——因为用到了诸如细分曲面shader,Graphics.Blit等个人虽知道但一直没有机会实际使用的功能模块或API,自己也是磕磕绊绊边查资料边做的效果,所以难免会有些理解不到位甚至错误的地方。也因此,这次除了记录知识点外,格外欢(期)迎(待)专业人士进行讨论或指正(如果有专业人士会看的话- -···虽然我好像每次都会说类似的话)。当然,单纯只是感兴趣的圈外人士也欢迎提问- -哪怕不是和本文的内容直接相关。

——我的一贯态度就是,比起流量和点赞、浮于表面的夸奖之类,含有分析的建设性批评、表扬或知识分享,对我而言更令人愉悦(虽说流量可能也有增加获得这些的数学期望的作用就是了┑( ̄Д  ̄)┍)。

——自我抒情到此为止_(:з)∠)_那么下面正式开始。

一、流程分析

——事先说明,本文的效果只在PC端才有,在移动端(非云原神)则是只有脚印而没有拖拽的轨迹,并且脚印也没有体积(个人猜测,移动端可能的实现方案有动态创建销毁透贴片,基于Graphic.Blit的绘制等。相对来说前者的性能更优且效果更加可控,所以可能性更大些。但这些不是本文的重点,不过多讨论)。

——先直接说结论。这个效果的实现可以分成两个大步骤:轨迹体积的实现,以及轨迹的动态绘制。

1.1、轨迹体积的分析

 ——从上图中角色的脚被挡住,地面与岩石等其他场景模型的交界线形状发生变化等现象可以证明,PC端的效果并不是法线或视差贴图等障眼法(关于法线与视差是什么,不了解的可以点这里这里),而是真的去做了体积。

——个人在当时看到游戏中的效果时,脑子里主要浮现出了两个方案:

——1、模仿U3D的拖尾渲染器,写一个根据物体的运动动态生成横截面是U型的条状网格的脚本,同时想办法让轨迹模型外轮廓的顶点贴在地上(下面是U3D自带的拖尾渲染器的效果)。

 ——但简单想想,用这个方法的话,处理轨迹模型和地面的接缝以及轨迹自身的交叉过渡可能会比较麻烦。并且中间凹陷的地方可能是在地面以下的,这还会有一个渲染顺序的问题,可能需要用模板测试等方法做个剔除。总之,感觉前途多舛,不太行,pass。

—— 2、利用置换贴图+曲面细分的方式直接在地形上动手脚,分别都是什么意思会在下面细说。建模的盆友可能知道,其实就类似于zbrush里的细分级别,而这个效果本身总体来说也就是个低配版的zbrush。

——需要说明的是,曲面细分shader除了相对较大的性能开销外还存在兼容性问题。据我所知,尤其对于移动端显卡来说,较老的型号好像并不支持这个运算模块,个人认为这也是mhy没在移动端做这个效果的主要原因。

1.2、轨迹的动态绘制分析

——“动态变化可交互”才是这个效果的灵魂所在。如果只是个静态的效果,直接在模型上把轨迹做出来再上个法线不比上面那些省事又效果好?

——基于上面体积实现的思路,我们动态绘制的轨迹图至少得是一张类似于下面这样的灰度图。

——其中越黑的地方代表高度越低。而上面这张图,实际上是用PS画出来的。用过PS的盆友可能知道,PS的笔刷有个“绘制间距”的参数。这个参数d的含义就是,你画出来的那些看似连贯的线或色块,实际上是很多个中心间距为d的圆点(或者其他笔刷)叠在一起形成的。

—— 本人在较早的时候做过一个水波涟漪交互的效果。当时虽然想到了这层原理,但奈何知识有限,那时采用的方法十分简单粗暴,就是用一个1000长度的数组去记录每个“圆点”的相关参数(位置,大小,频率,衰减之类的),然后传到shader里做循环。每个像素1000次循环,再加上之前脚本的计算也是实时的,所以性能消耗可想而知。

——虽然这种方法对每个点都有着很强的可控性,但单就这个效果来说没必要,而且当绘制次数达到几万甚至几十万时,总不能还用数组去解决。考虑到一个点在画完后就不会再有什么变化,即便有,它的变化也与其他的点相同,而这种“大量单元相互独立且处理相同”就意味着该效果存在利用GPU的并行性解决的潜力。

——对于绘制,我们可以模仿PS的绘制过程来解决这个问题。

——这个绘制(添加新的“圆点”)的过程可以描述为一个迭代、或者说递归的过程,即用原图经过“加点”方法f(x)处理输出新图,而新图作为下次“加点”处理的原图输入,并重复这个过程。

Texture_{n+1}=f(Texture_{n})

——如此一来,在shader中只需计算和新加的那一个“圆点”相关的数据即可,而之前的结果都保存在了一张图像中。这个过程的实现方法也不唯一,可能用另一个我没怎么用过的叫ComputeShader的东西处理要更NB一些。但ComputeShader在兼容性上好像还不如曲面细分shader,总之这次姑且用U3D的内置函数——Graphics.Blit来解决。

二、轨迹体积的实现

2.1、置换贴图

——所谓置换贴图(或者叫位移贴图、高度贴图、凹凸贴图等。可能陈述有误,但不重要- -),一般是一张记录了表面凹凸程度(高度)的灰度图(比如1.2里的那张五角星),可以用它在顶点shader中改变模型的顶点位置(实际上模型本身没变,只是最终看上去的效果变了。最常见的套路就是下面这样沿法线方向膨胀)。

​——但像上面这样的做法存在两个问题:

——1、轨迹的形状可能存在外围比地表高,内部比地表低的情况,即大概下面这样的形状。

——但示例的高度挤出只是单向的。

——2、仔细观察示例可以发现,形状虽然变了,但是光影分布是错误的。

——对于问题1,可以仿照法线贴图的编码方式对置换贴图的灰度做一个[-1,1]->[0,1]的重映射,即实际的高度变化=2*灰度-1。(也就是说,原本的【灰度0对应高度0】变成了【灰度0.5对应高度0】,这使得图像中间接存储了负值信息。更进一步,如果有需要还可以自定义高度0对应的灰度,甚至非线性映射)确定编码规则后在shader中按对应规则解码即可。

——对于问题2,可以在置换贴图的基础上使用对应的法线贴图来矫正光影。虽然法线可以基于高度图在shader中实时计算,但考虑到性能开销与效果,这里还是用现成的法线贴图来做。这里可以做一个小优化,充分利用颜色通道,将法线信息存到图像的RGB通道,高度存到A通道中。

——综合以上两点可以得到类似于下面的笔刷贴图。

——需要注意的是,因为这里的法线是我们自定义的编码方式,所以U3D的图像导入设置中不能选NormalMap,shader中也不能用UnpackNormal解码。并且因为存储的是数据不是颜色,所以不能勾选sRGB。(原因可以参考我的这篇文章中末尾关于线性和Gamma空间的陈述)

——但实际上,仅仅是做了上面这些,效果也远远达不到预期。

​——原因便是模型本身的精度太低,与图像精度之间差距太大,这反而加剧了违和感。这就需要接下来的曲面细分来解决。

2.2、曲面细分

——为了节省性能及资源量,游戏中的模型,尤其是地形模型往往精度不高(顶点密度小)。但像是本文的这种效果,一条轨迹的宽度可能还没有地形中的一个三角面大,所以还需要在有轨迹的地方动态添加一定数量的顶点。这件事可以通过shader中的“细分曲面阶段”或“几何阶段”来实现。本文则是采用自动化程度较高的细分曲面shader来实现。

——曲面细分和几何shader是渲染管线中的两个可选阶段。一般我们写的shader,尤其是移动端shader只会用到顶点和片段shader,而完整的流程则是顶点->曲面细分->几何->片段。

——按个人的理解和概括(只是个人为了方便使用做的总结- -看完了能用来做东西,但理论层面上不一定对)&#x

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值