프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by ozlael

지난 번 글에서 이어지는 글입니다.

이전 글 : PC에서 3D 입체 영상 게임 개발하기 #3


들어가며

지난 시간에는 미들웨어의 지원을 받아서 따로 알아서 입체 영상이 생성 되는 것을 알아보았습니다. 이번 시간부터는 조금 귀챦은 내용을 다뤄보도록 하겠습니다 :-)

 

Virtual Screen과 UI

 전통적인 3D공간에서 모니터 스크린의 위치는 근(near)평면과 일치합니다. 전통적인 프러스텀공간을 생각시에는 당연한 이야기입니다만은 입체 영상에서는 추가적인 새로운 개념이 나타납니다. 근(near)평면과 원(far)평면 사이에 버쳘스크린(virtual screen)이존재하는 것입니다. 이 버쳘 스크린은 앞서 2화에서 말씀드렸던 컨버젼스 포인트(convergence point, 수렴 혹은 폭주)에 위치합니다. 즉 좌우 주시선이 교차하는 위치이고, 좌우 프러스텀이 겹치는 공간이고, 패럴렉스가 0인 위치인 것입니다. 사용자는 이를 모니터의 깊이로 받아들이게 되고 때문에 일반적으로 UI 및 HUD등은 이 깊이에 그립니다

이 virtual screen에 어떻게 UI가 입체화되지 않고 그려지는 것일까요? 앞서서 말씀드렸다시피 좌우 두개로 분리되어있는 랜더타겟에 드로우 시 입체화 되서 그려집니다. 이 UI를 그릴때도 역시 마찬가지로 두번 그려지긴합니다. 다만 패럴랙스가 일어나지 않는 같은 좌표에 그려지기 때문에 convergence point가 되어 virtual screen에 그려지는 것이지요. 이는 뷰트랜스폼을 다 처리 한 후 그릴시 이러한 현상이 일어납니다. 일반적으로 UI를 그릴 시 FVF를 D3DFVF_XYZRHW 로 설정하고 W를 1로 설정하여 그리지요. 이러한 경우는 트랜스폼음 모두 거친 것으로 처리되어 그대로 찍게 되는것입니다. 그렇기 때문에 패럴렉스가 일어나지 않고 좌우 같은 위치에 그려집니다.

하지만 여기서부터 신경 써 줘야 할 것들이 생깁니다. 모든 UI가 virtual screen 위치에 그려져야 하는 것은 아닙니다. 오히려 convergence point에 위치해 있으면 안되는 UI가 존재합니다. 3D 공간상의 포인터 역할을 하는 것 들, 즉 크로스헤어나 마우스커서나 케릭터명 등은 가리키는 오브젝트에 맞는 적절한 깊이에 그려져야 합니다. 그렇지 않고 스크린 깊이에만 그려진다면 뇌가 매우 힘들어하게되지요. 특히 FPS의 크로스헤어가 virtual screen 깊이에만 그려지는 경우는 치명적입니다. 그런 경우는 크로스헤어에 집중하면 케릭터의 상이 깨지고 케릭터에 집중하면 크로스헤어의 상이 깨지는 혼란을 가져다주게 됩니다. 눈과 뇌는 이러한 경우에 매우 취약해서 금새 안정피로 증상을 보일 수 있으므로 매우 조심해야 합니다. 그렇지 않으려면 크로스 헤어 역시 가리키는 케릭터의 깊이에 맞게 그려서 패럴렉스가 존재해야 합니다. 

하지만 그럴만한 여력이 되지 않는다면 크로스헤어를 끄는 옵션을 두는 것도 방법중 하나입니다. 다행히 세 미들웨어 모두 크로스헤어 기능을 제공하고 있기 때문에 유저가 게임에서 그려주는 크로스헤어를 끄고 미들웨어가 제공해주는 크로스헤어를 켜주면 미들웨어가 알아서 적절한 깊이에  크로스헤어를 그려줍니다.



특수 효과

하지만 문제는 UI뿐만이 아닙니다. 특수 랜더링 피쳐들이 사용 될 수록 문제점들이 보이기 시작 할 것입니다. 특히 픽셀 셰이더 레벨에서 스크린 스페이스로 투영하여 텍스쳐를 사용하여야 하는 효과들이 주로 그러합니다. 소프트 파티클이라던가 왜곡 효과 등 랜더 타켓에 그려진 씬의 장면을 스크린 스페이스에서 재차 샘플링 하여야 하는 것 들이지요. 보통 물에는 굴절 왜곡 효과를 넣는데 기존의 효과들을 미들웨어를 통해 드려보면 다음과 같이 어긋나 보일 것입니다.

왜 이러한 현상이 일어나는 것일까요? 일반적으로 이런 랜더링 피쳐들은 버텍스 셰이더에서 윌드 공간을 스크린 좌표로 변환하는 행렬을 반영하여 그 좌표를 픽셀셰이더로 넘겨주게 됩니다. 픽셀 셰이더에서는 그렇게 념겨 받은 좌표대로 장면 및 깊이 텍스쳐를 샘플링하여 특수 효과를 처리하게 되지요. 다음 코드는 DX9 shadowmap 샘플에서 발췌한 것인데 보통 저런 식으로 진행이 되겠지요.

VS :

VPosScreen = mul( vPos, g_mWorldToScreen );

PS :

float2 ScreenTexC = vPosScreen.xy / vPosScreen.w;

float4 d = tex2D( samShdow, ShadowTexC ) + ...

어느 부분이 문제인지 보이시나요? (물론 굵게 칠했으니 보이시겠지요 ㅋ) 버텍스 셰이더에서 곱해주는 g_mWorldToScreen 매트릭스는 mono eye 기준 값입니다. 드로우 콜을 날려주는 C++ 코드 상에서는 좌안 우안 신경쓰지 않고 모노 카메라 기준으로만 식들을 처리하기 때문에 셰이더 상수로 넘겨주는 매트릭스 값도 당연히 모노 카메라 기준 값이지요. 하지만 픽셀 셰이더ㅇ에 진입 시는 이미 스테레오화 되서 그려지게 되므로 모노와 스테레오간의 불일치가 일어나게 되는 것입니다.

하지만 셰이더 모델 3.0에서는 픽셀 셰이더에서 VPOS 시멘틱을 사용하면 간단하게 해결이 가능합니다. VPOS 를 사용하면 버텍스에서 픽셀로 좌표 관련 값을 넘겨 받을 필요가 없어지고 자연스레 모노 카메라 기준 매트릭스 값을 사용할 일이 사라져서 모노와 스테레오의 불일치 걱정이 가라지게 되지요. 좌안용 우안용 픽셀 세이더에서는 VPOS를 사용하여 각각에 맞는 샘플링 포인트를 얻을 수 있을 것입니다.



마치며

하지만 전통적인 랜더링 방식이 아닌 디퍼드 랜더링 방식에서는 일이 커지게 됩니다. 다음 시간에는 지옥의 맛을 다루기 시작하겠습니다. 감사합니다. 꾸벅


 


댓글을 달아 주세요

  1. peri 2012.07.11 17:41  댓글주소  수정/삭제  댓글쓰기

    재미있고 흥미로운 내용입니다. 시각 인지적인 부분의 고려가 많이 필요하고 미들웨어라던지, 생소한 개발환경(고려되어야 하는 부분과 기술) 때문에 개발이나 접근 자체가 쉽지 않아보이는데, 강연글을 쓰실 정도라니 멋집니닷! 이런 새로운 인지적 페러다임의 확장으로 점점 더 꿈같은 체험이 가능하게 되길 바랍니다!