火焰通常包括焰心、内焰、外焰,至少要有内焰、外焰的区分,另外有烟,火花,热扭曲之类的效果。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自带的粒子系统吧。