Pixel Bender で2値化 して lineTo で描いた線のアンチエイリアスを切る

Spark勉強会で gunyarapaint を発表していたグニャラくんが、lineToで描いた線のアンチエイリアスを切りたいと言ってたので諸々試してみたよ。


その1:PixelBender 使ってみる

速度を稼ぎたいので、試しにPixelBenderのフィルタを描いてみることにした。2値化すりゃいいんだから、グレースケールの値をroundしてやればええやんとか適当に考えてみたのだが…

…文法サッパリわかんねーーーナニコレ。

とりあえずグレーにするところは、Mike Chambers 殿のコレなどを参考に、こんなふうに書いてみた。丸めるには閾値を引数にして step っていうのを使うんやね。


<languageVersion : 1.0;>

kernel Digitize

{
    parameter float threshold<
        minValue:       float(0.0);
        maxValue:       float(1.0);
        defaultValue:   float(0.5);
        description:    "threshold";
    >;

    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        dst = sampleNearest(src,outCoord());
        float avg = step(0.2125 * dst.r + 0.7154 * dst.g + 0.0721 * dst.b, threshold);
        dst = float4(avg, avg, avg, dst.a);
    }
}

なんかそれっぽい絵ができた。

600fpsてナニソレ…爆速。ASじゃ絶対にそんな素振り見せないくせに。
 
 
その2:フィルタとして使ってみる

じゃこれをAS3で読み込んでフィルタとして使う。
Loader動かすのダルいので、直接埋めて使う事に。
出来上がったのがコレ
軽いやん。


package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.ShaderFilter;
	import flash.utils.ByteArray;

	public class PixelBenderSample extends Sprite
	{
		//PixelBenderフィルタを埋め込み
		[Embed("Digitize.pbj", mimeType="application/octet-stream")]
		private var DigitizeFilter:Class;	

		//焼き込み用のビットマップ
		private var _bg:Bitmap;

		//線を描画するキャンバス
		private var _lineCanvas:Sprite;
		private var _tempBitmap:BitmapData;

		public function PixelBenderSample()
		{
			this.addEventListener(Event.ADDED_TO_STAGE, _onAddedToStage);

			_tempBitmap = new BitmapData(500,500);
			_bg = new Bitmap(_tempBitmap);
			addChild(_bg);

			_lineCanvas = new Sprite();
			_lineCanvas.cacheAsBitmap = true;
			addChild(_lineCanvas);

			//Shaderを設定
			var shader:Shader = new Shader(new DigitizeFilter() as ByteArray);

			shader.data.threshold.value = [0.5];
			var filter:ShaderFilter = new ShaderFilter(shader);

			//フィルタをかける
			_bg.filters = [filter];

		}

		//マウスのイベント処理
		private function _onAddedToStage(e:Event):void{
			this.stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
			this.stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
		}

		private function _onMouseDown(e:MouseEvent):void{
			_lineCanvas.graphics.lineStyle(5, 0);
			_lineCanvas.graphics.moveTo(this.mouseX, this.mouseY);
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
		}

		private function _onMouseUp(e:MouseEvent):void{
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
			_tempBitmap.draw(_lineCanvas);
			_lineCanvas.graphics.clear();
		}

		private function _onMouseMove(e:MouseEvent):void{
			_lineCanvas.graphics.lineTo(this.mouseX, this.mouseY);
		}
	}
}

塗りを簡単にするために試したものの、ちゃんとPixelBender使ってやれば、そっちで塗りの処理ができるような…(笑
まあええか。

Leave a Reply