Pixel Bender をちょっとやってみた。
メモ的です。
#ああ、まだ全然分かんないから丸のみにしないで。
そろそろFlash10も出そうなのでちょっくらPixel Bender をインストールしてみたら普通にGPUに対応しているんだね。
ってことで、簡易ベンチしてみました。
CPUのみで処理(←プロパティで設定できるよ)
GPU処理
#100倍も違うとは。
参考にさせていただいているページ
- Adobe Pixel Bender Toolkit によるFlash Player 10 向けカスタムフィルタの作成
- AIF Toolkitメモ
- Pixel Bender Toolkit:Gallery
- Pixel Bender Exchange
んで、早速クールなフィルターが作りたくて勉強しているのですが、なんか書きづらい。
↓ちょびっと勉強してて感じたことを書いてます。
float4
float4 は 4つの値がいっぺんに格納できる値(配列)って思うと簡単かも。
float3 は3個。float2は2個。floatは1個。
宣言は float4( 1 , 1 , 1 , 1 );
でもまとめて計算もできるっぽい。
float4( 1.0 - 0.5 ) ⇒ float( 1.0 - 0.5 ) float( 1.0 - 0.5 ) float( 1.0 - 0.5 ) float( 1.0 - 0.5 )
まとめて書けるのがとにかく便利。
float4を使う理由は画像のRGBAがまとめて設定できるからだと思う。
出力について
src は読み込み画像
dst は出力画像
srcはいきなり float4に変換されるのであまりフィルター部分では最初だけでそれ以降はあんま見ない。
float4 inputColor;
inputColor = sampleNearest( src , outCoord() ); //outCoord()分かんない
どっちかというと dst で遊ぶ。
dst = sampleNearest( src , outCoord() ); //outCoord()分かんない dst.a = dst.a * 0.5;
普通のプログラムと違うところ
rgbaのセットでまとめて計算できる。
//RGBA値を全部半分 dst.rgba = dst.rgba * 0.5; //こっちでもOK dst = dst * 0.5;
もちろん、個別に計算したい時は dst.r とかで取り出して計算できる。
パラメーター設定
パラメーターはメインプログラムの上に書きます。
Pixel Bender上ではパラメーターがインターフェイスになるのでデバッグが簡単。
//パラメーター作成 parameter float4 ColorRatio < defaultValue:float4(1,1,1,1); >; //メイン部分 input image4 src; output pixel4 dst; void evaluatePixel() { //フィルター部分 }
実際にみんなに使ってもらう
FlashやFlexからはshader.data.paramで設定できるっぽいです(←まだやってない)
shader.data.ColorRatio.value[0]=0.5; shader.data.ColorRatio.value[1]=0.6; shader.data.ColorRatio.value[2]=0.7; shader.data.ColorRatio.value[3]=0.8;
以下は現在勉強中のプログラムのネタです。
RGBA色を変更
<languageVersion:1.0;> kernel NewFilter < namespace:"myname"; vendor:"myname"; version:1; description:"my description"; > { parameter float4 ColorRatio < defaultValue:float4(1,1,1,1); >; input image4 src; output pixel4 dst; void evaluatePixel(){ float4 inputColor; inputColor = sampleNearest( src , outCoord() ); dst = inputColor * ColorRatio; } }
レベルフィルター
<languageVersion : 1.0;> kernel NewFilter < nameSpace : "anttikupila"; vendor : "Antti Kupila"; version : 1; description : "Levels filter"; > { //parameter setting parameter float2 red< minValue :float2( 0 , 0 ); maxValue :float2( 1 , 1 ); defaultValue:float2( 0 , 1 ); >; parameter float2 green< minValue :float2( 0 , 0 ); maxValue :float2( 1 , 1 ); defaultValue:float2( 0 , 1 ); >; parameter float2 blue< minValue :float2( 0 , 0 ); maxValue :float2( 1 , 1 ); defaultValue:float2( 0 , 1 ); >; parameter float2 RGB< minValue :float2( 0 , 0 ); maxValue :float2( 1 , 1 ); defaultValue:float2( 0.1 , 0.9 ); >; //input output image input image4 src; output pixel4 dst; //main program void evaluatePixel(){ //input image pixel4 p; p = sampleNearest( src , outCoord() ); //param RGB Diff float rgbdiff = RGB[1] - RGB[0]; p.r = ( ( p.r - red[0] ) / ( red[1] - red[0] ) - RGB[0] ) / rgbdiff; p.g = ( ( p.g - green[0] )/ ( green[1] - green[0] ) - RGB[0] ) / rgbdiff; p.b = ( ( p.b - blue[0] ) / ( blue[1] - blue[0] ) / - RGB[0] ) / rgbdiff; //output dst = p; } }
セピア
kernel Sepia < namespace: "popforge::ImageProcessing"; vendor: "Joa Ebert"; version: 1; description: "A good looking sepia filter using Y transform"; > { input image4 src; output pixel4 dst; void evaluatePixel() { pixel4 color = sampleLinear( src, outCoord() ); float y = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b; // use min/max instead of if's float r = min(1.0, y + 0.19); float g = max(0.0, y - 0.055); float b = max(0.0, y - 0.22); dst = pixel4(r,g,b,1.0); } }
ピクセレート(モザイク)
<languageVersion : 1.0;> kernel NewFilter < namespace : "Your Namespace"; vendor : "Your Vendor"; version : 1; description : "your description"; > { parameter float2 strength< minValue: float2(1.0); maxValue: float2(64.0); defaultValue: float2(2.0); description: "The strength or square-size."; >; input image4 src; output pixel4 dst; void evaluatePixel() { float2 pos = outCoord(); pos -= mod( pos, strength ); dst = sampleNearest( src, pos ); } }
おそらく outCoord() で現在のx,y座標を取得で sampleNearest( src , pos ) で ActionScript における .draw( src , matrix ) みたいなのをしているもんだと思う。
基本畳み込み。