앞서 작성한 그림자 글대로 그림자를 구현하면 가장자리가 울퉁불퉁해 보인다.
이것을 해결하기 위해 함수를 조금 수정해보자.
/*
// 3. 쉐도우맵에서 값 가져오기
float depth = shadowMap.Sample(shadowPointSampler, lightTexcoord).r;
// 4. 가려져 있다면 그림자로 표시
if (depth + 0.001 < lightScreen.z)
shadowFactor = 0.0;
*/
shadowMap.SampleCmpLevelZero(shadowCompareSampler, lightTexcoord.xy, lightScreen.z - 0.001).r;
3번과 4번 과정을 SampleCmpLevelZero라는 함수로 합칠 수 있다. shadowPointSampler 대신 shadowCompareSampler을 쓰고 인자로 그림자로 가려지는 기준이 되는 값을 넣어준다. (lightScreen.z - 0.001) 그리고 shadowFactor을 기존처럼 0이나 1 둘 중 하나로 정하는 것이 아니라 주변 픽셀 4개의 값에 따라 blend를 하기 때문에 부드럽게 보인다.
shadowCompareSampler은 SamplerState가 아닌 SamplerComparisonState이고 desc에서 Filter 설정할때도
FILTER_COMPARISON_MIN_MAG...로 설정한다. ComparisonFunc 도 LESS_EQUAL로 설정해줘야 한다.
uint width, height, numMips;
shadowMap.GetDimensions(0, width, height, numMips);
float dx = 5.0 / (float) width;
float percentLit = 0.0;
const float2 offsets[9] =
{
float2(-1, -1), float2(0, -1), float2(1, -1),
float2(-1, 0), float2(0, 0), float2(1, 0),
float2(-1, +1), float2(0, +1), float2(1, +1)
};
[unroll]
for(int i=0;i<9;i++)
{
percentLit += shadowMap.SampleCmpLevelZero(shadowCompareSampler,
lightTexcoord.xy, + offsets[i] * dx, lightScreen.z - 0.001).r;
}
shadowFactor = percentLit / 9.0;
주위 9픽셀을 돌면서 9번 샘플링하면 더 결과가 부드러워진다. 이것을 Percentage Closer Filtering이라고 한다.
index를 random으로 하거나 샘플을 더 늘리면 더 자연스러운 효과를 만들어낼 수 있다.
'그래픽스' 카테고리의 다른 글
| [그래픽스] Compute Shader 개념 및 구조 (0) | 2023.07.24 |
|---|---|
| [그래픽스] 부드러운 그림자 - PCSS (0) | 2023.07.23 |
| [그래픽스] 그림자 (0) | 2023.07.23 |
| [그래픽스] Depth Map (0) | 2023.07.23 |
| [그래픽스] 렌더링 엔진 구조 변경 (0) | 2023.07.23 |