ライトプリパスレンダリング Part3 アンチエイリアス

アンチエイリアス処理を行います。MSAAによるAAを試しましたがうまくいかなかったため、ポストプロセス処理のAAであるSMAA(Enhanced Subpixel Morphological Antialiasing)を実装してみました。かなりいい感じです。ただ、輪郭線処理との相性が悪いため輪郭線描画は無効にしています。
ライトプリパスレンダリングのプログラム作成は、ここで一旦終了します。

SMAA 1x
SMAA 1x

AAなし
AAなし

SMAA : Enhanced Subpixel Morphological Antialiasing

http://www.iryoku.com/smaa/
MSAAのようなサブピクセルによるAAではなく、レンダリング画像をポストプロセス処理するタイプのAAです。MSAAのように特殊な設定が不要なため、容易に実装できます。複雑な計算処理を行うため、それなりに重い処理です。

処理の流れ

SMAAは3つの処理で構成されます。最初に画像のエッジ検出、次にエッジ検出の結果を使い周囲画素とのブレンド率を計算、最後にブレンド率に従ってブレンド処理。エッジ検出方法は、輝度、色、デプスから選択。2番目の処理では、周囲を広範囲に調べエッジの傾き(方向)を検出し、MSAAなどと同等なAA結果が得られるようなブレンド率計算を行います。
エッジ検出、ブレンド率計算の結果は一旦作業用のレンダーターゲットに出力され、次の処理で参照されるため、少し複雑な処理の流れになります。

実装方法

http://www.iryoku.com/smaa/からソースコードをダウンロード、その中のSMAA.hと事前計算結果を格納したテクスチャを使用します。SMAA.hはシェーダコードに必要なdefine定義を行いinclude、用意された関数をコンパイル、事前計算結果テクスチャは関数の引数に指定します。前計算結果テクスチャはヘッダファイルに定義されたDDSバイナリデータかDDSファイルのどちらかを使います。それから計算結果を出力するレンダーターゲットの作成、設定が必要です。

シェーダコード例

// シェーダモデル DX11なので4.1
#define SMAA_HLSL_4_1	1	

// ピクセルサイズ(画面解像度)
#define SMAA_PIXEL_SIZE float2(1.0/640.0, 1.0/480.0)

// 品質
//#define SMAA_PRESET_LOW		1	//(%60 of the quality)
//#define SMAA_PRESET_MEDIUM	1	//(%80 of the quality)
#define SMAA_PRESET_HIGH	1	//(%95 of the quality)
//#define SMAA_PRESET_ULTRA	1	//(%99 of the quality)

#include "SMAA.h"

//SMAA 1xのみ対応
Texture2D<float4> txColor : register( t0 );		// AA対象の画像(レンダリング結果)
Texture2D<float4> txEdge : register( t1 );		// エッジ検出結果
Texture2D<float4> txBlend : register( t2 );		// ブレンド率計算結果
Texture2D<float4> txArea : register( t3 );		// 事前計算テクスチャ
Texture2D<float4> txSearch : register( t4 );	// 事前計算テクスチャ

//----------------------------------------
// エッジ検出
void EdgeDetectionVS(
        float4 position : POSITION,
        out float4 svPosition : SV_POSITION,
        inout float2 texcoord : TEXCOORD0,
        out float4 offset[3] : TEXCOORD1 )
{
    SMAAEdgeDetectionVS(position, svPosition, texcoord, offset);
}

float4 EdgeDetectionPS(
        float4 position : SV_POSITION,
        float2 texcoord : TEXCOORD0,
        float4 offset[3] : TEXCOORD1) : SV_TARGET
{
    //return SMAAColorEdgeDetectionPS(texcoord, offset, txColor);
    return SMAALumaEdgeDetectionPS(texcoord, offset, txColor);
}

//-----------------------------------------
// ブレンド率計算
void BlendingWeightCalculationVS(
        float4 position : POSITION,
        out float4 svPosition : SV_POSITION,
        inout float2 texcoord : TEXCOORD0,
        out float2 pixcoord : TEXCOORD1,
        out float4 offset[3] : TEXCOORD2 )
{
    SMAABlendingWeightCalculationVS(position, svPosition, texcoord, pixcoord, offset);
}

float4 BlendingWeightCalculationPS(
        float4 position : SV_POSITION,
        float2 texcoord : TEXCOORD0,
        float2 pixcoord : TEXCOORD1,
        float4 offset[3] : TEXCOORD2) : SV_TARGET
{
    int4 subsampleIndices = {0, 0, 0, 0};
    return SMAABlendingWeightCalculationPS(texcoord, pixcoord, offset, txEdge, txArea, txSearch, subsampleIndices);
}

//---------------------------------
// AA実行
void NeighborhoodBlendingVS(
        float4 position : POSITION,
        out float4 svPosition : SV_POSITION,
        inout float2 texcoord : TEXCOORD0,
        out float4 offset[2] : TEXCOORD1 )
{
    SMAANeighborhoodBlendingVS(position, svPosition, texcoord, offset);
}

float4 NeighborhoodBlendingPS(
        float4 position : SV_POSITION,
        float2 texcoord : TEXCOORD0,
        float4 offset[2] : TEXCOORD1,
        uniform SMAATexture2D colorTex,
        uniform SMAATexture2D blendTex) : SV_TARGET
{
    return SMAANeighborhoodBlendingPS(texcoord, offset, txColor, txBlend);
}

//シェーダエフェクト定義
//注意 DX9を参考にした独自のエフェクト定義
#ifdef ZGFX
    technique EdgeDetection
    {
        pass P0
        {
            CullMode = NONE;
            DepthEnable = FALSE;
            AlphaToCoverageEnable = FALSE;
            BlendEnable[0] = FALSE;
			
            VertexShader = compile vs_5_0 EdgeDetectionVS();
            PixelShader = compile ps_5_0 EdgeDetectionPS();
        }
    }

    technique BlendingWeightCalculation
    {
        pass P0
        {
            CullMode = NONE;
            DepthEnable = FALSE;
            AlphaToCoverageEnable = FALSE;
            BlendEnable[0] = FALSE;
			
            VertexShader = compile vs_5_0 BlendingWeightCalculationVS();
            PixelShader = compile ps_5_0 BlendingWeightCalculationPS();
        }
    }
	
    technique NeighborhoodBlending
    {
        pass P0
        {
            CullMode = NONE;
            DepthEnable = FALSE;
            AlphaToCoverageEnable = FALSE;
            BlendEnable[0] = FALSE;
			
            VertexShader = compile vs_5_0 NeighborhoodBlendingVS();
            PixelShader = compile ps_5_0 NeighborhoodBlendingPS();
        }
    }
#endif//ZGFX

SMAAの設定、種類

SMAAの品質はパラメータプリセットが用意されていてdefine定義で指定します。個別のパラメータの調整も可能です。SMAAには1x、S2x、T2x、4xの4つ方法があります。

SMAA 1x

基本的なSMAA、レンダリング結果(静止画像)をAA処理

SMAA S2x

MSAA2xのレンダリング結果をAA処理

SMAA T2x

1つ前のレンダリング結果と速度ベクトルを使ったAA処理、動きのある画像に対応

SMAA 4x

S2xとT2xの組み合わせ


サンプルプログラム

ライトプリパスPart3 SMAAによるアンチエイリアス

“ライトプリパスPart3 SMAAによるアンチエイリアス” をダウンロード dx11LightPrePass3.zip – 640 回のダウンロード – 197 KB


リンクなど

SMAA

SMAA : Enhanced Subpixel Morphological Antialiasing

スクリーンショットのモデルとモーション

キャラクターモデル

ままま式GUMIβ版 / 3xma

モーション

【第9回MMD杯Ex】星間飛行GUMI/ニコニコ動画

背景モデルデータ

ぴくちぃ式 背景パック 1.3 M5ミクちゃん部屋 / MshZ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

認証:数字を入力してください(必須) * Time limit is exhausted. Please reload CAPTCHA.