スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

DXライブラリでFXAA

こんにちは、未だスカイリム満喫中のペチコです
現実逃避とも言います

スカイリム

今回はアンチエイリアシング技法の一つFXAAで遊びます
SMAAとかEdgeAAに失敗したので今更FXAAです


取り敢えず画質比較。画像はクリックで大きくなります
AAなしFXAA
AAなし
FXAA

4x16x
4x
16x


細かいところ
AA比較

jpegな時点で元とは違うというのはおいといて、拡大すると16xもボケボケしてますが、上を見ると流石の画質です
FXAAの弱点として画面がぼやけた感じになるのですが、ロープ部分はそれが顕著に見られます


パフォーマンス(1フレームに掛かったμ秒)
コグ400隻
無駄に400隻の船団を組んでみました
単純な画面だと数字が細かすぎて誤差の範囲に収まってしまうので。。。

AAなし1300-1600FXAA1400-18004x1600-200016x2000-16000

揺れ幅は適当に目測です
前のプロジェクトの使い回しなので随分無駄な処理が入っていて正確ではないかもですが、大体画質通りのパフォーマンスですね
16xは揺れ幅が大きすぎて平均が掴めませんでした


FXAAは2DシェーダなのでAAを掛けたものにさらに適用できます
FXAA+4x
4xにFXAAを掛けたもの
パフォーマンスは2200近辺。画質はうーん…


HLSLはこちらのサイト様の丸ぱくりです
理解する事に頭を使うより、頭の良い方をいかにパクるかに全力を懸けていますダメ人間

FXAAPS.fx
// ディフューズマップテクスチャ
sampler DiffuseMapTexture : register( s0 ) ;

float FxaaLuma(float4 rgba) {
//(ax * bx + ay * by + az * bz) NTSCグレースケール化
return dot(rgba.rgb, float3(0.299, 0.587, 0.114));
}

float4 main(float2 Tex : TEXCOORD0) : COLOR0
{
//周囲の座標取得用
float2 Pos_h = (0.5f/1024.0f,0.5f/768.0f);
float2 Pos_t = (2.0f/1024.0f,2.0f/768.0f);

//周囲の座標
float4 ConsolePos = float4(Tex.x - Pos_h.x, Tex.y - Pos_h.y, Tex.x + Pos_h.x, Tex.y + Pos_h.y);

float luma_LT = FxaaLuma(tex2D(DiffuseMapTexture, ConsolePos.xy));
float luma_LB = FxaaLuma(tex2D(DiffuseMapTexture, ConsolePos.xw));
float luma_RT = FxaaLuma(tex2D(DiffuseMapTexture, ConsolePos.zy)) +0.002604167;
float luma_RB = FxaaLuma(tex2D(DiffuseMapTexture, ConsolePos.zw));
float4 luma_C = tex2D(DiffuseMapTexture, Tex); //中央

//周囲の最大最小
float luma_Max = max(max(luma_RT, luma_RB), max(luma_LT, luma_LB));
float luma_Min = min(min(luma_RT, luma_RB), min(luma_LT, luma_LB));

//最大照度の1/8
float lumaMaxScaledClamped = max(0.05, luma_Max * 0.125);

//グレースケール
float luma_M = FxaaLuma(luma_C);
//照度差
float lumaMaxSubMinM = max(luma_Max, luma_M) - min(luma_Min, luma_M);

//変化を比較
if(lumaMaxSubMinM < lumaMaxScaledClamped)
{
//変化が少ない場合は元の色を返す
return luma_C;
}
else
{
//各方向の照度差
float dirSwMinusNe = luma_LB - luma_RT;
float dirSeMinusNw = luma_RB - luma_LT;

//照度ベクトル
float2 dir1 = normalize(float2(dirSwMinusNe + dirSeMinusNw, dirSwMinusNe - dirSeMinusNw));
//照度ベクトルの差
float2 dirAbsMinTimesC = dir1 / (8.0 * min(abs(dir1.x), abs(dir1.y)));
//範囲に収める
float2 dir2 = clamp(dirAbsMinTimesC, -2.0, 2.0) * Pos_t;

//移動量算出
dir1 *= Pos_h;
//各方向取得
float4 rgbyN1 = tex2D(DiffuseMapTexture, Tex - dir1); //半ドット×照度ベクトル 左上
float4 rgbyP1 = tex2D(DiffuseMapTexture, Tex + dir1); //半ドット×照度ベクトル 右下
float4 rgbyN2 = tex2D(DiffuseMapTexture, Tex - dir2); //2ドット×照度ベクトル 左上
float4 rgbyP2 = tex2D(DiffuseMapTexture, Tex + dir2); //2ドット×照度ベクトル 右下
//加算した値
float4 rgbyA = rgbyN1 + rgbyP1; //加算して結果を保存
//1/4した値
float4 rgbyB = (rgbyN2 + rgbyP2 + rgbyA) * 0.25;

//グレースケール
float rgbyBM = FxaaLuma(rgbyB);
//半値分岐
if((rgbyBM < luma_Min) || (rgbyBM > luma_Max))
{
//1/2を返す
return rgbyA * 0.5;
}
else
{
//1/4を返す
return rgbyB;
}
}
}


VERTEX2DSHADERで予め板ポリゴンを作っておいて、通常描画した画面をテクスチャとして、DrawPrimitive2DToShaderで描画します
その辺りは他でやってるぼかしとかグローとか見て頂けると幸いです

画面の半ドットと2ドットを取得する処理(float2 Pos_h = (0.5f/1024.0f,0.5f/768.0f)~部分)をコード内決め打ちでやってますが、画面サイズ固定でない場合はC++の方からレジスタで渡さないといけませぬ

画面全体にAAが掛かるので、文字とかUIはFXAA掛けた後に描画しないとボケボケになります
まるでペチコの頭のように


コメントの投稿

非公開コメント

プロフィール

ペチコートさん

Author:ペチコートさん
大航海時代オンライン
Zephyros、Eurosサーバーに潜伏中

偽ペチコ1号・2号
ペチコの手下達
Zephyrosサーバーに潜伏中

最新記事
月別アーカイブ
カテゴリ
リンク
最新コメント
検索フォーム
QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。