【Aegisub】火焰模擬、火焰仿真效果

????????前面介紹了融球效果,提到了利用液滴也可以做出火焰效果:

? ? ? ? 當(dāng)然也說了,利用噪聲同樣可以做火焰仿真效果:


? ? ? ? 當(dāng)然之前也反復(fù)說過,這些效果都不是用一堆像素做的,而是直接生成一塊塊大的繪圖來做的。
????????那么現(xiàn)在,就來講講這兩種火焰是怎么做的。首先講第二種是怎么做的。
? ? ? ? 之前講了分形噪聲能做下圖的效果

但問題是一整張噪聲圖,怎么變成類似三角形的樣子。那就要用到紋理映射(或者說紋理貼圖),現(xiàn)在只需要簡單地用到其中的思維即可?,F(xiàn)在假設(shè)噪聲圖是這樣的

假設(shè)黑色是0、白色是1、灰色當(dāng)然是0到1之前,每一個點都對應(yīng)一個噪聲值?,F(xiàn)在要得到火焰說明要過濾掉一些部分,所以可以做標(biāo)記(即mask),使每一個點對應(yīng)的值發(fā)生改變,最后只留下數(shù)值在規(guī)定范圍的點即可。比如可以讓下面三角形部分的點對應(yīng)的數(shù)值更大、其它部分的點對應(yīng)的數(shù)值更小,這樣就可以過濾不需要的部分了。
????????舉例子比如,現(xiàn)在準(zhǔn)備這樣一張圖:

黑色到白色就是0到1、圖中每個點對應(yīng)一個0到1的數(shù)值,那每個點的數(shù)怎么算呢,顯然越接近底部數(shù)字越大,所以用縱坐標(biāo)的差距即可。假設(shè)頂部y是0、底部y是h,那么任意一點到底部的距離是math.abs(h-y),將其變到0到1之間是math.abs(h-y)/h,而math.abs(h-y)/h當(dāng)然是越接近底部的點數(shù)值越小、在底部的點數(shù)值就是math.abs(h-h)/h=0,但是現(xiàn)在想要從頂部到底部的點對應(yīng)的數(shù)值是從0到1、而不是從1到0,所以反過來就行了,這很簡單,用"1-"即可。也就是1-math.abs(h-y)/h不就行了嗎,1-math.abs(h-y)/h就是從0到1了。那么不就可以利用這張圖來標(biāo)記噪聲圖的點嗎、將這張圖作為mask。將兩張圖相加就有

兩張圖的數(shù)的范圍反正可以隨便設(shè)定嘛,既然現(xiàn)在兩張圖各點的數(shù)值都是0到1,那加起來就變成了0到2,可以除以2嘛。

可以看到,原本的噪聲圖(左)加了mask標(biāo)記以后就得到了右圖了。這樣每個點對應(yīng)的數(shù)值就變了嘛,然后你就可以保留數(shù)比較大的點了,比如如果某點對應(yīng)的數(shù)值大于0.61,那么就保留這一點,于是就有

當(dāng)然全部畫為白色就有

再比如,現(xiàn)在保留所有數(shù)值大于0.27的點,那么就有

那么現(xiàn)在已經(jīng)有了火焰的形狀了,然后你就可以讓它動起來的不是嗎?只需要平移噪聲圖即可,之前其實已經(jīng)講過的嘛。要讓火焰往上飄,只需要讓噪聲圖往下移動即可,也就是增加y,隨著時間的增加,噪聲圖里每個點的y坐標(biāo)在原本的基礎(chǔ)上一點點增大,然后每一幀得到的圖連起來即可。這樣不就可以做出這樣的效果了嗎:

所以現(xiàn)在只需要mask是三角形的即可。這也很簡單,只需要兩張圖就能得到想要的mask

剛剛已經(jīng)講了、用了右邊的紋理圖,現(xiàn)在只需多計算一張新的圖、即左邊的圖,將左右兩個圖加起來(或者相乘也行)不就可以得到三角形的mask了嗎:

當(dāng)然相乘也可以得到三角形的mask,還是一樣的道理

然后剛剛已經(jīng)講了下圖的右邊的圖是怎么做的,然后現(xiàn)在還需要得到左邊的圖

左邊的圖很容易得到,橫向看每個點代表的數(shù)值是從0到1再到0的,什么意思,也就是說,點離中間越近則該點對應(yīng)的數(shù)字越接近1。假設(shè)橫坐標(biāo)從0開始到w結(jié)束,則中間的x是w/2,所以任意一點到中間線的距離是math.abs(w/2-x),然后產(chǎn)生1到0的過渡即math.abs(w/2-x)/(w/2),由于需要的是0到1到0而不是1到0到1,所以同樣的,反過來,用上"一減"、即"1-",就有1-math.abs(w/2-x)/(w/2)了,這樣不就有了從0到1到0的變化了嗎,也就是

這樣兩個圖相加,就有了三角形mask了

這樣就又可以對噪聲圖作標(biāo)記了:

顯然,作標(biāo)記以后、有了可愛的mask以后,每個點代表的數(shù)值就又變化了,這樣又可以過濾掉一部分?jǐn)?shù)值的點,比如現(xiàn)在只保留大于0.53的點,那么就有

這不就出來了嗎?其它細(xì)節(jié)你可以自己調(diào)嘛?,F(xiàn)在比如你又設(shè)定只保留大于0.7的點,那么范圍當(dāng)然就更小了:

這樣通過范圍的設(shè)定,就能畫出不同的等值線、做出內(nèi)焰和外焰的效果了:

顯然,做火焰效果是不需要用一堆像素做的,因為早就講過了,如何繪制等值線,所以只需要繪制出一整塊的、大的繪圖即可。當(dāng)然繪制的網(wǎng)格和生成噪聲圖的網(wǎng)格不是一回事、沒理由把它們搞混。那么這樣第二種火焰效果的原理和實現(xiàn)就介紹清楚了。所以當(dāng)然你可以有各種各樣的mask來做各種各樣的效果,可謂千變?nèi)f化。
????????再反復(fù)講一下,剛剛的漸變圖,每一個點都對應(yīng)一個0到1的數(shù)字,而為了將其可視化,就配上了顏色、黑色是0白色是1,這樣就有"漸變圖"了。然后兩張圖相加就是字面意思的相加,每個點對應(yīng)的數(shù)字相加即可得到新的數(shù)字、然后你可以將這個數(shù)字的范圍重新控制在0到1之間。同樣,兩個圖相乘也是一樣的,每個點對應(yīng)的數(shù)字相乘即可,當(dāng)然0到1的數(shù)字乘以0到1的數(shù)字得到的數(shù)字結(jié)果還在0到1這個范圍內(nèi),很方便。實際上,圖和圖加減乘除都不奇怪,而且根據(jù)需要,有時也會把一個圖平方,比如下圖原本是這樣的:

平方以后就變成了

顯然對于一個0到1的數(shù),平方以后數(shù)字就會比原本的更小,所以現(xiàn)在的圖接近白色的部分就更少了。
? ? ? ? 然后關(guān)于mask,一般是翻譯成遮罩,但顯然mask和clip并不是一回事,雖然clip也可翻譯成遮罩,不過,clip翻譯成裁剪會更加"精準(zhǔn)"一些。其實在圖形布爾運算里,clip就是翻譯成裁剪的。所以如果以后我提到mask遮罩時,一定不要理解成clip了。
????????然后就是介紹第一種火焰效果怎么做。當(dāng)然是用融球做的,也非常的簡單。只需要不停地向上發(fā)射小球、然后對這些小球做融合效果即可。

很簡單,先設(shè)置一個大的球,然后每一幀發(fā)射一些小球(比如每幀發(fā)射兩個新的小球),小球的半徑當(dāng)然需要比大球小很多很多了。小球可以從大球中心的位置開始發(fā)射出來,也可以在其它位置開始發(fā)射,比如離大球頂部近一些的位置。然后你還可以每一幀讓已經(jīng)發(fā)射出的小球慢慢變小,如果小球半徑小到一定程度或者小球已經(jīng)移動到繪制畫布外,就可以將物體表里的該小球刪除。這樣,對每一幀的這些物體(球)做融合效果即可。非常簡單就有了融球火焰效果了。