shader|Shader实现喷射蜘蛛网特效


本文由RoadLun原创,转载请声明
效果如下:

shader|Shader实现喷射蜘蛛网特效
文章图片
shader|Shader实现喷射蜘蛛网特效
文章图片



由于录屏软件的原因,gif看起来一卡一卡的,实际情况并没有卡顿,详情见篇末资源包 图片是由本人绘制,没有alpha通道,Shader没有用透明度混合,所以整个特效看起来有些low, 阅读本文需要一定shader基础,如果阅读困难,可以先阅读 浅墨大神的Shader教程。 蛛网效果主要由三个部分组成: 1.弧形效果2.剔除3.蛛网喷射(放大)4.蛛网抖动5.消失
1.先说第一个弧形效果,我刚开始的思路是用一个Plan,获取Plan的中心点,即UV为(0.5,0.5),然后使Plan的所有顶点沿法线方向外拓,外拓距离为当前顶点到中心点的距离,此距离当作一个二次函数的x值,y值即为外拓长度。 (x*a)2*b=y用a和b来控制曲面的弧度。

理论上,这是一种可行的方法,但是涉及到逐顶点计算并且涉及到较为复杂的数学运算,这对于GPU来说并不是一件好事,所以我用了一个偷懒的方法模拟弧度,用一个Sphere:

shader|Shader实现喷射蜘蛛网特效
文章图片



如图,但借用Sphere模拟弧度也不是最佳的方法,还是会有多余的网格,对于CPU来说是一种浪费,让美术同学制作一个弧面模型是最完美的解决方案。 2.好,言归正传,现在解决剔除问题,如果没有剔除,将会显示一个球体,而不是蜘蛛网。 shader|Shader实现喷射蜘蛛网特效
文章图片
通常用来剔除背景的方式是透明度混合,这种特效看起来更虚幻飘渺,本人电脑上并没有安装PS(ps破解三次都没成功,真是头疼),所以我用CDR来绘制贴图,并没有透明度通道,所以我用在片段着色函数里写discorve方法来剔除背景,设置一个剔除值,如果下当前像素的亮度低于剔除值,则剔除当前像素。 shader|Shader实现喷射蜘蛛网特效
文章图片
此处我的剔除值初始是0.7,所以刚开始贴图的黑色背景就会被剔除。

3. 蛛网喷射效果,此处我用顶点沿法线外拓的方法实现,外拓的值随时间增大而增大,但外拓后顶点的x值偏移量太大,所以对x进行修正。 shader|Shader实现喷射蜘蛛网特效
文章图片
4.蛛网的抖动,这里通过顶点进行有频率的抖动实现,同样是在顶点着色器里面, shader|Shader实现喷射蜘蛛网特效
文章图片


shader|Shader实现喷射蜘蛛网特效
文章图片

【shader|Shader实现喷射蜘蛛网特效】
5. 蛛网消失,操作方法在第二步,通过剔除来实现,使剔除值随时间增大而增大,当超过1时,蛛网被完全剔除掉。 shader|Shader实现喷射蜘蛛网特效
文章图片

ok,思路就是这样。源码附上:

Shader "Custom/1" { Properties { _Diffuse("漫反射",Color)=(1,1,1,1) _MainTex("基础贴图",2D)="white"{} //控制溶解的参数 _DissolveMap("噪波贴图",2D)="white"{} _DissolveThreshold("溶解阈值",Range(0,1.1))=0 _FlyThreshold("破灭程度",Range(0,1))=0.1 _FlyFactor("破灭延迟",Range(0,0.19))=0.1 //控制曲线的参数 _K1("K1",Float)=0.1 _K2("K2",Float)=0.1 _B1("B1",Float)=1 } CGINCLUDE #include "Lighting.cginc" uniform fixed4 _Diffuse; uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform sampler2D _DissolveMap; uniform float _DissolveThreshold; uniform float _FlyThreshold; uniform float _FlyFactor; uniform float _K1; uniform float _K2; uniform float _B1; struct v2f { float4 pos :SV_POSITION; // float3 worldNormal:TEXCOORD0; //贴图坐标 0 float2 uv:TEXCOORD1; //贴图坐标 1 }; v2f vert(appdata_base v) { //法线外拓 v2f o; _FlyFactor=_Time*2; v.vertex.xyz += v.normal * _FlyFactor*10; v.vertex.x-=v.normal*_FlyFactor*30; //顶点抖动 v.vertex.y+=1-sin(_Time.y* +v.vertex.x *_K1 * v.vertex.z+_B1)*_K2; o.pos=UnityObjectToClipPos(v.vertex); o.uv=TRANSFORM_TEX(v.texcoord,_MainTex); o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject); return o; } fixed4 frag(v2f i): SV_Target { //剔除 _DissolveThreshold=_Time+0.7; fixed4 dissolveVolue =tex2D(_DissolveMap,i.uv); if(dissolveVolue.r<_DissolveThreshold) { discard; } //Diffuse+Ambient 光照计算 fixed3 worldNormal = normalize(i.worldNormal); fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); fixed3 lambert = saturate(dot(worldNormal, worldLightDir)); fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 color = tex2D(_MainTex, i.uv); return fixed4(color,1); } ENDCG SubShader { Tags{"RenderType"="Opaque"} Pass { Cull off CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma Lambert ENDCG } } Fallback"Diffuse"}

资源包(百度网盘):https://pan.baidu.com/s/12Br6wh7ikBgI0H73qFhMMg

    推荐阅读