火焰通常包括焰心、內焰、外焰,至少要有內焰、外焰的區分,另外有煙,火花,熱扭曲之類的效果。html
基本原理很簡單,就是使用梯度值(通常是uv.y)截取不斷上移的噪聲值來造成火焰效果。動畫
參考博客3d
使用step區份內外焰,效果上相似卡通火焰(toon fire)。
code
另外使用偏導數也能夠實現相似效果,好處是能加一點抗鋸齒效果。orm
參考博客htm
效果其實差很少blog
噪聲值減去遞增梯度值便可,結果是顏色變化比較平滑。ci
float gradientValue = 1 - uv.y; float t = noiseValue + lerp(0, -2, gradientValue); float3 col = _FireColor.rgb*(1-t);
使用Mask來約束火焰外形的時候,定值截取效果並很差。應該是須要特製下噪聲,讓火焰集中。get
插值的火焰效果就好不少。博客
煙能夠單獨製做而後疊加上去,也能夠從火焰中截取一部分做爲煙霧。
與火焰原理相同,一個噪聲向上移動,而後須要另加一個噪聲與之相差讓結果有層次感。
相乘結果:
修改顏色,加上Mask。
最後將結果和合併到火焰上取便可。
既然前面能夠截取噪聲不一樣值區份內外焰,那麼天然能夠截取一部分做爲煙。
直接插值截取效果並很差,比較好的實現參考:
火花使用純粹的shader實現起來比較麻煩,目前沒有找到好的方法,仍是使用粒子效果或者動畫。
熱扭曲就是簡單的uv扭曲。
在一個貼圖上是能夠模擬出粒子效果。最簡單原理參考:
粒子模擬須要能獲取上一渲染結果,在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上有一些不錯的火焰模擬,基本上能夠經過這個方法移植過來,好比這個:
仍是直接使用Unity自帶的粒子系統吧。