Shadow Map이란?
그림자를 만들어내기 위해서 Shadow Map을 활용한다
모델링 과정에서 생성하는 노말맵과는 달리
쉐도우맵은 리얼타임으로 생성 및 적용한다
Shadow Map 방법 - Two pass algorithm
Shadow Map을 실시간 생성 및 적용을 하기 위해서는
두 번의 렌더링 과정을 거치기에 two pass algorithm이라고 부른다
여기서 algorithm은 렌더링 과정을 의미한다
1. Shadow Map 생성을 위한 렌더링
2. 생성된 Shadow Map을 Scene에 렌더링
1) Shadow Map 생성을 위한 렌더링
해당 렌더링은 real 렌더링이 아니다
단순히 데이터만 만들어내고 유저에게 보이기 위한 렌더링은 아니라는 것이다
렌더링을 하는 방법은
가상의 카메라를 light source의 관점으로 조절해서
깊이 정보(z값)를 담고 있는 Shadow Map을 생성한다
여기서 z값은 아래 그림처럼 projection transform, viewport transform을 거친 값으로 저장된다
참고로,
depth 맵은 카메라 관점에서의 깊이를 저장한 맵
shadow 맵은 광원 관점에서의 깊이를 저장한 맵으로
depth 맵이 더 큰 개념이라고 보면 된다
2) 생성된 Shadow Map을 Scene에 렌더링
해당 렌더링은 유저에게 보이는 real 렌더링이다
카메라에 특정 좌표가 그림자인지 아닌지를 판단하기 위해서
light source로부터 해당 좌표까지의 거리 d와 depth 값을 비교해서
d > z true면 그림자, false면 그림자 X
즉, 쉐도우맵은 광원을 기준으로 빛에 비쳐지는 부분만의 거리를 추출한 맵이고
실제 거리가 쉐도우맵의 depth 값과 같거나 작다면, 비쳐지는 부분이니 그림자 X
실제 거리가 쉐도우맵의 depth 값보다 큰 경우라면, 비쳐지지 않는 부분으로 뒤에 있으니 그림자 O
Shadow Map 문제 - Surface Acne 원인
쉐도우맵을 만들 때의 위치와 해상도와
실제로 최종적으로 렌더링 되는 카메라 뷰의 위치와 해상도가 다르기 때문에
카메라의 특정 좌표의 정확한 z값은 쉐도우맵에 없을 가능성이 높다
아래 사진을 통해 정확한 z값이 없는 경우에 발생하는 문제를 보자
q1과 q2 각각의 z값은 쉐도우맵에 없다
그래서 nearest point sampling을 통해 가장 가까운 좌표의 z값을 가져온다
그러다 보면
q1처럼 d값이 z값보다 항상 클 수밖에 없고
그림자로 판단해 버리면서 Surface Acne 문제가 발생한다
Shadow Map 문제 - Surface Acne 해결
bias 값을 설정해 d값을 줄여주면 된다
다만,
bias 값을 너무 작게 설정하면 surface acne 발생하고
bias 값을 너무 크게 설정하면 그림자가 작아진다
그래서 적절히 bias 값을 설정해줘야 한다
또한,
고정된 bias 값이 아닌 유동적인 bias 값을 사용하면
조금 더 안정적이다
그런데 여기에서 사용하는 bias를 위한 기준 값도 결국 상황에 맞게 설정은 해줘야 한다
float shadow = current > closest ? 1.0 : 0.0; //텍스처에 저장된 값이 더 작으면(그림자 영역이면) 1 반환
// 그냥 고정값만 사용하는 경우
//float bias = 0.05;
//간단히 고정된 bias 대신 계산을 통해 적절한 bias 선정하는 경우
vec3 normal = normalize(v_Normal);
vec3 lightDir = normalize(light.direction);
float bias = max(0.05*(1.0 - dot(normal, lightDir)),0.055);
float shadow = current - bias > closest ? 1.0 : 0.0; //bias 적용
if (projCoords.z > 1.0) //far plane 뒤쪽으로는 shadow 적용 안함
{
shadow = 0.0;
}
위의 코드를 보면,
1.0 - dot(normal, lightDir) 값은 0에서 1 사이의 값이 나온다
dot(normal, lightDir)이 1이면, 같은 방향을 바라보는 것이고
dot(normal, lightDir)이 0이면, 서로 90도인 상태인 것이다
따라서,
같은 방향을 바라볼수록(평행) 작은 bias를 사용하고
90도에 가까워질수록 큰 bias를 사용해서 조금은 자연스럽게 구현할 수 있다
Shadow Map 문제 - 해상도가 떨어지는 문제 & 해결
쉐도우맵의 해상도가 낮은 경우에
여러 픽셀의 그림자 여부를 판단할 때 하나의 texel값만 참조해서
해상도가 떨어지는 문제가 발생한다
이를 해결하기 위해
쉐도우맵 해상도를 무작정 높이는 것은 성능적으로 좋지 않다
따라서, Shadow Map Filtering을 사용한다
위의 그림처럼
그림자의 여부를 0, 1로만 판단하는 것이 아닌
중간 값들을 만들어주는데
이를 PCF(percentage closer filtering)라고 한다
PCF를 이용하면, 해상도 문제를 해결하고 조금 더 자연스럽게 그림자를 만들 수 있다
'게임 그래픽스 > [전북대] OpenGL' 카테고리의 다른 글
[OpenGL Note] Normal Map (0) | 2024.11.25 |
---|---|
[OpenGL Note] Quaternion (0) | 2024.11.24 |
[OpenGL Note] Output Merger - Alpha Blending (0) | 2024.04.20 |
[OpenGL Note] Output Merger - Z buffering (0) | 2024.04.20 |
[OpenGL Note] Lighting - Ambient, Emmisive (0) | 2024.04.19 |