Shader について
■ Shader について
■シェーダー機能について
Flash 10 以降から、Shader 機能が追加されました。
ピクセルシェーダーの一種です。画像処理に特化しています。
■シェーダーの開発ツールについて
Pixel Bender Toolkit というツールを使用します。
専用の言語を使用します。
Toolkit から、バイトコードファイル(PBJ) を出力できます。
■ Shader クラスについて
Pixel Bender 内の、カーネル(Kernel) に該当します。
■ Shader オブジェクトを使用する
■ Shader オブジェクトを準備する
Shader オブジェクトに、バイトコード(PBJ) のバイナリを渡します。
■フィルタとして活用する
ShaderFilter クラスにて使用します。
■ブレンドとして活用する
blendShader プロパティに渡します。
■描画時にスタイルとして活用する
Graphics クラスにて使用します。
Shader オブジェクトを作成する
■ Shader オブジェクトを作成する
■ Shader オブジェクトを作成する
new 演算子を使って、Shader クラスをインスタンス化します。
引数に、バイトコードファイル(PBJ) のバイナリを指定します。
new Shader ( バイトコード ) :Shader
第01引数(略可) | ByteArray | byteCode プロパティと同等 |
戻り値 | Object | Object オブジェクト |
■作成例
Shader オブジェクトを作成する
import flash.display.Shader;
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = new Shader();
// 出力テスト
trace(shader_obj);
シェーダーバイトコードを設定する
■Shaer オブジェクトにバイトコードをセットする
byteCode プロパティを使用します。
このプロパティは、書き込み専用です。
セットした場合、内部の ShaderData オブジェクトも一新されます。
■バイトコードファイルを、静的に埋め込んで、バイナリを取得する
1.バイトコードファイルを埋め込む
Embed メタタグを使用します。
Adobe Flash CS4 以降から利用可能です。
source パラメータに、バイトコードファイル(PBJ) のパスを指定します。
プロジェクトからの相対パスを指定します。
mimeType パラメータに、"application/octet-stream" を指定します。
続けて、クラス名を宣言します。
ここでは、"MyByteCode" と名前を付けます。
埋め込みアセットクラスを設定する
[Embed( source="./sample.pbj" , mimeType="application/octet-stream" )]
var MyByteCode:Class;
2.Flash を書き出して、データの埋め込みを確認する
この状態で、Flash を書き出します。
すると、swf ファイルにデータが埋め込まれるようになります。
swf ファイルのサイズが増えたか、確認します。
3.ByteArray オブジェクトを作成する
MyByteCode クラスを、new 演算子を使ってインスタンス化します。
このクラスは、ByteArray クラスを継承しています。
埋め込んだファイルから、ByteArray オブジェクトを作成する
import flash.utils.ByteArray;
import flash.display.Shader;
// ------------------------------------------------------------
// 埋め込みアセットクラス
// ------------------------------------------------------------
[Embed( source="./sample.pbj" , mimeType="application/octet-stream" )]
var MyByteCode:Class;
// ------------------------------------------------------------
// 埋め込んだファイルから、ByteArray オブジェクトを作成する (自作クラス "MyByteCode" )
// ------------------------------------------------------------
var byte_code:ByteArray = new MyByteCode();
// 出力テスト
trace(byte_code);
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = new Shader(byte_code);
// 出力テスト
trace(shader_obj);
■バイトコードファイルを、動的に読み込んで、バイナリを取得する
外部ファイルを読み込んでバイナリを取得する
取得例
外部のファイルを読み込んで、バイナリを取得する
import flash.display.Shader;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.utils.ByteArray;
import flash.events.Event;
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = new Shader();
// ------------------------------------------------------------
// URLLoader オブジェクトを作成
// ------------------------------------------------------------
var url_loader:URLLoader = new URLLoader();
// 受信結果をバイナリ形式で取得する
url_loader.dataFormat = URLLoaderDataFormat.BINARY;
// ------------------------------------------------------------
// 読み込み完了時に実行されるイベント
// ------------------------------------------------------------
url_loader.addEventListener (Event.COMPLETE , function (e:Event):void{
// ------------------------------------------------------------
// 受信結果(レスポンスボティ)を取得する
// ------------------------------------------------------------
var byte_code:ByteArray = url_loader.data as ByteArray;
// 出力テスト
trace(byte_code);
// ------------------------------------------------------------
// バイトコードをセットする
// ------------------------------------------------------------
shader_obj.byteCode = byte_code;
});
// ------------------------------------------------------------
// 読み込みを開始する
// ------------------------------------------------------------
// URLRequest オブジェクトを作成する(アクセス先 URL を指定)
var url_request:URLRequest = new URLRequest( "./sample.pbj" );
// 読み込みを開始する
url_loader.load(url_request);
パラメータを設定する
■ ShaderData クラスについて
ShaderData クラスについて
シェーダー内の情報にアクセスするには、ShaderData クラスを使用します。
ShaderData オブジェクトを取得する
data プロパティを使用します。
Shader から、ShaderData オブジェクトを取得する
import flash.display.Shader;
import flash.display.ShaderData;
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = new Shader();
// ------------------------------------------------------------
// ShaderData オブジェクトを取得する
// ------------------------------------------------------------
var shader_data:ShaderData = shader_obj.data;
// 出力テスト
trace(shader_data);
ShaderData オブジェクトについて
ShaderData オブジェクトは、連想配列です。
以下のデータが、混在して格納されています。
データ型 | 説明 |
String | カーネルの「メタデータ」関連の情報。 |
ShaderParameter | カーネルの「パラメータ変数」関連の情報。 |
ShaderInput | カーネルの「入力変数(ビットマップ)」関連の情報。 |
カーネルメタデータ情報を取得する
カーネルのメタデータ情報を取得できます。
以下のプロパティ名を使って、読み取りアクセスします。
省略されている場合もあります。
プロパティ名 | データ型 | 説明 |
name | String | カーネル名を取得。 |
nameSpace | String | カーネルの名前空間を取得。 |
vendor | String | カーネルのベンダー情報を取得。 |
version | String | カーネルのバージョン値を取得。 |
description | String | カーネルの説明情報を取得。 |
ShaderParameter オブジェクトを取得する
パラメータ変数に付けた変数名で、プロパティにアクセスします。
ShaderInput オブジェクトを取得する
入力変数に付けた変数名で、プロパティにアクセスします。
ShaderParameter オブジェクトを抽出取得する
for..in 文を使って、ShaderParameter 型のオブジェクトを抽出します。
index プロパティは、パラメータ変数の宣言順です。
ShaderParameter オブジェクトをまとめて取得する関数
import flash.display.ShaderData;
import flash.display.ShaderParameter;
// ------------------------------------------------------------
// ShaderParameter オブジェクトをまとめて取得する関数
// ------------------------------------------------------------
function ShaderDataGetParameterList(shader_data:ShaderData):Array{
var a:Array = new Array();
var p:ShaderParameter;
var k:String;
for(k in shader_data){
p = shader_data[k] as ShaderParameter;
if(!p) continue;
a[p.index] = p;
}
return a;
}
ShaderInput オブジェクトを抽出取得する
for..in 文を使って、ShaderInput 型のオブジェクトを抽出します。
index プロパティは、入力変数の宣言順です。
ShaderInput オブジェクトをまとめて取得する関数
import flash.display.ShaderData;
import flash.display.ShaderInput;
// ------------------------------------------------------------
// ShaderInput オブジェクトをまとめて取得する関数
// ------------------------------------------------------------
function ShaderDataGetInputList(shader_data:ShaderData):Array{
var a:Array = new Array();
var i:ShaderInput;
var k:String;
for(k in shader_data){
i = shader_data[k] as ShaderInput;
if(!i) continue;
a[i.index] = i;
}
return a;
}
取得例
ShaderData オブジェクト内のすべてのデータにアクセスする
import flash.utils.ByteArray;
import flash.display.Shader;
import flash.display.ShaderData;
import flash.display.ShaderParameter;
import flash.display.ShaderInput;
var i:int;
var num:int;
var key:String;
// ------------------------------------------------------------
// 埋め込みアセットクラス
// ------------------------------------------------------------
[Embed( source="./sample.pbj" , mimeType="application/octet-stream" )]
var MyByteCode:Class;
// ------------------------------------------------------------
// 埋め込んだファイルから、ByteArray オブジェクトを作成する (自作クラス "MyByteCode" )
// ------------------------------------------------------------
var byte_code:ByteArray = new MyByteCode();
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = new Shader(byte_code);
// ------------------------------------------------------------
// ShaderData オブジェクトを取得する
// ------------------------------------------------------------
var shader_data:ShaderData = shader_obj.data;
// ------------------------------------------------------------
// ShaderParameter オブジェクトをまとめて取得する関数
// ------------------------------------------------------------
function ShaderDataGetParameterList(shader_data:ShaderData):Array{
var a:Array = new Array();
var p:ShaderParameter;
var k:String;
for(k in shader_data){
p = shader_data[k] as ShaderParameter;
if(!p) continue;
a[p.index] = p;
}
return a;
}
// ------------------------------------------------------------
// ShaderParameter オブジェクトをまとめて取得する
// ------------------------------------------------------------
var shader_parameter_list:Array = ShaderDataGetParameterList(shader_data);
num = shader_parameter_list.length;
for(i=0;i < num;i++){
// ShaderParameter オブジェクトを取得する
var shader_parameter:ShaderParameter = shader_parameter_list[i];
// 出力テスト(プロパティ)
trace("index" , shader_parameter.index);
trace("type" , shader_parameter.type);
trace("value" , shader_parameter.value);
// 出力テスト(メタデータ)
for(key in shader_parameter){
trace(key , shader_parameter[key]);
}
trace(" --- ");
}
// ------------------------------------------------------------
// ShaderInput オブジェクトをまとめて取得する関数
// ------------------------------------------------------------
function ShaderDataGetInputList(shader_data:ShaderData):Array{
var a:Array = new Array();
var i:ShaderInput;
var k:String;
for(k in shader_data){
i = shader_data[k] as ShaderInput;
if(!i) continue;
a[i.index] = i;
}
return a;
}
// ------------------------------------------------------------
// ShaderInput オブジェクトをまとめて取得する
// ------------------------------------------------------------
var shader_input_list:Array = ShaderDataGetInputList(shader_data);
num = shader_input_list.length;
for(i=0;i < num;i++){
// ShaderInput オブジェクトを取得する
var shader_input:ShaderInput = shader_input_list[i];
// 出力テスト(プロパティ)
trace("index" , shader_input.index);
trace("channels" , shader_input.channels);
trace("width" , shader_input.width);
trace("height" , shader_input.height);
trace("input" , shader_input.input);
// 出力テスト(拡張情報)
for(key in shader_input){
trace(key , shader_input[key]);
}
trace(" --- ");
}
■ ShaderParameter クラスについて
ShaderParameter クラスについて
プロパティ一覧
プロパティ名 | データ型 | 説明 |
index | int | パラメータ変数の宣言位置を取得。(上から昇順) |
type | String | パラメータ変数の型名を取得。(ShaderParameterType.*) |
value | Array | 値情報をセットする。(パラメータ変数に渡す) |
メタデータ情報を取得する
ShaderParameter オブジェクトは、連想配列です。
メタデータ情報も、格納されています。
for..in 文を使うと、メタデータ情報のみを、すべて抽出できます。
メタデータの一例です。
プロパティ名 | データ型 | 説明 |
name | String | パラメータ変数名を取得。 |
defaultValue | Array | 初期値を取得。 |
minValue | Array | 最小値を取得。 |
maxValue | Array | 最大値を取得。 |
stepInterval | Array | 1ステップごとに変化する最小単位を取得。 |
previewValue | Array | プレビュー時に最適な値を取得。 |
「値情報」を「パラメータ変数」に渡す
value プロパティを使用します。
値情報を、配列に格納して渡す必要があります。
例えば、float 型であれば、要素は 1 個必要です。
例えば、float3 型であれば、要素は 3 個必要です。
例えば、float4 型であれば、要素は 4 個必要です。
例えば、float3x3 型であれば、要素は 9 個必要です。
例えば、float4x4 型であれば、要素は 16 個必要です。
■ ShaderInput クラスについて
ShaderInput クラスについて
プロパティ一覧
プロパティ名 | データ型 | 説明 |
index | int | 入力変数の宣言位置を取得。(上から昇順) |
channels | int | 入力変数のカラーチャンネル数を取得。 |
input | Object | ビットマップ情報をセットする。(入力変数に渡す) |
width | int | ビットマップの幅を設定。 |
height | int | ビットマップの高さを設定。 |
拡張情報を取得する
プロパティ名 | データ型 | 説明 |
name | String | 入力変数名を取得。 |
「BitmapData オブジェクト」を「入力変数」に渡す
input プロパティに、BitmpData オブジェクトを渡します。
width、height プロパティの設定は不要です。
「ByteArray オブジェクト」を「入力変数」に渡す
最初に、width、height プロパティを設定します。
次に、input プロパティに、ByteArray オブジェクトを渡します。
用意するバイナリは、0.0 ~ 1.0 の連続した数値データです。
赤、緑、青、透過チャンネルの順序で書き込みます。
(赤|緑|青|透過) | (赤|緑|青|透過) | (赤|緑|青|透過) ...
「Vector.<Number> オブジェクト」を「入力変数」に渡す
最初に、width、height プロパティを設定します。
次に、input プロパティに、Vector.<Number> オブジェクトを渡します。
0.0 ~ 1.0 の連続した数値データです。
赤、緑、青、透過チャンネルの順序で書き込みます。
(赤|緑|青|透過) | (赤|緑|青|透過) | (赤|緑|青|透過) ...
■パラメータの設定例
■使用例(Pixel Bender 側のコード)
「元のグラフィック」「1枚目のソースイメージ」間をマージする
<languageVersion : 1.0;>
// ------------------------------------------------------------
// カーネルを宣言
// ------------------------------------------------------------
kernel MyKernel < namespace:""; vendor:""; version:1; > {
// ------------------------------------------------------------
// 入力変数の宣言(ビットマップ)
// ------------------------------------------------------------
// 1枚目の入力イメージ(フィルタを適用する直前のグラフィック)
input image4 src0;
// 2枚目の入力イメージ(外部から渡される1枚目のソース)
input image4 src1;
// ------------------------------------------------------------
// 出力変数の宣言(ピクセルカラー)
// ------------------------------------------------------------
output pixel4 dst;
// ------------------------------------------------------------
// パラメータ変数の宣言
// ------------------------------------------------------------
// 透明度
parameter float alpha
<
minValue : 0.0;
maxValue : 1.0;
stepInterval : 0.01;
defaultValue : 0.5;
>;
// スクロール値
parameter float2 scroll
<
minValue : float2( -2096.0 , -2096.0 );
maxValue : float2( 2096.0 , 2096.0 );
stepInterval : float2( 0.01 , 0.01 );
defaultValue : float2( 0.0 , 0.0 );
>;
// ビットマップのサイズ(入力変数 "src1" )
parameter float2 src1Size
<
parameterType : "inputSize";
inputSizeName : "src1";
>;
// ------------------------------------------------------------
// ピクセルごとに実行される関数
// ------------------------------------------------------------
void evaluatePixel() {
// 現在のピクセル位置を取得する
float2 pos0 = outCoord();
// スクロールを加算
float2 pos1 = pos0 + scroll;
// 画像のサイズ
float w = src1Size.x;
float h = src1Size.y;
// 位置を画像のサイズ内に収める
pos1.x -= floor(pos1.x / w) * w;
pos1.y -= floor(pos1.y / h) * h;
// 位置を指定して、画像からピクセルカラーを取得する(ニアレストネイバー)
pixel4 color0 = sampleNearest(src0 , pos0);
pixel4 color1 = sampleNearest(src1 , pos1);
// ピクセルカラーを出力する
dst = (color1 - color0) * alpha + color0;
}
}
■使用例(Flash 側のコード)
シェーダーを渡して、フィルタを動作させる
import flash.utils.ByteArray;
import flash.display.Shader;
import flash.display.ShaderData;
import flash.display.ShaderParameter;
import flash.display.ShaderInput;
import flash.display.Shape;
import flash.display.Graphics;
import flash.display.BitmapData;
import flash.filters.ShaderFilter;
// ------------------------------------------------------------
// Shape オブジェクトを作成する
// ------------------------------------------------------------
var shape:Shape = (function():Shape{
// Shape オブジェクトを作成
var shape:Shape = new Shape();
// Shape に矩形を描画
var g:Graphics = shape.graphics;
g.beginFill ( 0xFFE0E0 , 1.0 );
g.drawRect( 0 , 0 , stage.stageWidth , stage.stageHeight );
g.endFill();
return shape;
})();
// ステージに配置する
stage.addChild(shape);
// ------------------------------------------------------------
// BitmapData オブジェクトを作成する
// ------------------------------------------------------------
var bmp_data:BitmapData = (function():BitmapData{
// BitmapData オブジェクトを作成する
var bmp_data:BitmapData = new BitmapData( 256 , 256 , true , 0x00000000 );
// イメージにパーリンノイズを描画する
bmp_data.perlinNoise(
64,
64 ,
1,
Math.floor(Math.random() * 0x7FFFFFFF),
true,
false,
(0),
true
);
return bmp_data;
})();
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = (function():Shader{
// 埋め込みアセットクラス
[Embed( source="./filter.pbj" , mimeType="application/octet-stream" )]
var MyByteCode:Class;
// 埋め込んだファイルから、ByteArray オブジェクトを作成する (自作クラス "MyByteCode" )
var byte_code:ByteArray = new MyByteCode();
return new Shader(byte_code);
})();
(function():void{
// ------------------------------------------------------------
// ShaderData オブジェクトを取得する
// ------------------------------------------------------------
var shader_data:ShaderData = shader_obj.data;
// ------------------------------------------------------------
// ShaderParameter オブジェクトを取得する
// ------------------------------------------------------------
var parameter_alpha:ShaderParameter = (shader_data["alpha"]) as ShaderParameter;
var parameter_scroll:ShaderParameter = (shader_data["scroll"]) as ShaderParameter;
var parameter_src1Size:ShaderParameter = (shader_data["src1Size"]) as ShaderParameter;
// ------------------------------------------------------------
// ShaderInput オブジェクトを取得する
// ------------------------------------------------------------
var input_src1:ShaderInput = (shader_data["src1"]) as ShaderInput;
// ------------------------------------------------------------
// サポートチェック
// ------------------------------------------------------------
if(!(parameter_src1Size)) return;
if(!(parameter_alpha)) return;
if(!(parameter_scroll)) return;
if(!(input_src1)) return;
// ------------------------------------------------------------
// 入力変数 "src1" に、BitmapData オブジェクトを渡す
// ------------------------------------------------------------
input_src1.input = bmp_data;
// ------------------------------------------------------------
// パラメータ変数 "src1Size" に、ビットマップのサイズを渡す
// ------------------------------------------------------------
parameter_src1Size.value = [ bmp_data.width , bmp_data.height ];
// ------------------------------------------------------------
// ShaderFilter オブジェクトを作成する
// ------------------------------------------------------------
var shader_filter:ShaderFilter = new ShaderFilter(shader_obj);
var alpha:Number;
var rad:Number = 0.0;
// ------------------------------------------------------------
// 毎フレーム実行されるイベント
// ------------------------------------------------------------
stage.addEventListener(Event.ENTER_FRAME , function (e:Event):void{
// ------------------------------------------------------------
// 透明度を変更
// ------------------------------------------------------------
rad += 10 * Math.PI / 180;
alpha = (Math.sin(rad) + 1.0) * 0.5;
alpha = alpha * 0.5 + 0.25;
// ------------------------------------------------------------
// 入力変数 "alpha" に、透明値を渡す
// ------------------------------------------------------------
parameter_alpha.value = [alpha];
// ------------------------------------------------------------
// 入力変数 "scroll" に、マウス位置を渡す
// ------------------------------------------------------------
parameter_scroll.value = [ -stage.mouseX , -stage.mouseY ];
// ------------------------------------------------------------
// フィルタを更新する
// ------------------------------------------------------------
shape.filters = [shader_filter];
});
})();
算術演算の精密度を指定する
■算術演算の精密度を指定する
precisionHint プロパティを使用します。
ShaderPrecision.* 定数を指定します。
詳しい仕様は、公式リファレンスが参考になります。
http://help.adobe.com/ja_JP/FlashPlatform/reference/actionscript/3/flash/display/Shader.html#precisionHint
定数 | 文字列 | 説明 |
ShaderPrecision. | "full" | デフォルトのモードです。 すべての環境で同じ結果が得られます。 |
ShaderPrecision. | "fast" | より高速で動作するモードです。 CPU 環境によって結果が異なる場合があります。 |
シェーダーの算術演算の精密度を指定する
import flash.utils.ByteArray;
import flash.display.DisplayObject;
import flash.display.Shader;
import flash.display.ShaderPrecision;
import flash.filters.ShaderFilter;
// ------------------------------------------------------------
// 埋め込みアセットクラス
// ------------------------------------------------------------
[Embed( source="./sample.pbj" , mimeType="application/octet-stream" )]
var MyByteCode:Class;
// ------------------------------------------------------------
// 埋め込んだファイルから、ByteArray オブジェクトを作成する (自作クラス "MyByteCode" )
// ------------------------------------------------------------
var byte_code:ByteArray = new MyByteCode();
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = new Shader(byte_code);
// ------------------------------------------------------------
// 算術演算の精密度を指定する
// ------------------------------------------------------------
shader_obj.precisionHint = ShaderPrecision.FAST;
// ------------------------------------------------------------
// ShaderFilter オブジェクトを作成する
// ------------------------------------------------------------
var shader_filter:ShaderFilter = new ShaderFilter(shader_obj);
// ------------------------------------------------------------
// Document 表示オブジェクトに、フィルタを適用する
// ------------------------------------------------------------
var document_obj:DisplayObject = stage.getChildAt(0);
document_obj.filters = [shader_filter];