效果一覽

基本原理

利用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
}
}
}

參數一覽

其中消融點坐標為場景中火把火焰的世界坐標

推薦閱讀:

相关文章