SSAO
Screen Space에서 화면에 보이는 오브젝트만 Ambient Occlusion을 통해 특정 점을 기준으로 구를 그려 한번씩 체크하여
다른 점을 발견하면 그 점에 대해 차폐됬다고 판단하여 어둡게 처리하는 방식.
Camera View 공간에서 Depth 값과 Normal 값을 이용하여 처리.
// SSAO Pass전 Depth Buffer 생성..
vout.Depth = float4(normalV, pin.PosV.z);
float4 SSAO_PS(VertexIn pin) : SV_Target
{
float4 normalDepth = gDepthMap.SampleLevel(gSamBorderLinearPoint, pin.Tex, 0.0f);
// View Space Normal
float3 n = normalDepth.xyz;
// View Space Position Z
float pz = normalDepth.w;
// View Space Position
float3 p = (pz / pin.ToFarPlane.z) * pin.ToFarPlane;
// Random Vector를 통한 임의의 Normal Map 설정..
float3 randVec = 2.0f * gRandomVecMap.SampleLevel(gSamWrapLinerPoint, 4.0f * pin.Tex, 0.0f).rgb - 1.0f;
float occlusionSum = 0.0f;
[unroll]
for (int i = 0; i < 14; ++i)
{
// Reflect(반사)를 이용해 랜덤성을 증가..
float3 offset = reflect(gOffsetVectors[i].xyz, randVec);
// Offset Vector 와 Noraml의 내적을 구해서 부호를 구한다..
float flip = sign(dot(offset, n));
// 현재 위치에서 부터 차폐를 검사할 Vector를 구한다..
// flip을 곱하여 반구 방향으로만 계산..
float3 q = p + flip * gOcclusionRadius * offset;
// 위에서 구한 Vector에 Projection과 Texture Space 행렬을 곱하여 좌표 구한다..
float4 projQ = mul(gViewToTexSpace, float4(q, 1.0f));
projQ /= projQ.w;
// 위에서 구한 좌표에 해당하는 깊이값을 구하고 깊이값에 매칭되는 View Space 좌표를 구한다..
float rz = gDepthMap.SampleLevel(gSamBorderLinearPoint, projQ.xy, 0.0f).w;
float3 r = (rz / q.z) * q;
float distZ = p.z - r.z;
float dp = max(dot(n, normalize(r - p)), 0.0f);
float occlusion = dp * OcclusionFunction(distZ);
occlusionSum += occlusion;
}
// 차폐를 계산한 만큼 정규화..
occlusionSum /= 14;
float access = 1.0f - occlusionSum;
// 차폐된 최종 결과물 극대화 시키기 위해 변환..
return saturate(pow(access, 4.0f));
}
위와같이 SSAO Map을 뽑으면 노이즈 현상이 심하기 때문에 Blur 처리가 필요하다.
변경사항
1. Normal Map기준 Normal View 변환 놓친 부분 수정.
2. 최종 출력에 생기는 노이즈가 Blur 과정에서 문제가 있어 수치 변경.
'DirectX 11' 카테고리의 다른 글
[DirectX 11] Skinning Mesh (0) | 2021.12.18 |
---|---|
[DirectX 11] Normal Mapping (0) | 2021.12.18 |
[DirectX 11] Gamma Correction (0) | 2021.12.18 |
[DirectX 11] Deferred Rendering GBuffer (0) | 2021.12.14 |
[DirectX 11] Shadow Map (0) | 2021.12.14 |