- 追加された行はこの色です。
- 削除された行はこの色です。
*エフェクト-SSAO [#w0f74216]
Screen Space Ambient Occlusion。
スクリーンスペースで遮蔽計算を行う。
以下のロジックはまだ綺麗に出来ていないので改善点はあります。
----
#contents
** 参考サイト [#uc2f1cfa]
床井研究所
床井研究室
http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20101122
** 計算 [#y3346a68]
***サンプル点の計算。 [#l4e131aa]
今回はランダムサンプル。計算式は床井研究室さん参考。
ここで計算した数値を、Uniformで2パス目のシェーダに渡す。
// サンプルする最大数
const int SampleMax = 100;
// サンプルする半径
const float SampleRadius = 0.1f;
// 格納場所
float sample_list[SampleMax][3];
for (int i = 0 ; i < SampleMax ; ++i) {
// 床井研究室
// http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20101122
// crytek方式(半径Rでランダムサンプル)
// v = [-1, 1]の乱数
// u = [0, 1)の乱数
// w = [0, 1]の乱数
// R = 半径
// r = w * R
// x = r * sqrt(1 - v^2) * cos(2 * PI * u)
// y = r * sqrt(1 - v^2) * sin(2 * PI * u)
// z = r * v
float v = static_cast<float>(rand()) / RAND_MAX * 2.0f - 1.0f;
float u = static_cast<float>(rand()) / (RAND_MAX + 1);
float w = static_cast<float>(rand()) / RAND_MAX;
float r = w * SampleRadius;
float t = 2.0f * M_PI * u;
float sp = sqrtf(1.0f - v * v);
float cn = cosf(t);
float sn = sinf(t);
sample_list[i][0] = r * sp * cn;
sample_list[i][1] = r * sp * sn;
sample_list[i][2] = r * v;
}
***描画パス [#ab368829]
事前準備としては、[[Deferred Rendering>エフェクト-Deferred Rendering]]を行い、2パス目の部分に計算を追加する。
また、1パス目にはModelView行列と計算した座標を出力しておく。
// サンプリング最大数
#define SampleMax 100
// サンプル点の補正係数
#define SampleRatio 2.5
float3 SamplingPoint[SampleMax]; // Uniform サンプリングするポイント
float4x4 proj_matrix; // Uniform 1パス目のモデルを描画したProjectionMatrix
float4 normal = tex2D(normal_sampler, tex_coord0); // 1パス目の法線テクスチャ
float4 position = tex2D(position_sampler, tex_coord0); // 1パス目の座標テクスチャ
float4 depth = tex2D(depth_sampler, tex_coord0); // 1パス目の深度テクスチャ
// occlusionの計算
int count = 0;
for (int i = 0 ; i < SampleMax ; ++i) {
// サンプルする座標をずらす
float4 pos = mul(position + float4(SamplingPoint[i], 0.0f), proj_matrix);
pos /= pos.w;
// テクスチャ座標に
pos.xy = pos.xy * 0.5 + 0.5;
pos.y = 1.0 - pos.y;
// サンプルした方が、1パス目の深度より手前にあれば遮蔽されていない
if (pos.z < tex2D(depth_sampler, pos.xy).z) ++count;
}
// 補正を入れ、遮蔽されていない数を最大サンプルで割る
float ao = min((count * SampleRatio) / float(SampleMax), 1.0);
** 参考 [#s0fa481f]
・深度
&ref(ssao-depth.JPG,,40%);
・SSAO抽出結果
&ref(ssao-ssao_lighting.JPG,,40%);
・通常シェーディング
&ref(ssao-deferred_shading.JPG,,40%);
・SSAO付きシェーディング
靴とかの辺りがチラッとだけ。
もっときっちりやらないと見栄えが良くならないかも。
&ref(ssao-ssao_shading.JPG,,40%);
** シェーダコード [#w9575bc5]
1パス目:&ref(deferred_shading.fx);
2パス目:&ref(ssao.fx);