日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

火焰效果材质实现_利用噪音图制作一个纸张燃烧的效果

發布時間:2024/9/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 火焰效果材质实现_利用噪音图制作一个纸张燃烧的效果 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫在前面

前幾天有人在群里問怎么制作一個紙張被火燒掉的效果,剛好那天沒那么忙,就嘗試實現了一個,效果如下:

這個shader并不復雜,主要是對噪音圖的使用,趁這次機會和大家分享一下

基礎材質

紙張本身不是這次效果的重點,所以簡單的采樣一張貼圖即可,下面是隨便找了張圖貼上去

fixed4 col = tex2D(_MainTex, i.uv.xy);

我們還需要一張燃燒過后的圖,把上面那張圖扔PS里去個色,然后加點污漬:

fixed4 colAsh = tex2D(_AshTex, i.uv.xy);

余燼效果

燃燒過會還會留下一下余燼,我們可以利用噪音圖來實現,通過采樣兩次噪音圖進行疊加來讓噪音更隨機一些,讓其中一次稍微放大一些防止完全重疊的情況。

這里用到一張網上隨便找的噪音圖(注意商用的話可能會有侵權風險)

vertex:

o.uv2 = TRANSFORM_TEX(v.uv, _NoiseMap).xyxy * half4(1,1,1.3,1.3) + _FlowVector * _Time.x;

fragment:

fixed noise =(tex2D(_NoiseMap2 , i.uv2.xy) + tex2D(_NoiseMap2, i.uv2.zw)) * 0.5;


效果如下

當然你也可以試試別的疊加算法,比如這樣:

fixed noise =abs( (tex2D(_NoiseMap2 , i.uv2.xy) + tex2D(_NoiseMap2, i.uv2.zw)) - 1);

我們會得到一個這樣的效果

提取其中一部分區域作為遮罩,疊加上火焰的顏色:

fixed3 spark =(smoothstep(0.8,1, noise)) * _SparkColor;

就能得到這樣的效果了。

材質混合

這里圖省事我們就直接使用uv的x方向來進行混合,因為這里的過渡范圍限定為0到1,所以需要把混合因子映射到-1到2才能保證完全覆蓋,效果如下:

_Blend = _Blend * 3 - 1; half blendValue = smoothstep(_Blend-_Range, _Blend+_Range, i.uv.x) ; col.rgb = lerp(colAsh + spark, col , blendValue) + burnRange;

現在的混合邊緣太生硬,使用上面的噪音圖對混合的邊緣進行擾動,稍微調整下代碼:

half blendValue = smoothstep(_Blend-_Range, _Blend+_Range, i.uv.x + noise * _Range) ;

火焰

從上面的的混合權重里把邊緣提取出來,因為噪音的影響,我們就可以得到一個近似火焰的遮罩區域:

float3 burnRange = blendValue * (1-blendValue) * _RangeColor; col.rgb = lerp(colAsh + spark, col , blendValue) + burnRange;

現在火焰占滿了整個過渡區域,我覺得有點太過了,所以調整了下,把火焰限定在更小的范圍,并且加入了偏移值和火焰寬度值進行微調:

float3 burnRange = max(0 , 1 - abs(blendValue - (_FireOffset *(1-_FireRange*2)+ _FireRange)) /_FireRange) * _RangeColor;

寫這類效果的時候我一般喜歡畫圖來輔助計算,比較推薦一個網站:

Graphing Calculator - GeoGebra?www.geogebra.org

上面的那個算法圖像是這樣子的:

https://www.zhihu.com/video/1225579900545224704

消散效果

消散效果應該很多人都寫過,一個簡單的clip即可,因為我們需要按照燃燒>灰燼>消散這個過程漸變,所以消散效果要在前面的混合權重基礎上加一點偏移:

clip(col.a * (i.uv.x+ noise * _Range) - (_Blend - _Range -_EmberRange)) ;

頂點擾動

紙張燃燒時候還會因為熱量產生一點輕微的變形,我們利用頂點動畫來模擬這個效果,注意如果要做頂點動畫的話,頂點數量不能太少,這里的模型使用的是一個30*30的網格

float4 noiseuv = float4(v.uv * _NoiseMap2_ST.xy + _NoiseMap2_ST.zw * _Time.x, 0,0) ; fixed noise = tex2Dlod(_NoiseMap2 , noiseuv) ; _Blend = _Blend * 4 - 1; half vertOffset = noise * _VertOffset * saturate (1 - (o.uv.x*4 -_Blend));o.vertex = UnityObjectToClipPos(v.vertex + half4(0,0,vertOffset ,0));

這樣我們的效果就全部完成了,看上去還不錯, 再加一點粒子應該會很不錯。

完整代碼

/******************************************************* * 2020-03-18 16:38:42 * @Mya * 模擬紙張燃燒的shader ********************************************************/ Shader "Mya/Effect/BurningPaper" {Properties{_MainTex ("Texture", 2D) = "white" {}_AshTex ("Ash Texture", 2D) = "white" {}_NoiseMap("Noise" , 2D) = "black"{}_Blend("Blend" , Range(0,1)) = 0[hdr]_RangeColor("Range Color" , Color) = (1,0,0,1)_Range("Range" , Range(0.01,0.5)) = 0.1_FireRange("Fire Range" , Range(0,0.5)) = 0.2_FireOffset("Fire Offset" , Range(0,1)) = 0[hdr]_SparkColor("spark Color" , Color) = (1,0,0,1)_AshRange("EmberRange" , Range(0,1)) = 0.1_FlowVector("Flow Vector" , vector) = (0,0,0,0)_NoiseMap2("Noise2" , 2D) = "black"{}_VertOffset("Vert Offset" , Range(0,1)) = 0.1}SubShader{Tags { "RenderType"="Opaque" }LOD 100Blend SrcAlpha OneMinusSrcAlphaCull OffPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 uv2 : TEXCOORD1;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;sampler2D _AshTex;sampler2D _NoiseMap; float4 _NoiseMap_ST ;sampler2D _NoiseMap2;float4 _NoiseMap2_ST ;half _Blend;half _Range;fixed4 _RangeColor;fixed4 _SparkColor;half _AshRange;half _FireRange;half _FireOffset;half4 _FlowVector;half _VertOffset;v2f vert (appdata v){v2f o;o.uv = TRANSFORM_TEX(v.uv, _MainTex);//通過采樣兩次噪音圖進行疊加來讓噪音更隨機一些,讓其中一次稍微放大一些防止完全重疊的情況o.uv2 = TRANSFORM_TEX(v.uv, _NoiseMap).xyxy * half4(1,1,1.3,1.3) + _FlowVector * _Time.x;//頂點里采樣貼圖需要使用tex2Dlodfloat4 noiseuv = float4(v.uv * _NoiseMap2_ST.xy + _NoiseMap2_ST.zw * _Time.x, 0,0) ;fixed noise = tex2Dlod(_NoiseMap2 , noiseuv) ;_Blend = _Blend * 4 - 1;//對燃燒區域的頂點做一點偏移,模擬飄動的效果half vertOffset = noise * _VertOffset * saturate (1 - (o.uv.x*4 -_Blend));o.vertex = UnityObjectToClipPos(v.vertex + half4(0,0,vertOffset ,0));return o;}fixed4 frag (v2f i) : SV_Target{fixed noise = (tex2D(_NoiseMap , i.uv2.xy) + tex2D(_NoiseMap2, i.uv2.zw))*0.5;//基于uv的x方向計算混合的權重,邊緣使用噪音進行擾動//要保證四個狀態(原始,燃燒,灰燼,消散)都能完整顯示,需要把混合因子映射到-1~3_Blend = _Blend * 4 - 1;half blendValue = smoothstep(_Blend-_Range, _Blend+_Range, i.uv.x + noise * _Range) ;//原始的顏色fixed4 col = tex2D(_MainTex, i.uv.xy);//燃燒后的顏色fixed4 colAsh = tex2D(_AshTex, i.uv.xy);//余燼fixed3 spark =(smoothstep(0.8,1, noise)) * _SparkColor;//火焰float3 burnRange = max(0 , 1 - abs(blendValue - (_FireOffset *(1-_FireRange*2)+ _FireRange)) /_FireRange) * _RangeColor;//消散clip(col.a * (i.uv.x+ noise * _Range) - (_Blend - _Range -_AshRange)) ;//混合col.rgb = lerp(colAsh + spark, col , blendValue) + burnRange;return col;}ENDCG}} }

GitHub:

https://github.com/myacat/PaperBurn?github.com

寫在最后

簡單修改下還可以做出類似這樣的效果,有興趣的小伙伴可以自己嘗試繼續優化下:

=====4.18更新====================

今天稍微調整了一下這個曲線的算法,讓曲線更平滑一些

https://www.zhihu.com/video/1234725242905935872

左邊是新的算法

拆成了獨立的函數

half Pow2(half x){return x*x;}half ReMap(half range, half offset , half val){#if SMOOTHRANGE//Range(10-0)range = 10*(1 -range);return Pow2(max(0, 1 - Pow2(range*val + 2*val - range*offset - 1)));#else//Range(0.5-0.1)range = 0.1 + range * 0.4;return max(0 , 1 - abs(val - (offset *(1-range*2)+ range)) /range) ;#endif}

因為兩個算法range參數的值域是不一樣的,所以重映射了一次。

左邊是新的算法

然而改完后發現效果也并沒有變好多少.....emmm算是提供另一個思路吧...

總結

以上是生活随笔為你收集整理的火焰效果材质实现_利用噪音图制作一个纸张燃烧的效果的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。