| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> Unity的ScrollRect如何裁切粒子特效,以及如何使粒子特效显示在UI上 -> 正文阅读 |
|
[游戏开发]Unity的ScrollRect如何裁切粒子特效,以及如何使粒子特效显示在UI上 |
在功能开发中,有时候为了更好的效果会在UI上添加一些特效,比如在头像框上增加一个圆环的粒子特效,但由于粒子和UI的渲染方式有些不同,导致会出现UI和特效之间穿插,显示上不理想。并且如果在ScrollRect下显示人物列表,滑动滚动条时还无法对粒子特效进行遮罩处理。这里集中解决这两个问题: 首先解决如何使粒子特效显示在UI上:1.设定Canvas渲染模式:当添加一个UI对象时,如果Hierarchy下没有Canvas,则UGUI系统会自动添加该对象,并且Canvas的渲染模式默认为Screen Space - Overlay。Canvas有三种渲染模式: Screen Space - Overlay:无论其他任何3D物体,UI始终显示在屏幕最前方 Screen Space - Camera:此时Camera与Canvas有一定的距离,可以在这段距离内添加一些3D物体,如粒子特效等,通过调节粒子物体的Z坐标即可在UI上显示出来。当然为了实现这个效果也有别的方式,后面会介绍 World Space:这种模式下,UI就和普通的3D空间物体,比如引擎自带的Sphere、Box等一样。 由于粒子特效属于3D物体,为了使得粒子特效能够显示在UI上,这里需要改变Canvas的渲染模式为“Screen Space - Camera”: 这种模式下需要为Canvas指定渲染相机,同时设置本Canvas的Layer,以及order in layer。设置完成后,本Canvas下的所有UI都属于同一层,并且Order in layer保持一致,渲染时根据从上到下的顺序决定UI之间的遮挡关系 2.设置UI和粒子特效之间的Order in Layer:首先具体解释下UI之间的渲染关系: 各个UI根据自身设定的Layer分隔,在同一layer根据Order in layer进行排序,数值越大越显示在上面。在同一order in layer的UI则按照Hirearchy中从上到下的顺序依次渲染。后面的会遮挡之前渲染的UI。 如下图Hierarchy中UI设置以及显示效果如下: ? ?? ? ?? 在同一canvas下,按照从上到下的渲染顺序,Red一定会遮挡住Blue的画面。那么如何能够做到即使Blue在Red之前渲染,也依然能可以显示在Red上面呢?这种情况就需要改变UI的layer或者Order in layer —— 一般情况下改变Order in layer就可以达到效果,所以也用不着改变layer层了 为了实现效果有两种方式: 一、因为同一canvas下Red必定会挡住Blue,因此这里把Red从Blue下提取出来,这里为了演示的需要,仍然将Red放在Blue之下。然后给Blue添加Canvas用于改变Blue的Order in layer ? ?? Red在默认的Canvas下渲染,因此其layer - default, Order in layer - 0。当给Blue添加Canvas并开启Override sorting,设置Order in layer 为0后,会将该Order in layer已渲染完成的UI进行重置,默认显示重置之后的UI —— 但仅针对同一屏幕坐标有多个UI重叠的区域进行重置,在没有重叠的区域,则依然显示之前的UI: 上述情况Blue - size: 200 x 200, Red - size: 100 x 100,当重置Blue的canvas后,Blue会将同一Order in layer重置,因此会完全挡住Red。但如果改变Blue - size:50 x 50,则会显示: 由上可知,所谓的重置也仅仅只是针对同一区域有多个UI显示的情况,区域外的则不会受到影响 二、第二种方式和第一种的原理类似,但不用改变Blue 和 Red之间的父子关系,直接改变Red的Order in layer。在默认情况下,Blue 和 Red都在 Layer - default, Order in layer - 0,然后按照从上到下的顺序渲染,要使得Blue显示在Red上面,则需要重置Red。 ?? 虽然为Red添加了Canvas来重置Order in layer,但由于Blue 和 Red渲染layer、order设置相同,且Red - size较小,即使重置也只会影响很小的区域。所以就必须改变Red的Order,使得Red在Blue之后渲染,这样就可以实现Blue显示在Red上面了。由于Blue默认order in layer为0,因此这里设置Red的order in layer为“ -1”即可。 ? ?? 注意:UGUI在进行Drawcall合并时是按照Canvas来进行的,不同的Canvas即使layer,order in layer相同,也无法合并Drawcall。因此对于项目整体UI布局需要事先设计好,为了不影响后期优化,尽量不要随意添加Canvas来改变UI渲染关系 根据以上的解释,要使得粒子特效显示在UI上则只需要改变粒子特效的“Sorting layer” 和 “Order in layer”,通常情况下改变“Order in layer”即可达到效果。UI默认的“Order in layer”为“0”,因此只要设置粒子特效的“Order in layer”大于0即可。 运行效果如下: 如此粒子特效就显示在UI上了,通过设置粒子和UI之间的order in layer即可解决相关的UI穿插问题 2.如何解决ScrollRect滑动时粒子特效无法被遮罩处理的问题?首先我们需要知道遮罩Mask是如何起作用的? 这里需要引入一个“模板缓存 - Stencil Buffer”的Shader功能,当材质所使用的Shader支持Stencil Buffer时,则可以通过调节参数来自定义UI之间的遮挡剔除关系。 1.参数解析:Shader中的Stencil Buffer的关键参数:
通常自定义效果时改变的参数为:Ref [_Stencil],?Comp [_StencilComp],?Pass [_StencilOp] Ref:该UI所使用的referenceValue,在计算颜色时会把该数值与Stencil Buffer中存储的数值进行比较。对于使用具有模板缓存功能的shader,会把该UI的各个像素点使用referenceValue进行标记并将该referenceValue存入模板缓存即stencilBufferValue = referenceValue,用于后续与其他referenceValue的比较。取值范围是 0 - 255 的整数 Stencil Buffer在初始状态下referenceValue数值默认为0 Comp:将Ref数值与Stencil Buffer中存储的数值进行比较的操作,如大于、等于、小于等。 各种操作的情况如下:代表各个操作的数值从0 - 8 依次递增 ?Pass:代表通过上述的referenceValue比较后对该像素执行的操作,代表各个操作的数值从0 - 8 依次递增 ?PS: 一般情况下并不会对ReadMask、WriteMask进行修改,保持默认值即可。
各个参数详解:UnityShader实例09:Stencil Buffer&Stencil Test_lupeng的博客-CSDN博客_shader stencil 注意:当“_StencilComp”通过测试时,该像素点即会被绘制显示出来,但“_StencilOp”指的是通过模板或深度测试后,对“Stencil Buffer”中该像素点对应的标记值进行处理,这个与本像素点是否会显示出来是无关的,仅仅只是针对模板缓存中存储的数值进行操作,默认是keep,即本UI所使用的referenceValue并不会被写入模板缓存中,Stencil Buffer依然保留之前的数值——该数值会继续用于下次的“stencilComp”比较 2.Stencil Buffer实例操作:当新建某个UI image时,可以看到该image默认使用的shader为“UI/Default”,其已经支持了Stencil Buffer的功能: 但由于其使用的是UGUI中默认的材质“Default UI Material”,因此无法自定义其中的参数。 为了实现自定义遮挡的效果,可以新建一个materialA,并设置其shader为“UI/Default”即可: 如此即可以自由设定参数实现想要的效果 如上参数所示,默认情况下referenceValue = 0, Comp = Always, Op = Keep ?如下所示,创建两个image,都使用默认的材质: 由于参数保持默认,因此先绘制Blue时,始终通过stencil test,Blue整个被绘制出来;然后绘制Red,在两张image的重叠处,Red通过stencil test被绘制出来,所以Red会将Blue进行部分遮挡,此时stencil buffer中存储的数据由于stencilOp = keep,因此仍然保持为0 根据以上情况,如何在按照从上到下依次绘制Blue、Red的情况下,在重叠处依然显示Blue呢? 此时可以直接调节参数,只需要将Red设置为不通过stencil test即可: 解析:因为要实现在Blue与Red重叠处,对于Red不能通过stencil test,但是非重叠处则可以通过stencil test,因此这就必然要求在绘制Red之前就已经使得Blue显示区域和非显示区域的stencil buffer中存储的数值不同。默认情况下,stencil buffer中 stencilBufferValue = 0,因此需要改变Blue的referenceValue = 1,stencilOp = 2(Replace),stencilComp = 8(Always)。在通过stencil test后,根据stencilOp将referenceValue写入stencilBufferValue中。 ?? 此时Blue绘制区域的stencilBufferValue = 1,非绘制区域stencilBufferValue保持为默认的0。即满足了要求。 对于Red来讲,重叠处无法通过stencil test,而重叠处的stencilBufferValue = 1。因此设置Red的referenceValue = 0, stencilComp = Equal(3),stencilOp = 0。由于重叠处使用Equal比较,因此对于Red必然无法通过stencil test,不会被绘制,而非重叠处referenceValue = stencilBufferValue,所以通过stencil test,Red可以被绘制。针对于stencilOp参数,一般情况不需要改变,这里依然保持默认值Keep。效果如下: PS: 参数“Use Alpha Clip” 和 “Color Mask” 的作用:1.参数“Use Alpha Clip”: 如上图所示,虽然可以实现效果,但左下角依然有部分像素遮挡: 这是由于在将导入的Texture设置为“Sprite”格式时,Unity会自动裁切掉该texture多余的像素,但有些边角依然会有少许残留。当勾选“Use Alpha Clip”后: 该参数勾选后,会自动将image中alpha小于0.001的像素舍弃掉。如此在绘制UI时则相当于此处完全没有像素,也就不会对UI之间的遮挡有影响。 注意:如果美术人员的某张texture部分区域alpha很低,但由于此处依然有像素,因此还是会挡住其他的UI,并且如果stencilOp为replace,则此alpha很低的区域依然会写入stencilBufferValue中。为了解决这个问题,“Use Alpha Clip”会将image中alpha很低的像素舍弃掉 ? 如上图标记位置,虽然alpha很小,但依然会遮挡后面的图片。当舍弃该区域的像素时, ? ?如此则能得到更好的显示效果。 2.参数“Color Mask”:对本UI中通过stencil test的像素做屏蔽处理,注意这里的屏蔽仅仅只是针对自身而言。比如该区域之前已经有像素被绘制,本UI又没有通过stencil test,此时即使设置“Color Mask = 0”也不会对该区域之前的像素有影响 像素是否会显示出来取决于该像素是否通过stencil test,和 color mask设置的数值。默认情况下,“color mask = 15”,因此只要该像素通过stencil test即会在显示出来。 例如当设置BlueMat的“color mask = 0”时—— 可以使用这种方式达到一些镂空挖洞的效果 ? ? ?虽然Blue已经通过了stencil test,但由于color mask的作用,其并不会显示出来。并且通过调节“Color Mask”的数值可以得到不同的显示效果: Color Mask = 5:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Color Mask = 10:? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? 3.在粒子shader中加入stencil buffer功能:如下所示,在Blue下添加粒子效果,可以明显的看到粒子超出了image的边界——这里使用的shader是"Legacy Shaders/Particles/Additive"。出现这样的原因在于粒子shader并没有Stencil Buffer功能 ? ?为了实现遮罩效果,需要在粒子的shader中加入Stencil Buffer。新建Shader脚本,将该粒子所使用的shader源码拷贝到新建的shader脚本中,并在其中添加上述的Stencil Buffer关键参数Property 和 Stencil,并新建material使用该shader,这样就可以自由调节参数达到效果了。 例如:这里使用Unity内置的Shader:“Particle Add.shader” 新建Shader ——?CustomParticleShader.shader,拷贝“Particle Add.shader”的源码,并添加StencilBuffer关键参数到CustomParticleShader.shader脚本文件中:
此时将使用CustomParticleShader.shader的新材质ParticleMat赋值给粒子特效: ? 要实现的效果是粒子超出Blue边界时会自动被裁切掉,不会显示出来,所以需要调节ParticleMat的参数。由于Blue区域的stencilBufferValue = 1,区域外的stencilBufferValue = 0,因此可以设置ParticleMat中“referenceValue = 1,stencilComp = Equal(3),stencilOp = Keep(0)”,效果如下: 如此粒子特效的遮罩效果也实现了。 项目源码地址:Unity中UI和粒子特效之间的遮挡以及遮罩功能-Unity3D文档类资源-CSDN下载 ? PS: Unity的内置Shader源码:一是在官网下载:https://unity3d.com/get-unity/download/archive 选择对应的平台和版本后,点击“Built in shaders”即可 二是在Github上下载,有个开源项目地址:https://github.com/TwoTailsGames/Unity-Built-in-Shaders 这里附上下载好的Unity2018.4.1f1的内置Shaders源码文件:Unity2018.4.1f1内置Shaders的源码文件-Unity3D文档类资源-CSDN下载 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 16:30:10- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |