屈折の続き


ソレはソレとして,id:keim_at_Si:20070930の続き.


2DメタボールのConvolutionFilterは,基本的に電界マップの微分値を取るために使ってるんだけど,
そもそも,電界マップはグレースケール画像なので,RGBに全く同じ値が入っていて,
これにConvolutionFilterをかけるのは,3倍冗長な処理を行ってる事になる.
ので,電界マップの上中下段を3分割して,それぞれをRGBにコピーした
1/3の大きさの画像に対して,ConvolutionFilterをかければ良い.これで1.6倍速位.


最適化ってほどではないけど,3倍のConvolutionFilterってのは,
あまりにも冗長だし,明らかなボトルネックなので修正.


以下追加ソース.
ライセンスはPublic Domainです

public class main_ref_fast extends Sprite
{
    ...追加
    static private var base3:BitmapData;                // 1/3 base image
    static private var rc:Rectangle = new Rectangle();  // multipurpose
    static private var pt:Point = new Point();          // multipurpose
    static private var tmp3x:BitmapData;                // multipurpose 1/3 bitmap
    static private var tmp3y:BitmapData;                // multipurpose 1/3 bitmap
    ...
    
    public function main_ref_fast()
    {
        ... 追加
        base3  = new BitmapData(240, 82, false);
        tmp3x  = new BitmapData(240, 82, false);
        tmp3y  = new BitmapData(240, 82, false);
        ... 
    }

    
    private function _onEnterFrame(event:Event) : void
    {
        var i:int, j:int;
        
        // measure start
        //var start:int = getTimer(); for (var l:int=0; l<100; l++) {

        // execute
        ball.mouseX = mouseX;
        ball.mouseY = mouseY;
        for (i=0; i<balls.length; i++) { ball(balls[i]).gravity(); }
        for (i=0; i<balls.length-1; i++) for (j=i+1; j<balls.length; j++) { ball(balls[i]).interact(ball(balls[j])); }
        for (i=0; i<balls.length; i++) { ball(balls[i]).run(); }
        calcBallCenter();
        
        // draw balls
        base.fillRect(pixels.rect,0x000000);
        for (i=0; i<balls.length; i++) { ball(balls[i]).draw(base); }
        
        // divide by 3
        rc.width = 240;
        rc.height = 82;
        rc.x = 0;
        rc.y = -1;  base3.copyChannel(base, rc, base3.rect.topLeft, BitmapDataChannel.RED, BitmapDataChannel.RED);
        rc.y = 79;  base3.copyChannel(base, rc, base3.rect.topLeft, BitmapDataChannel.RED, BitmapDataChannel.GREEN);
        rc.y = 159; base3.copyChannel(base, rc, base3.rect.topLeft, BitmapDataChannel.RED, BitmapDataChannel.BLUE);

        // refraction
/*
        // original
        temp.applyFilter(base, base.rect, base.rect.topLeft, convx);
        bump.applyFilter(base, base.rect, base.rect.topLeft, convy);
        bump.copyChannel(temp, temp.rect, temp.rect.topLeft, BitmapDataChannel.RED, BitmapDataChannel.RED);
        temp.applyFilter(floor, floor.rect, floor.rect.topLeft, disp);
        alph.copyPixels(temp, temp.rect, temp.rect.topLeft);
*/
        tmp3x.applyFilter(base3, base3.rect, base3.rect.topLeft, convx);
        tmp3y.applyFilter(base3, base3.rect, base3.rect.topLeft, convy);
        rc.width = 240;
        rc.height = 80;
        rc.x = 0;
        rc.y = 1;
        pt.x = 0;
        pt.y = 0;   bump.copyChannel(tmp3x, rc, pt, BitmapDataChannel.RED,   BitmapDataChannel.RED);
        pt.y = 80;  bump.copyChannel(tmp3x, rc, pt, BitmapDataChannel.GREEN, BitmapDataChannel.RED);
        pt.y = 160; bump.copyChannel(tmp3x, rc, pt, BitmapDataChannel.BLUE,  BitmapDataChannel.RED);
        pt.y = 0;   bump.copyChannel(tmp3y, rc, pt, BitmapDataChannel.RED,   BitmapDataChannel.GREEN);
        pt.y = 80;  bump.copyChannel(tmp3y, rc, pt, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);
        pt.y = 160; bump.copyChannel(tmp3y, rc, pt, BitmapDataChannel.BLUE,  BitmapDataChannel.GREEN);
        temp.applyFilter(floor, floor.rect, floor.rect.topLeft, disp);
        alph.copyPixels(temp, temp.rect, temp.rect.topLeft);
        
        // lighting
/*
        // original
        temp.applyFilter(base, base.rect, base.rect.topLeft, conv);
        alph.draw(temp,null,null,BlendMode.HARDLIGHT);
*/
        tmp3x.applyFilter(base3, base3.rect, base3.rect.topLeft, conv);
        pt.y=0;   temp.copyChannel(tmp3x, rc, pt, BitmapDataChannel.RED,   BitmapDataChannel.RED);
        pt.y=80;  temp.copyChannel(tmp3x, rc, pt, BitmapDataChannel.GREEN, BitmapDataChannel.RED);
        pt.y=160; temp.copyChannel(tmp3x, rc, pt, BitmapDataChannel.BLUE,  BitmapDataChannel.RED);
        temp.copyChannel(temp, temp.rect, temp.rect.topLeft, BitmapDataChannel.RED, BitmapDataChannel.GREEN);
        temp.copyChannel(temp, temp.rect, temp.rect.topLeft, BitmapDataChannel.RED, BitmapDataChannel.BLUE);
        alph.draw(temp,null,null,BlendMode.HARDLIGHT);
        
        // cutout
/*
        // original
        temp.copyPixels(base, base.rect, base.rect.topLeft);
        temp.colorTransform(temp.rect, colt);
        alph.copyChannel(temp, temp.rect, temp.rect.topLeft, BitmapDataChannel.RED, BitmapDataChannel.ALPHA);
*/
        base3.colorTransform(base3.rect, colt);
        pt.y=0;   alph.copyChannel(base3, rc, pt, BitmapDataChannel.RED,   BitmapDataChannel.ALPHA);
        pt.y=80;  alph.copyChannel(base3, rc, pt, BitmapDataChannel.GREEN, BitmapDataChannel.ALPHA);
        pt.y=160; alph.copyChannel(base3, rc, pt, BitmapDataChannel.BLUE,  BitmapDataChannel.ALPHA);
        
        // draw
        pixels.copyPixels(floor, floor.rect, floor.rect.topLeft);
        pixels.copyPixels(alph, alph.rect, alph.rect.topLeft);
        drawFace();
            
        // measure end
        //} trace(getTimer() - start);
    }
    
    ... 後は一緒
}