ドッターがアンチエイリアスをかける時の感覚をPixel Benderで再現してみよう
アンチエイリアスの処理を行なう時に,特に重要なのはメモリ使用量と速度だ。となれば,Pixel Benderを使うしかない。
下調べで,色々なアンチエイリアスの方法があることがわかった訳だが,どの方法を取るか。スーパーサンプリングが一般的なようだが,そのためにはPixel Benderに入力する画像(フォント描画)を最低2倍にしなければならない。できればそれは避けたい。
そこでドッターがアンチエイリアスをかける時の感覚をPixel Benderで再現してみたらどうだろうと考えた。
ドット絵の解説本をいくつか当たりつつ考えるに,その感覚とは「上下左右に隣接するカラーピクセルが2つ以上ある透明ピクセルに,隣接しているカラーピクセルの中間色を割り当てる」というように見えた。
それを実装するとこうだ。
一応考えたことは実現できたが,現実的なアンチエイリアス効果とはならなかった。かえって汚くなる場合もあり,まったくもって使えない。スクリーンショットを取る気も起きない(^^);
いかにFPに搭載されているSaffronが優秀であるかを実感した。
いやぁ。やおいかん。
下調べで,色々なアンチエイリアスの方法があることがわかった訳だが,どの方法を取るか。スーパーサンプリングが一般的なようだが,そのためにはPixel Benderに入力する画像(フォント描画)を最低2倍にしなければならない。できればそれは避けたい。
そこでドッターがアンチエイリアスをかける時の感覚をPixel Benderで再現してみたらどうだろうと考えた。
ドット絵の解説本をいくつか当たりつつ考えるに,その感覚とは「上下左右に隣接するカラーピクセルが2つ以上ある透明ピクセルに,隣接しているカラーピクセルの中間色を割り当てる」というように見えた。
それを実装するとこうだ。
<languageVersion : 1.0;>
kernel EdgeAntiAliasFilter
< namespace : "junkoro";
vendor : "Masahito Ohtsuka";
version : 1;
description : "edge anti-aliasing filter";
>
{
//入力画像
input image4 src;
//出力ピクセル
output pixel4 dst;
#if !AIF_FLASH_TARGET
//フィルタースイッチ
parameter bool on
<
defaultValue:bool(true);
>;
//補完エッジ表示スイッチ
parameter bool showEdge;
//補完エッジピクセルカラー
parameter pixel4 edgeColor
<
minValue:pixel4(0);
maxValue:pixel4(1);
defaultValue:pixel4(1, 0, 0, 1);
>;
#endif
//ピクセル処理
void evaluatePixel() {
//現在注目しているピクセルの位置
float2 pos = outCoord();
//3x3の行列の各要素を次のように考える
// LT CT RT
// LM CM RM
// LB CB RB
//上段
//pixel4 pixLT = sampleNearest(src, pos + float2(-1, -1));
pixel4 pixCT = sampleNearest(src, pos + float2(0, -1));
//pixel4 pixRT = sampleNearest(src, pos + float2(1, -1));
//中段
pixel4 pixLM = sampleNearest(src, pos + float2(-1, 0));
pixel4 pixCM = sampleNearest(src, pos + float2(0, 0));
pixel4 pixRM = sampleNearest(src, pos + float2(1, 0));
//下段
//pixel4 pixLB = sampleNearest(src, pos + float2(-1, 1));
pixel4 pixCB = sampleNearest(src, pos + float2(0, 1));
//pixel4 pixRB = sampleNearest(src, pos + float2(1, 1));
//透明ピクセル
pixel4 pixNull = pixel4(0);
//上下左右に隣接するピクセルがあれば加算しつつ隣接ピクセルカウントを増やす
int neighborCnt = 0;
pixel4 pix = float4(0);
if (pixCT != pixNull) {
neighborCnt++;
pix += pixCT;
}
if (pixLM != pixNull) {
neighborCnt++;
pix += pixLM;
}
if (pixRM != pixNull) {
neighborCnt++;
pix += pixRM;
}
if (pixCB != pixNull) {
neighborCnt++;
pix += pixCB;
}
//透明部分でかつ上下左右に隣接するピクセルが2つ以上ある場合のみ処理
//通常コード
#if !AIF_FLASH_TARGET
if (pixCM == pixNull && neighborCnt >= 2 && on) {
if (showEdge) {
//エッジカラーを出力
dst = edgeColor;
} else {
//上下左右,4つのピクセルカラーの平均
pix /= 4.0;
//平均したピクセルを出力
dst = pix;
}
}
#endif
//Flash用コード
#if AIF_FLASH_TARGET
if (pixCM == pixNull && neighborCnt >= 2) {
//上下左右,4つのピクセルカラーの平均
pix /= 4.0;
//平均したピクセルを出力
dst = pix;
}
#endif
else {
//入力ピクセルをそのまま出力
dst = pixCM;
}
}
}
一応考えたことは実現できたが,現実的なアンチエイリアス効果とはならなかった。かえって汚くなる場合もあり,まったくもって使えない。スクリーンショットを取る気も起きない(^^);
いかにFPに搭載されているSaffronが優秀であるかを実感した。
いやぁ。やおいかん。
やおいかんねぇ、この問題は。もう泣こうごたるばい。
返信削除