Shader學習筆記 05 - 2d火焰


2D程序式火焰

火焰一般包括焰心、內焰、外焰,至少要有內焰、外焰的區分,另外有煙,火花,熱扭曲之類的效果。

基本原理很簡單,就是使用梯度值(一般是uv.y)截取不斷上移的噪聲值來形成火焰效果。

截取方法可以定值截取,也可以插值截取
1. 定值

參考博客

使用step區分內外焰,效果上類似卡通火焰(toon fire)。
image

另外使用偏導數也可以實現類似效果,好處是能加一點抗鋸齒效果。

參考博客

image效果其實差不多

2. 插值

噪聲值減去遞增梯度值即可,結果是顏色變化比較平滑。

float gradientValue = 1 - uv.y;
float t = noiseValue + lerp(0, -2, gradientValue);
float3 col = _FireColor.rgb*(1-t);

image

Mask

使用Mask來約束火焰外形的時候,定值截取效果並不好。應該是需要特制下噪聲,讓火焰集中。

image

插值的火焰效果就好很多。

image

Smoke

煙可以單獨制作然后疊加上去,也可以從火焰中截取一部分作為煙霧。

1. 單獨制作

與火焰原理相同,一個噪聲向上移動,然后需要另加一個噪聲與之相差讓結果有層次感。

image

相乘結果:

image

修改顏色,加上Mask。

image

最后將結果和合並到火焰上取即可。

2. 截取

既然前面可以截取噪聲不同值區分內外焰,那么自然可以截取一部分作為煙。

直接插值截取效果並不好,比較好的實現參考:

shadertoy

火花、熱扭曲

火花使用純粹的shader實現起來比較麻煩,目前沒有找到好的方法,還是使用粒子效果或者動畫。

熱扭曲就是簡單的uv扭曲。

其他

在一個貼圖上是可以模擬出粒子效果。最簡單原理參考:

How to Write a Smoke Shader

粒子模擬需要能獲取上一渲染結果,在unity中需要創建2個RenderTexture。

private RenderTexture SimTexture;
private RenderTexture buffer;
private Material ParticleSimulationMat;
public Shader ParticleSimulationShader; // 粒子模擬Shader
public Material ObjMat;  // 目標Sprite的Material
Start {
    ParticleSimulationMat = new Material(ParticleSimulationShader)
    SimTexture = new RenderTexture(512, 512, 0, RenderTextureFormat.ARGBFloat);
    buffer = new RenderTexture(512, 512, 0, RenderTextureFormat.ARGBFloat);
}
Update {
    // Graphics.Blit(SimTexture, SimTexture, ParticleSimulationMat) 無效,2019.4 版本
    // 保存渲染結果,ParticleSimulationMat中_MainTex便是上一渲染結果
    Graphics.Blit(SimTexture, buffer, ParticleSimulationMat);
    Graphics.Blit(buffer, SimTexture);
    ObjMat.SetTexture("_SimTexture", SimTexture);
}

shadertoy上有一些不錯的火焰模擬,基本上可以通過這個方法移植過來,比如這個:

Smoke and fire

結論

還是直接使用Unity自帶的粒子系統吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM