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


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 – 776 回のダウンロード – 197 KB
リンクなど
SMAA
SMAA : Enhanced Subpixel Morphological Antialiasing