十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
大数据中一种模型淡入淡出时透明面重叠问题的解决方案,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
成都创新互联是专业的围场网站建设公司,围场接单;提供成都网站建设、网站制作,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行围场网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
角色死亡时需要一个渐消效果,最普通的想法就是转成透明物体设置alpha淡化,然后就会出现这样的情况。
由于模型有分层,会露出衣服下面的部分,而那些部分往往是有缺失的,就算只显示1秒也非常出戏。而想解决这个问题也简单,在前面新增一个PASS仅绘制深度,就能过滤掉内部的模型了。这也是魔兽世界等游戏处理潜行和幽灵人物的方法。
Pass { Tags{ "RenderType"="Transparent" "Queue"="Transparent" } ColorMask 0 }
这个方案的是完美的吗?其实并不是。首先这样做会导致模型以透明方式绘制,无法遮挡地面导致overdraw,但这也算小事。问题在于,这种方法只能针对单Renderer物体,有多个Renderer的时候它还是会重叠绘制。如果你希望不重叠,可以将写深度的PASS的RenderQueue向前设置,但这样做的话,所有被这个物体遮挡的透明物体又都无法显示了(我的世界的玻璃就是这样一种状况),想要两全其美比较麻烦。合并模型是能解决问题,但是材质不同怎么合?分部位换装怎么可能只用一张贴图?
更何况,毕竟这是把不透明物体变成了透明物体,这两者在渲染处理上相差巨大,并不总能保证转换自然(透明度设置为1时应该保证和之前不透明时的显示一致)。而到了延迟渲染管线后,由于透明物体机理上难以接受光照,只能单独处理,或者代价巨大,就彻底无法使用了。
所以现世代游戏不少都是用的下面这种做法。
某一帧
实际上并没有任何透明像素,仅仅是通过clip让前方的像素和后方的像素交替显示,做出一种“看上去是半透”的效果。这样实质上还是不透明物体渲染,上面说的那些问题就都不存在了。
以下是Shader
Shader "Unlit/AlphaGrid" { Properties { _MainTex ("Texture", 2D) = "white" {} _Alpha ("Alpha", Range(0,1)) = 0.1 _AlphaGridTex ("Alpha Grid Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float4 screenUv : TEXCOORD1; UNITY_FOG_COORDS(1) }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _AlphaGridTex; //float4 _AlphaGridTex_ST; float _Alpha; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); float4 screenPos = ComputeScreenPos(o.vertex); screenPos.xy *= _ScreenParams.xy / 8;//此处不能先除w,会导致插值精度不够 o.screenUv = screenPos; o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); float gridAlpha = tex2Dproj(_AlphaGridTex, i.screenUv).a; // apply fog UNITY_APPLY_FOG(i.fogCoord, col); clip(_Alpha - gridAlpha); return col; } ENDCG } } }
注意_AlphaGridTex应该设成全局纹理,我这样写只是为了不写cs代码。
纹理本身是这样的一张8x8的alpha8图片,记录了每个8x8屏幕像素的过滤顺序。
放大:
本来想用算法生成,最后还是手绘方便……64个点而已。
当然,这样做虽然不用额外PASS,但是毕竟是AlphaTest的做法,比不透明物体渲染还是会慢的,顶点上也多了一些计算压力,但也就仅此而已了。
(目前手游上,非PowerPR芯片使用discard会导致Early-Z失效,AlphaTest的物体即使被其他物体遮挡也会照样绘制,导致浪费OverDraw,但那也是它被遮挡的时候才会发生的情况,这种情况恐怕并不常见,而且即使再差也还是比alphablend强。
而PowerPR芯片则是另外一种情况,虽然不会导致OverDraw浪费,但是绘制本身变慢了,假如人物frag阶段比地面复杂,半透程度也比较高的话,确实会有一定的性能问题。所以这并非优化,而是一种解决问题的办法,至于到底是变快还是变慢还要看具体的情况)
当然,这种方法并不能用来做常态的人物半透,久了是必然糊弄不了的,只能用来做渐入渐消。(虽然有游戏确实在这么搞,诸如FF14,他们也是没其他的选择吧)
效果确实也不能算好,只是特殊情况的特殊选择。
但多个选择总是好的。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注创新互联行业资讯频道,感谢您对创新互联的支持。