效果一覽
基本原理
利用clip()函數將距離目標點一定距離內的像素進行剔除,通過採樣雜訊貼圖對該距離進行擾動,以便形成較為無序自然的燃燒邊緣,同時燃燒邊緣一定距離內對燃燒顏色貼圖採樣來形成燃燒邊緣顏色
具體實現
在Unity中完成該效果,講解見注釋,場景搭建參考我專欄的另一篇文章unity熱擾動
新建box,添加如下shader
DistanceMelt.shader
Shader "Custom/DistanceMelt" { Properties { [NoScaleOffset]_MainTex("主貼圖", 2D) = "white" {} _MaxDistance("影響半徑",float) = 0.5 _NoiseTex("雜訊貼圖",2D) = "black"{} _XDensity("雜訊密度(水平)", float) = 1 _YDensity("雜訊密度(豎直)", float) = 1 _MeltPoint("消融點坐標",Vector)=(0,0,0,1) _NoiseEffect("雜訊影響佔比",Range(0,1))=0.5 [NoScaleOffset]_EdgeColor("消融邊緣貼圖",2D) = "black"{} _ColScale("顏色比例",float) = 1 _EdgeWidth("消融邊緣寬度",Range(0,1)) = 0 } SubShader { Tags { "RenderType" = "Opaque" } LOD 100
Pass { Cull Off
CGPROGRAM #pragma vertex vert #pragma fragment frag
#include "UnityCG.cginc"
struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; };
struct v2f { float4 pos : SV_POSITION; float2 uvMain : TEXCOORD0; float2 uvNoise : TEXCOORD1; float4 objPos : TEXCOORD2; };
sampler2D _MainTex; sampler2D _NoiseTex; sampler2D _EdgeColor; float4 _NoiseTex_ST; float4 _MeltPoint; float _Threshold; float _XDensity; float _YDensity; float _EdgeWidth; float _MaxDistance; fixed _NoiseEffect; float _ColScale; float _DelayTime;
v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uvMain = v.uv; _NoiseTex_ST.xy *= float2(_XDensity, _YDensity);//改變雜訊貼圖縮放來控制雜訊密度 o.uvNoise = TRANSFORM_TEX(v.uv, _NoiseTex); o.objPos = v.vertex;//保留物體的物體空間坐標,為後續計算距離準備 return o; }
fixed4 frag(v2f i) : SV_Target { float4 PointPos = mul(unity_WorldToObject , _MeltPoint);//將世界坐標的目標點轉到物體空間坐標 float Distance = length(i.objPos - PointPos);//計算他們在物體空間坐標的距離 fixed noise = tex2D(_NoiseTex, i.uvNoise).r;//採樣雜訊,後續將對消融距離進行擾動 //noise*_NoiseEffect表示雜訊擾動的影響程度 //Distance減去noise*_NoiseEffect完成對距離的擾動影響 //最後減去_MaxDistance判斷影響後的距離是否大於最大距離,小於就剔除,大於就保留像素 fixed cutout = Distance - noise * _NoiseEffect - _MaxDistance; clip(cutout);//cutout小於0剔除像素,反之保留像素 fixed4 col = tex2D(_MainTex, i.uvMain); //cutout若大於0即可表示成與_MaxDistance的距離,除於_EdgeWidth並約束到0~1轉化1成uv即可完成根據與_MaxDistance的距離查找uvEdgeCol對應的顏色 //_ColScale對uv.x進行縮放,完成水平方向對EdgeCol自定義分配,數值越大,採樣約接近EdgeCol的深黑色部分 //EdgeCol帖圖的導入設置中wrap mode要設為clamp fixed2 uvEdgeCol = fixed2(_ColScale*smoothstep(0, 1, cutout / _EdgeWidth), smoothstep(0, 1, cutout / _EdgeWidth)); fixed4 edgeCol = tex2D(_EdgeColor, uvEdgeCol); //根據與_MaxDistance的距離與_EdgeWidth的佔比來過渡MainTex顏色與邊緣顏色edgeCol fixed f= smoothstep(0, 1, cutout / _EdgeWidth); col = lerp(edgeCol, col, f); return col; } ENDCG } } }
參數一覽
其中消融點坐標為場景中火把火焰的世界坐標
推薦閱讀: