TA-Shader-文件 Unity技术分享 |《Trifox》中的遮挡处理和溶解着色器
发布于
2019-11-12
4507
3
TA资源类型
TA资源类型: 算法思路 效果图 
shader资源类型: shader代码 
适用引擎: unity 
资源介绍: -

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 幺九 于 2021-2-18 22:25 编辑

本文作者是来自Glowfish Interactive的开发者Brecht Lecluyse,目前正在开发一款独特而多彩的顶视角双摇杆动作冒险游戏《Trifox》,灵感源自经典的跳台游戏,玩家在《Trifox》中扮演一只技艺超群的狐狸去拯救被侵略的家园。今天将由Brecht Lecluyse为大家分享《Trifox》游戏项目中遇到的角色与障碍物间的遮挡处理,以及溶解着色器相关的问题。

角色应该如何显示

定义问题

在开发过程中,我们面临的首要挑战,就是在全3D的场景中让主角保持在头顶视角的相机之内。也就是说,如果有东西挡住了主角,是选择避免这些遮挡,还是把遮挡物隐藏掉?假使选择隐藏的话,如何采用一个视觉上令人可以愉快接受的方式,来让隐藏的过程符合游戏风格?如何保持不会妨碍游戏体验的空间感?

对于那些镜头设置类似于《Trifox》的游戏而言,这是一个非常常见的问题。所以在开始实现自己的方案之前,我们先参考了一些已有的方案。

鸟瞰视角

第一个方案是禁止关卡中出现任何横亘玩家与摄像机之间的巨大障碍物。这意味着大部分区域必须非常广阔,而墙壁和障碍物需要尽可能保持低矮,或干脆完全避免使用它们,并且摄像机与玩家角色要有一个特定的距离,尽可能垂直向下看。这种形式非常适合于“街机”类游戏,或场景中所有物体都面向同一个方向的传统顶视角RPG。然而在我们的案例中,视角与角色的距离拉远会导致玩家与主角产生疏远感。同时,也会使场景显得更加不自然,从而使玩家难以感知我们的游戏性、沉浸感以及视觉风格。
f5d57409-e15d-4c8e-8139-f4b455b0b606_1.jpg

鸟瞰视角例子:Arrow Head的《Helldivers》


切割及掀盖

下一个方案是对环境进行切割。您可以把场景想象为一个多层蛋糕,基于当前镜头关注的区域,玩家只能看到某一层的内容。

当主角站在建筑外部时,可以看到建筑的屋顶;而当他进入建筑内部时,整个屋顶以及高楼层就被全部隐藏,只显示当前楼层的墙壁和地板。大多数情况下不显示屋顶,这样能避免额外的设置工作。这种方法能够给玩家自然进出建筑物的感觉,让游戏能有更复杂的关卡设计和更强的空间感。虽然我们依旧需要将镜头定位在一个合适的距离并向下看,但由于障碍物可以被隐藏或显示,构造环境的方法可以更加自由。

为了进一步优化这个方法,我们隐藏墙壁和其他各种物体,决定它们是否遮挡我们的视野,是否允许更低的镜头角度及玩家角色视野更近。
5924d22a-bea0-4938-9af8-9cb71d833245_2.jpg

掀盖式相机示例:Firaxis Games的《XCom:Enemy Unknown》


这种方法唯一的缺点是会让人感觉不太自然。虽然可以通过淡出和使用透明材质来减轻这种感觉,但总体来说,我们希望尽可能远离这些东西,以避免重绘性能问题和全屏透明覆盖。这种方法确实更加符合需求,但对于我们的游戏而言仍然不是非常理想。

自然演化

在考察了常规的解决方案后,我们仍旧感觉有些问题。这些方法在大多数游戏中都工作得很好,但在这个项目上,我们总感到似乎缺了点什么。

我们具体想要达成以下目标:

  • 障碍物应当能在平滑而自然的过渡之后被隐藏。
  • 关卡设计师应当能控制哪些东西能够被隐藏,于是我们就可以保留一部分依然能够遮挡视野的物体,在环境中增加纵深感。
  • 镜头和角色之间的距离发生变化时,系统应当运作如常。
  • 遮挡处理应当在任何角度下都能工作。
  • 障碍物被隐藏后,玩家需要依然能够感受到它的存在。
  • 设置工作需要尽可能简化。



我们最终得出的方案整合了之前所有的方法,并增加了额外的障碍物隐藏风格。



当玩家向遮盖物移动的时候,遮盖物会逐渐变透明,确保视野不被遮挡,同时清楚地表现出此处确实有物体存在。这样,封闭空间场景依然可以保持封闭的感觉,并且墙面逐渐淡出不至于太显眼。这同时意味着我们可以让多个相交的大小形状不同的对象在一个统一的方式下消失,而不需要额外的设置。

那么我们如何达成这个目标?解决这个问题需要考虑如何来轻松地创建一个很棒的隐藏效果,可应用于各种游戏中的各种物体上。本文将阐述实现最终方案的过程,从深入研究一些常用的溶解着色器技术开始。

基础的溶解着色器与世界空间UV

基于噪音纹理的裁切

最简单的溶解效果可以使用2D噪音纹理和裁剪的着色器技术来实现。这个裁剪函数会将所有大于等于0的值绘制到屏幕上,让所有小于0的值不可见,可以作为材质的开关。

上述的噪音纹理应用到Unity默认的立方体的示例如下。




下一步是通过基于噪音纹理处理让这个立方体逐渐消失。回过头去看看clip着色器函数的工作原理和渐变纹理,这就很容易实现了。只需取出纹理中的灰度值,并减去一个0到1之间的值,这个值可以作为透明度百分比。



您可能注意到上图的对象会在大概75%的透明度下完全消失,而不是100%。这并不完全是我们期待的结果。纹理像素的值完全处于0和1之间,为什么会这样呢?

这是因为纹理导入引擎时,会进行一次伽马校正。这种情况下,我们需要将纹理当作线性数据纹理使用,也就是说我们需要将rgba的值当作数据而非颜色来使用。所以需要确保信息不被导入过程所改变。这可以通过调整纹理的导入设置来实现。

在“导入设置”窗口中,将纹理类型设为“Advanced”并启用“Bypass sRGB Sampling”标志。下面的动画展示了启用该设置前后的区别。在处理一些用到了纹理数据的更加复杂的着色器效果时,这个设置尤其重要。





这种方式对于一些可展开的网格非常适用,但如果是其它网格呢?如果有一些互相交叉的对象,能否创建一个效果,让它们表现得像是一个整体?



除非特地在溶解纹理上展开了每一个对象,否则相邻的对象在溶解时会出现很大的差异。而对于缩放过的对象,将需要针对每一个缩放级别各自应用一个材质来保持噪音细节平滑。很明显,这会导致巨量的设置工作,不符合需求。下一步:用程序化世界空间展开来替代手动展开。

世界空间UV

通常,纹理是依据网格在创建时定义的UV坐标映射到网格表面的。现在我们想要替换这些UV坐标,转而使用一个基于表面在场景中位置的坐标系。通过添加Unity内置的着色器输入参数“worldPos”,我们就可以在着色器中访问到这个信息。

这是一个常见的着色器技术,可以用于各种有趣的程序纹理贴图技术。例如,可以用它自动在表面低于某个特定高度的地方创建水浸效果。



再次把调整过后的着色器应用于立方体,这里需要一些额外步骤才能使世界空间纹理技术能够正常用于淡出效果。目前这个展开程序仅支持3D平面,这里的示例是XY平面,因为用到了x和y坐标来代替UV坐标。



可以通过一些向量运算计算出能够作用于所有表面的UV集,无论这些表面在空间中的位置和方向如何。最终实现一个纹理应用于网格后,它能在不同的方向、缩放以及位置下保持连贯。



最终应用于游戏资源的效果如下:



这足以应付大多数情况,但我们并未止步于此。从上图可以看出,使用这种噪音可能会产生令人不适的边缘溶解效果。此外,由于使用了纹理,在接近对象的时候会观察到明显的像素变化。我们同样也无法保证噪音纹理能够在很大的表面角度差和互相交错的物体之间都保持很好的连续性。



如何在游戏过程中处理遮挡住镜头视野的物体?我们提出了适用于该游戏的解决方案,考察了一些常用的着色器技术,比如:世界空间贴图和基于纹理的溶解着色器。效果如下:

我们发现了一些基于纹理的着色器技术的瑕疵:

  • 溶解效果在过渡边缘会显得很混乱。
  • 在近距离观察物体的时候会看到很大的像素块。
  • 无法让噪音纹理在很大的表面角度差和交错的物体之间保持很好的连贯性。

本篇内容

由于基于纹理的溶解着色器存在一些瑕疵,让我们不得不考虑完全摈弃纹理,而程序3D噪声方法会是一个比较好的选择。换句话说,我们可以使用数学过程由程序来生成3D噪音,以世界空间坐标为主要的输入参数,使用一个由包含0到1之间变化值的渐变体组成的3D纹理。

上图的溶解百分比设为50%左右,以便更好的展示3D噪音体


下面一起来看看使用纹理和使用程序生成3D噪声这两种方案的对比。

基于纹理的溶解着色器的效果



基于程序3D噪声的溶解着色器效果


很神奇吧,全程序化技术与纹理技术相比的平滑度差别有多么大,再加上一个自发光边缘,就会看到有趣的魔幻破碎效果。

这是因为使用程序生成的3D噪音可以任意缩放而不损失质量。并且由于不需要UV坐标,无论物体之间方向如何,溶解过程同样也会无缝衔接。不过,这个问题解决之后,还需要思考一下:如何使用这个技术动态地处理镜头遮挡问题?

引入屏幕空间坐标系 - 动态处理镜头遮挡问题

上篇文章在谈到如何处理遮挡问题时,我们提到过玩家应当能够感受到被隐藏的障碍物的存在。如果可能的话,在不影响视野的前提下,我们仍然希望能够看见隐藏物体的一部分。为了实现这一点,我们在着色器中引入了屏幕空间坐标系。用这种方法,可以在屏幕空间中根据将要渲染的表面离屏幕中心的距离来决定是否移除它。

通常屏幕空间坐标系是用来做后期特效的,但在这里用于影响物体的基本着色。添加下面的着色器输入结构体来访问屏幕空间位置:float4 screenPos;这样就能够像访问世界坐标一样,访问屏幕坐标。

用这样的方法,我们计算出一个简单的屏幕空间辐射渐变,并应用到场景中的物体上。值得注意的一点是,这并不是覆盖效果,而是屏幕坐标直接影响了渲染的几何体的色彩值。如下图,最终画面结果感觉就像用一个聚光灯照射在屏幕中心一样。

一个完全未改变的辐射渐变


经过了压缩调整的辐射渐变


经过压缩调整的辐射渐变可以符合屏幕的形状,并给出最终需要的遮罩。这个生成的遮罩能够帮我们判断出哪些部分需要溶解。但仍有一个重要的问题需要解决:如果就这样使用该遮罩,可能会为整个场景从相机位置开始打一个无限远的洞,如果玩家站在了一个可被溶解的遮挡物前,会怎样呢?我们希望确保那些物体保持完全可见,或至少把溶解效果控制在最小范围。

这个问题可以通过将玩家和相机的距离纳入计算,并分析渲染物体的深度值,被很好地解决掉。加入噪音遮罩后,最终得到如下结果:

这里玩家距离被设为固定的20米,以便展示效果更好


最终用于《Trifox》的效果添加了额外的步骤以获取更多的处理选项,比如通过顶点绘制来降低溶解密度,屏幕空间下降的控制,以及各种噪音微调选项。下图展示了完整的遮挡处理系统的效果:

可以在拱门的下半部分看到基于深度的噪音衰减效果和顶点绘制控制。

在Unity 5.6 Beta版中,Vulkan使图形显示性能更上一层楼,在最终发布的正式版中,Vulkan将支持Android,Windows,Linux,以及Tizen平台。

最后一步 - 功能检查与验证

在宣布遮挡处理系统完工前,让我们一起回顾最初的需求,并探讨这个方案是否符合。

  • 障碍物:应当以一个平滑而自然的方式移出视野,在任意角度都有效,即使已经被隐藏,玩家应当依然能够感觉到它的存在。
  • 关卡设计师:需要能够控制哪些东西可以被隐藏,以此加强环境的深度感。
  • 系统:无论角色和镜头之间的距离如何变化都能工作。
  • 设置工作:尽可能简化。

恭喜,任务完成!现在拥有了一个能够正常运转的系统,能够实现我们想要的效果,并且风格与游戏相匹配。  

总结

回顾整篇文章,以上是攻克《Trifox》中的障碍物处理问题的过程。从定义问题开始,我们考察了可能的解决方案,然后一步一步实现了最终游戏里的效果。

我们最终使用的是一个可以实现很多视觉效果的技术,《Trifox》中的大量游戏细节都使用该技术,包括让被打败的敌人和被破坏的物体消失,以及改变环境的外观或让整个世界淡入或淡出等等。下面提供了两个原型示例,展示这个技术的不同应用:


比利时工作室Exiin也在游戏《Ary And The Secret Of Seasons》中运用了同样的技术,如下图所见,用来将季节球淡出。

希望您喜欢这篇关于《Trifox》中的障碍物处理和溶解着色器技术的文章。

参与人数 2 元素币 +31 活跃度 +1

使用道具 举报 登录

回复 <
图南·光  发表于 2020-9-10 17:50:38  
2#
效果看起来很棒
回复 收起回复
使用道具
zhuxisky  发表于 2020-12-21 19:56:43  
3#
这样你就以为我就会了吗,天真
回复 收起回复
使用道具
狂奔de蜗牛  发表于 2023-8-9 11:41:38  
4#
回复 收起回复
使用道具

快来发表你宝贵的意见吧!

kanisen 实名

通过了实名认证的内容创造者

【尊贵的网吧二楼会员】

主题
205
精华
20
超神
0
扩散
0
微金
3003
智慧
240
余额
0
在线时间
6756 小时

钢剑 翡翠剑 魔影剑 光之杖 【绝】珍珠戒指 【绝】黄金项链 【绝】红龙战甲 魔神战甲 元素之铠 英雄盾 钢盾 裁决 彗星钛晶矿 守望者【EX】 希望人没事 元素之盾 小苹果 神速靴 巨浪 双杀 振金项链 六维几何 火元素 学徒法袍 元素铜币 元素银币 元素金币 长剑 长枪

快速回复 返回顶部 返回列表