Shader學習筆記 05 - 2d火焰

2D程序式火焰

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

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

截取方法能夠定值截取,也能夠插值截取
1. 定值

參考博客3d

使用step區份內外焰,效果上相似卡通火焰(toon fire)。
imagecode

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

參考博客htm

image效果其實差很少blog

2. 插值

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

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

image

Mask

使用Mask來約束火焰外形的時候,定值截取效果並很差。應該是須要特製下噪聲,讓火焰集中。get

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自帶的粒子系統吧。

相關文章
相關標籤/搜索