18. 그림자 기법 원형그림자
3D게임에 그림자가 등장하면서 많이 사용된 방식.
현재까지도 사라지지 않고 사용되어지고 있습니다.
19. 그림자 기법 원형그림자
그 이유는...
부하가 적고 하드웨어사양와도 크게 상관이
없기 때문에
빛이 있는 곳에 어둠을 표시하기 위한 최소한의
장치로서 활약하고 있습니다.
20. 그림자 기법 원형그림자
하지만 치명적인 약점이 존재하는 데...
빛에 영향을 받는 게 아니라 그림자가 될 텍스처를
사용해 찍기 때문에 비현실적이고, 모양이 언제나
같으며, 평면이 아닌 지형에서도 사용은 할 수 있으
나 여러가지면에서 예쁘지 못합니다!
21. 그림자 기법 원형그림자
다음과 같은 원형그림자 텍스처를 만들어 둡니다.
그림자의 위치를 지정해주기 위해
높이가 Y좌표일 때 [X,Z]좌표를 사용하여
위치를 지정하고,
해당 모델보다 약간 아래로 그림자를 찍으
면 됩니다.
너무 간단하기 때문에 설명은 여기까지.
22. 그림자 기법 평면투영그림자
평면만을 위해서 태어난 그림자 기법.
말 그대로 평면에서만 사용할 수 있는 그림자 방식입니다.
23. 그림자 기법 평면투영그림자
앞에 원형그림자에 비해서 텍스처를 이용하지 않고
모델을 한번 더 그리기 때문에,
원본 모델을 그림자로 사용하고자 할 경우
한번 더 그려야 됩니다.( 물론 텍스처를 입히지 않은 상태 )
그렇기 때문에 폴리곤이 많은 모델일 경우,
그림자용 모델을 따로 제작해야 되는 번거로움이 존재합니다.
24. 그림자 기법 평면투영그림자
물론 원형그림자에 비해서 그림자가 모델 모양에 가깝게 나오기 때
문에 평면에서만 사용한다는 가정하에 현실성을 높여줄 수 있습니다.
지형이 평면에서밖에 안 사용되어진다면
평면투영 그림자기법은 다른 어떤 그림자기법보다
가장 먼저 꺼내서 사용하시면 되겠습니다.
32. 그림자 기법 투영 텍스처 그림자
카메라의 위치를 광원이 있는 위치 카메라
로 옮깁니다. 광원
왜냐하면 그림자는 광원의 영향을
받아서 만들어지므로,
광원의 위치를 가지고 텍스처에 해
당 장면을 그려주어야 하기 때문입
니다.
33. 그림자 기법 투영 텍스처 그림자
그러면 다음과 같은 텍스처를 얻으 광원
실 수 있습니다.
그리고 옮겼던 카메라 위치는 다시
원래의 자리로 돌립니다.
카메라
34. 그림자 기법 투영 텍스처 그림자
광원에서의 투영공간과 텍스처공간은 중심위치가 다르므로
U = +0.5X + 0.5
V = -0.5Y + 0.5
위의 식을 사용하여 투영공간의 좌표를 텍스처공간의 좌표로
변환해줄 수 있습니다.
35. 그림자 기법 투영 텍스처 그림자
이를 행렬로 표현하면 다음과 같습니다.
근데 왜 갑자기 투영 공간의 좌표를
텍스처 공간으로 옮기는 작업을 하고 있나요?
36. 그림자 기법 투영 텍스처 그림자
우선 우리가 만든 텍스처는 광원
위치에서 찍은 투영공간상에 찍은
것입니다.
그리고
흰색과 검은색으로 단 2개의 색으
로 이루어져 있다는 것을 확인할
수 있습니다.
37. 그림자 기법 투영 텍스처 그림자
즉, 카메라 위치에서 모델을 그리면, 정점은
투영공간으로 변환됩니다.
그림자를 그릴 때 위의 텍스처로 만든 투영 텍스처를 그림자로
사용하기 위해서 찍은 것이므로,
투영공간 => 텍스처공간 변환
이후에 해당 위치의 텍셀을 참조하여 그림자인지 아닌지를 판
단하게 됩니다.
38. 그림자 기법 투영 텍스처 그림자
FinalColor = DestColor * SrcTexel
흰색은 1.0f이므로 DestColor가 그대로 나오겠지만,
검은색은 0.0f이므로 0.0f 즉 검은색으로 나오게 되어 그림자가
생성되어지게 될 것입니다.
39. 그림자 기법 투영 텍스처 그림자
즉 방금 살펴본 과정을 다시 여기
에서 설명하면
DestColor의 대상이 되는 곳이 바
로 이 지면일 것입니다.
1. 광원위치에서 그림자 텍스처 생
성
2. 그림자 텍스처를 지면과 혼합시
켜서 그림자 출력.
40. 그림자 기법 투영 텍스처 그림자
주의사항으로는 텍스처 어드레싱 모드를
DirectX기준으로
D3DTADDRESS_CLAMP
으로 해주어 [0,1]범위 이외의 텍셀은 투명하도록 해줍니다.
안 그러면 위와 같이 나오지 말아야 할 그림자가 나오는 현상이
발생하게 됩니다.
41. 그림자 기법 투영 텍스처 그림자
보셨듯이 텍스처에 그림자를 남기는 방식이기 때문에
텍스처에 최대한 많은 그림자를 생성하면 한번의
패스로 많은 그림자들을 한번에 그릴 수 있습니다.
단, 큰 해상도의 텍스처가 필요할 것이기 때문에
그만큼 메모리를 많이 소비할 수밖에 없습니다.
또 작게 만들면 그만큼 그림자 품질도 떨어지겠죠?
42. 그림자 기법 투영 텍스처 그림자
그 외에도 그림자를 출력할 대상이 될 지면 오브젝트를 정하는 것과
광원과 그림자 사이에 장애물 오브젝트가 존재할 경우 이상한 곳에
그림자가 나올 수 있다는 것을 주의해야 합니다.
43. 그림자 기법 투영 텍스처 그림자
그냥 문제될만한 이런 제약사항이 없을 때
이 기법을 이용합시다!
44. 그림자 기법 스텐실 그림자
스텐실 그림자는 2004년 존카막의 둠3에 의해
세상에 공개되어졌습니다...
45. 그림자 기법 스텐실 그림자
스텐실 그림자의 최대 장점은 바로 앞에 기법들이 해내지 못한
셀프그림자를 지원하다는 것입니다.
46. 그림자 기법 스텐실 그림자
스텐실 그림자는 다음과 같이 그림자 볼륨이라는 것을 생성하게 됩니다.
이게 무엇이냐면 광원의 방향으로부터 빛을 받은 정점들은 뒤쪽으로 잡
아서 늘여 뜨리게 됩니다.
47. 그림자 기법 스텐실 그림자
실제 화면을 보면 다음과 같은 그림자 볼륨을 생성하게 됩니다.
화면에 보이는 건 단순한 모델이지만 그림자 볼륨까지 봤을 때
정점수가 상당히 많아 보입니다.
48. 그림자 기법 스텐실 그림자
그렇습니다...
렌더링 부하가 장난아니게 큽니다.
픽셀셰이더에는 부하가 없으나 정점셰이더에는
이들이 모두 들어가기 때문이니까요.
49. 그림자 기법 스텐실 그림자
어쨌든 지금은 스텐실 그림자를
다루고 있으니 계속 진행하겠습
니다.
50. 그림자 기법 스텐실 그림자
원리는 간단합니다.
우선 그림자 볼륨의 앞면을
스텐실 버퍼에 +1이라고 기록을
하도록 합니다.
만약 광원이 여러 개라면 중첩
으로 인해 +1이상의 값이 나올
수도 있겠죠.
51. 그림자 기법 스텐실 그림자
이번에는 그림자 볼륨의 뒷면입
니다.
앞면과는 반대로 -1을 기록하도
록 합니다.
이제는 어느 정도 감이 올 수 있
겠죠?
52. 그림자 기법 스텐실 그림자
그렇습니다.
앞면과 뒷면은 사실 그림자가
될 수 없는 운명이었습니다.
이들은 합쳐져 최종적으로 0이
되었기에 볼륨은 사실상 최종적
인 화면에서 제외됩니다.
하지만 실제로 그림자가 출력되
어져야 할 부분은 뒷면이 존재
하지 않기에 +1만 남아
그림자가 되었습니다.
57. 그림자 기법 우선순위 버퍼 그림자
우선순위 버퍼 그림자 역시 앞서 보았던 그림자 기법들처럼,
광원의 위치에서 오브젝트들을 렌더링합니다.
다만 그림자가 될 오브젝트뿐만 아니라 화면안에 그려져야 할
모든 대상의 오브젝트들을 그린다는 차이점이 있습니다.
58. 그림자 기법 우선순위 버퍼 그림자
우선순위 버퍼그림자는 각각의 오브젝트들을 자기 입맛대로
색깔을 지정해주어 텍스처에 기록할 수 있습니다.
즉 이 입혀진 색깔은 오브젝트의 성격임과 동시에 서로 다를 경우 그림자
가 나타날 수 있습니다.
59. 그림자 기법 우선순위 버퍼 그림자
위에서 보았던 오브젝트들을 가지고
텍스처에 기록해봅시다.
지면은 검은색, 그리고 구는 주황색으로 기록하였습니다.
60. 그림자 기법 우선순위 버퍼 그림자
텍스처의 내용을 그대로 갖다 붙여서 생각해본다면 다음과 같은 모양
이 될 것입니다.
61. 그림자 기법 우선순위 버퍼 그림자
128
32
내용을 쉽게 이해하기 위해 텍스처에 기록할 때,
지면은 132, 구는 32로 기록했다고 합시다.
현재 ID가 입력된 그림자 텍스처인 ID맵은 완성된 상태이므로
실제로 오브젝트에 그림자를 입히는 작업을 하도록 합시다.
62. 그림자 기법 우선순위 버퍼 그림자
32
구를 먼저 그립니다.
보시다시피 구만 덩그러니 그려질 것입니다.
왜냐하면 ID맵을 보았듯이 구가 더 뷰에 가까웠기 때문에,
ID맵을 참조하여도 ID가 같으므로 그림자를 만들 건덕지가 없습니다.
63. 그림자 기법 우선순위 버퍼 그림자
그림자 텍스처와 128
겹쳐진 부분
32
128의 ID를 가진 지면을 그릴 경우 네모부분이 바로 그림자가 되는
부분인데요. 128인 부분을 그리면서 겹쳐진 부분을 만나게 됩니다.
FinalColor = 지면IDofPixel != ID맵ofPixel ? 0 : DestColor;
식을 보시다시피 ID맵으로부터 참조해서 다를 경우에
그림자가 생기도록 합니다.
64. 그림자 기법 우선순위 버퍼 그림자
그림자 텍스처와 128
겹쳐진 부분
32
128의 ID를 가진 지면을 그릴 경우 네모부분이 바로 그림자가 되는
부분인데요. 128인 부분을 그리면서 겹쳐진 부분을 만나게 됩니다.
FinalColor = 지면IDofPixel != ID맵ofPixel ? 0 : DestColor;
식을 보시다시피 ID맵으로부터 참조해서 다를 경우에
그림자가 생기도록 합니다.
65. 그림자 기법 우선순위 버퍼 그림자
투영 텍스처 그림자처럼 셀프그림자를 지원하지 않습니다.
전후 관계를 고려하기 때문에 많은 오브젝트가 있어도 그림자가 정확
하게 출력된다는 장점이 있습니다.
물론 ID가 서로 같을 경우에는 무슨일이 있어도 그림자가 생기지 않으니
이러한 점은 고려되어져야 합니다.
66. 그림자 기법 깊이버퍼 그림자
우선순위버퍼 그림자와의 차이점은 단지 ID로 사용하는 색을 그리는 게
아니라 아예 깊이 버퍼값을 사용한다는 것입니다.
샘플그림은 메탈기어솔리드4로서 지금 설명하는 기법을 사용했기에
한번 넣어봤습니다.
67. 그림자 기법 깊이버퍼 그림자
광원의 위치로부터 깊이 버퍼로 텍스처를 그리게 된다면,
가까이 있는 것은 검게, 멀리 있는 것은 하얗게 표시되는
흑백필름영화 느낌의 텍스처를 얻게 될 것입니다.
68. 그림자 기법 깊이버퍼 그림자
두번째 패스에서 오브젝트를 그립니다.
그려진 오브젝트의 깊이값은 깊이버퍼를 기록한 텍스처와 비교를
해야 하므로
정점좌표 * (월드행렬*광원위치의 뷰행렬*투영행렬)
를 곱해야만 같은 공간에 있게 되므로 올바른 비교가 될 것입니다.
69. 그림자 기법 깊이버퍼 그림자
FinalColor = ZofDepthMap < ZofDestBuffer ?
0 ? DestColor;
즉 깊이맵이 그려져야 할 곳의 깊이값보다 더 작다면 뷰에 더 가깝다는
것을 의미하고 배경을 덮어 씌우는 것이기 때문에,
그림자가 만들어 질 것입니다.
70. 그림자 기법 깊이버퍼 그림자
하지만 이 공식만 사용해서 구현했을 경우...
예상치 못한 결과가 나옵니다.