Starling2 ScanLineFilter他の作成

新たにAGAL1でStarling2用のフィルターを2つつくりました。テレビの捜査線のようなスキャンラインフィルターと、そのななめ限定版のスラッシュシェードフィルターです。後半にざっとAGALコードを解説します。デモはこちらに。 http://harayoki.github.io/qiita_demo/Scanline1/index.html

<img width="258" src="https://qiita-image-store.s3.amazonaws.com/0/8302/d755c6a5-d324-7159-13ef-3c0a446250f9.png">
_ScanLineFilter。テレビっぽいやつです。ラインの太さと間隔とカラーと透明度などが指定できます。_

<img width="273" src="https://qiita-image-store.s3.amazonaws.com/0/8302/4c906f73-448d-038e-3fb5-3e6bb1573185.png">
_ななめ45度専用のSlashShadedFilter。こちらも線の間隔と色・透明度が指定できます。_

<img width="262" src="https://qiita-image-store.s3.amazonaws.com/0/8302/96d3b828-bb6e-267d-f679-c42f1c5bfa25.png">
_ScanLineFilterは角度も変えられるのでSlashSadedFilterが要らなそうですですが、後者の方が決め打ちの処理によってよりドットが綺麗です。_

<img width="285" src="https://qiita-image-store.s3.amazonaws.com/0/8302/53c94542-47cd-63c5-301e-59a31883b0b5.png">
_ScanLineFilterは重ねがけするとモアレがでてきて面白いです。なお、各フィルタは元画像が半透明の部分にもいい感じにラインが入ります。_

#ScanLineFilterの使い方

コンストラクタやプロパティで、線の太さ、角度、線の間の距離、カラー、アルファ、が設定できます。距離がマイナスの値だと線になる部分と画像のままの部分の比率が逆転します。

```example.as
var filter:ScanLineFilter = new ScanLineFilter(2.0, 0, 1, 0xffffff, 1.0);
filter.scale = 1.0;
filter.degree = 90;
filter.distance = -3; // マイナスもOK (-5 ~ 5 の範囲)
filter.color = 0xff00ff;
filter.alpha = 0.5;
someQuad.filter = filter;
```

#SlashSadedFilterの使い方
似た感じですが、角度が２種類しか指定できません。専用処理にしたことでScanLineFilterよりもドット処理が綺麗になっています。コンストラクタやプロパティで、線の間の距離、カラー、アルファ、斜めの向き(右下方向/左下方向)が設定できます。距離がマイナスの値はとれません。

```example.as
var filter:SlashSadedFilter = new SlashSadedFilter(4, 0x000000m 1.0, SlashShadedFilter.TYPE_SLASH);
filter.distance = 2;
filter.color = 0xff00ff;
filter.alpha = 0.5;
filter.type = SlashShadedFilter.TYPE_BACK_SLASH; // スラッシュ(／)か逆(＼)で斜めの方向を指定
someQuad.filter = filter;
```

#ScanLineFilterのAGALコード

大雑把にポイントだけ説明します。Fragmentシェーダに渡す定数は以下３つです。

fc0 : カラーRGBA値
fc1 : 計算用固定値0、線の距離、反転フラグ(反転なし：1 or 反転:0)、線の位置のオフセット
fc2 : 回転と拡大のmatrix
(0を定数で１つ渡しておくていろいろ便利です。これについては別の投稿で。)

Vertexシェーダーではスクリーンへの座標変換をかける前のva0値(Starlingから渡されてくる)もそのままv1としてFragmentシェーダーに受け渡します。これをFragment側でそのままドット座標値として演算しています。

Fragmentシェーダーではこのy座標によって線を描画するかしないかを決定するのですが、その判定前にMatrix演算で回転と拡大を適用することで、描画される線も回転拡大がかけられてます。

N行ごとにラインを描画する座標かどうかは
`(floor(y) / N) == 0`
この判定を満たすかどうかでジャッジしています。式で書くと簡単ですが、AGALに変換すると頭を使います。

条件を満たす行の場合、RGB値は指定の値に、アルファ値は元画像のアルファ値に指定アルファ値をかけたものを使います。これによって透明部分にはラインが描画されません。半透明部分には半透明のラインが引かれます。

そのほか、 距離が0指定の時はラインを描画しない、距離がマイナス値の時はライン部分と画像部分を反転する、などの処理を行っています。

ScanLineFilter.asのコードはこちらにあります。具体的なコードはこちらで。
https://github.com/harayoki/Starling2FiltersAndStyles/blob/master/src/harayoki/starling2/filters/ScanLineFilter.as

今回から、AGALのコードを書き出すのに自作の[AGALユーティリティクラス](https://github.com/harayoki/AGALCodePrinters)を使っています。ある程度の型保管を受けながら以下のような感じでAGALが記述できます。まだブラッシュアップ&バグ取り中なので、今回は紹介しませんが、機会あれば。現状でもそこそこ便利です。生でAGALを書くよりはずっと楽です。

```sample.as
move(ft7, fc1);
divide(ft0.xyz, ft0.xyz, ft0.www);
move(ft1, v1);
multiplyMatrix3x3(ft1.xyz, ft1.xyz, MATRIX);
:
:
```

#SlashSadedFilterのAGALコード

こちらもかいつまんで解説します。

ScanLineFilterの処理では、斜め45度になった際、一部ドット欠けのような描画ができる場合がありました。そもそもこの斜め斜線フィルタが作たくて、そのベースとしてScanLineFilterを作ったのですが、完全に綺麗な描画にならなかったので、専用処理で書き直しました。

VertexシェーダーはScanLineFilterと同じです。

Fragmentシェーダーに渡す定数は以下３つです。

fc0 : カラーRGBA値
fc1 : 未使用、線の距離、斜線方向(／=0、＼=1)、線の位置のオフセット(をAGAL内で計算が楽なように調整したもの)
fc2 : 計算用固定値0、1、２、３

途中までScanLineFilterと同じような感じですが、ライン描画判定が異なります。
方眼にパターンをかいて、ロジックを考えたところ、`((x % N) + (y % N)) == N-1` この判定でNドット間隔で斜めの線が引ける事がわかりました。こちらも式にすると簡単なのですが、AGALに変換するのはしんどいです。

斜めの方向を反転させる式がちょっとトリッキーになっています。説明が難しいので省略しますが、もっと上流で左右座標反転のMatrix演算するだけで良かった気がします。（つまり意味なく難しい事をしていまったので、参考にならない。作り直すのが面倒なのでこのまま。。）

SlashShadedFilterのコードはこちらにあります。
https://github.com/harayoki/Starling2FiltersAndStyles/blob/master/src/harayoki/starling2/filters/SlashShadedFilter.as

#おわりに
上記のフィルターは通常画像にアルファを与えるような場面で使うとかっこいい(?)表現になると思うので、FilterではなくStyleにした方が使いかっては良さそうです。Style化は機会があれば。

さて、ここまでで合計３つのStarling2フィルターを作ってみて、自己流ですが、AGALコーディングのノウハウがある程度たまりました。これは別途記事にまとめようと思います。（とはいえ今回のコードにも完全にノウハウ活かせてないんですが。）