炎のゆらぎを表現する


んで、とりあえず今日は「ファイア・エフェクト」のプログラムを 組んでみました。
「ファイア・エフェクト」というのは、炎を コンピュータ上で表現するアルゴリズムのことです。
百聞は一見に如かず。早速画面を見てみましょう。

ちょっと小さくてわかり辛いかもしれませんが、炎がゴーゴーと勢いよく燃えています。
一見してみると、「なんだか難しそうなことやってるなぁ」と、お思いの方もいらっしゃるでしょうが、 これがところがスットコドッコイ、実は炎を揺らがせているアルゴリズムは至極単純なのです。

まず、パレットに、「赤-黄-黒」といった炎らしい色をセットして、その最も明るい色と暗めの色を 画面下の方に適当にバラ巻きます。これが「火種」となります。
画面の各ピクセルは、火種の影響を受けて「セルオートマトン」的なアルゴリズムで 自身の色を変えていきます。

「セルオートマトン」というのは、…うーん、どう説明したらいいんだろう。 とりあえず具体例を書きます。

ここに

000000000

0が9個並んでいるセルがあるとします。
このセルは「0か1の値を取り」
決まり事として、「隣が1ならば、自分も1になる」
「1になった次のターンには、0に戻る」
という性質を持っているとします。

000000000

とりあえず今の状態はすべてが0なので、いくら待っても変化はおきません。
ということで、前述した「火種」をセルの中央に置くことにします。

000010000

はい。「火種」セット完了です。
後は、連鎖反応的に、セルが互いに影響を及ぼし合います。
まずは「隣が1ならば、自分も1になる」の条件通り、
「火種」の両隣が1になります。
「火種」は0に戻ります。

000101000

さらに今度は、1に変わった両隣が3つが1になります。

001010100

というような連鎖反応が続いていきます。
これがファイア・エフェクト・アルゴリズムの根幹です。
要するに、このプログラムではこの考えを利用して、 各ピクセルを、その周囲のピクセルの色と照らし合わせることによって色をぼかしつつ、 ゆらぎを加えながら上に押し上げていくのです。 このことが理解できればすぐにでもプログラムを組むことができるでしょう。

汚いですが、ソース↓
    //---------------------------
    //   炎を描画する
    //---------------------------
    public void DrawFire(){

        int seed;   //火種の位置
        int color;  //色成分
        int color_R;
        int color_G;

        //画面下に火種をセットする
        for(int i=0;i<200;i++){
            pbuf[39600 + i] = 0xff000000;   //黒をセット
        }
        for(int k=0;k<fire_seed;k++){
            seed = (int)(Math.random()*199);
            pbuf[39600 + seed] = 0xffffffff;   //白をセット
        }
        for(int k=0;k<fire_seed;k++){
            seed = (int)(Math.random()*199);
            pbuf[39800 + seed] = 0xffffff00;   //黄色をセット
        }

        //ピクセルごとの色平均を取りながら、上に押し上げる
        for(int x=1;x<199;x++){

            for(int y=1;y<199;y++){

                //赤成分の平均
                color_R = (pbuf[200*y + x-1]&0x00ff0000)>>16;
                color_R += (pbuf[200*y + x+1]&0x00ff0000)>>16;
                color_R += (pbuf[200*(y+1) + x]&0x00ff0000)>>16;
                color_R += (pbuf[200*y + x]&0x00ff0000)>>16;
                color_R = color_R>>2;

                //緑成分の平均
                color_G = (pbuf[200*y + x-1]&0x0000ff00)>>8;
                color_G += (pbuf[200*y + x+1]&0x0000f900)>>8;
                color_G += (pbuf[200*(y+1) + x]&0x0000f200)>>8;
                color_G += (pbuf[200*y + x]&0x0000ff00)>>8;
                color_G = color_G>>2;

                color = 0xff000000 | (color_R<<16) | (color_G<<8);

                pbuf[200*(y-1) + x] = color; //上に

            }

        }
    }
参考ホームページ
http://www01.u-page.so-net.ne.jp/fa2/y_yutaka/

参考文献
InsideDelphiX 、 Cマガ
ダウンロードは自己の責任において行ってください。