Vertex Shader
Input Assembler에서 받은 정점 정보들로 도형은 생성했지만
로컬 좌표게에 있기 때문에 해당 데이터를 화면에 그대로 출력해 버리면
여러 가지의 도형이 전부 같은 위치에 생성이 된다
공간 좌표계(World)로 변환해야 한다
Local Space > World Space > View Space(카메라 기준의 공간) > Projection(Clip Space) > Screen Space
월드변환
Local Space라고도 불리는 오브젝트 공간은 3차원 세상에서 표현될 각각의
개인 공간에 정의된 영역이다
그런데 이러한 오브젝트들을 하나가 아닌 여러 개를 한 화면에 모아놓은 공간을
World Space라고 한다
카메라변환
월드 변환이 완료되어 모든 물체가 한 공간(World Space)으로 모아지면
우리가 원하는 시점에서 물체를 관찰할 수 있어야 한다
이때 관찰자로서 가상의 카메라가 필요하고
카메라가 볼 수 있는 영역의 공간 혹은 뷰 공간이라고 한다
월드 공간의 모든 물체를 카메라 공간으로 변환하게 되면 효율적으로 렌더링 작업을 수행할 수 있다
카메라가 바라보는 세상에 대해 생각해 보면,
가상의 카메라는 컴퓨터 성능의 한계 때문에 실제 세상의 카메라와는 다르게
시야가 제한될 수 있다
Fox(시야각), Aspect(종횡비)에 의해 결정되는데
이러한 시야의 가시영역을 View Volume이라 부르고, 이렇게 생성된 뷰 볼륨은
n(near), f(far)에 의해 전달되어 View Frustrum(절두체)의 영역으로 다시 정의된다
View Frustrum
절두체 공간 밖에 있는 물체는 그리지 않는데, 우리가 살고 있는 3차원 세상은 모든 걸 보여준다
이렇게 밖에 없는 이유는 계산상 효율성을 위해 어쩔 수 없이 도입된 개념이다
만약 물체가 절두체의 경계에 걸치게 되면 바깥쪽 부분은 자르고 버리게 되는데
이를 클리핑이라고 하고 카메라 변환에서 일어나지 않고 추후 클립공간에서 수행되는데 이는 뒤에서 설명
Projection(투영변환)
Projection에서 카메라 변환에서 월드의 모든 물체를 카메라 공간으로 이동시켰고
이제 카메라 시점에서 세상을 바라보는 과정은 끝났지만
우리가 카메라를 통해 바라보는 가상의 공간을 현실세계처럼 3차원이지만 우리가 최종적으로 바라봐야 할 공간은 2차원이 되어야 한다
3차원 공간을 2차원 공간으로 표현할 수 있는 방법은
원근감에 따라 멀리 있는 물체는 작게, 멀리 있는 물체일수록 소실점에 가깝게
3차원 세상은 2차원 평면에 표현하는 방법은 화가들에 의해 개발되어서 우리 또한 같은 방법을 사용한다
투영변환은 이러한 원근법을 구현하기 위해 카메라 공간에서 정의된 절두체를 축에 나란한 직육면체 볼륨으로 변경하여
카메라 공간의 모든 물체를 3차원 클립공간으로 변환하는 것을 의미한다
Camera Space > Clipping Space의 과정이다
투영변환이라는 이름과는 다르게 3차원 카메라 공간의 물체를 2차원 평면으로 투영하는 것이 아니라
또 다른 3차원 물체로 변형됨에 주목해야 한다
이러한 투영변환을 거친 물체들을 관찰해 보면 절두체 뒤 쪽에 있던 영역의 폴리곤은 상대적으로 작아지는 것을 볼 수 있는데
우리가 원했던 원근법을 적용된 것이라 볼 수 있다
다시 정리하면 3차원 공간 내에서 원근법을 실행하고 Clipping Space로 바꾸기만 한 것이다
추가적으로 하나 더 생각하면 원근법을 3차원 공간에서 실현하기 위해 직육면체 볼륨으로 물체들을 변환시켰는데
여기서 얻는 이점이 있다 좀 더 간단한 공식으로 쉽게 클리핑 작업을 쉽게 할 수 있다 (다육면체 > 직육면체)
Hult Shader Stage ~ Domain Shader Stage (Tesselation)
Tesselation이 일어나는 단계이다
로우 폴리곤 하이 폴리곤이 있는데
회사에서는 둘 다 만들어놓고 가까이 있는 물체라면 하이, 멀리 있다면 로우를 쓴다
테셀레이션 단계는 생략이 가능하며
주어진 모델의 정점을 더 잘게 쪼개서 디테일하게 표현할 수 있고
또는 정점의 일부들을 합쳐서 저해상도로 표현하여 최적화 성능을 올릴 수 있고
이러한 기술을 LOD(Level of Detail)라고 하며
Tesselation을 사용하면 하나의 모델에 여러 해상도의 모델 데이터를 가지고 있을 필요가 없다
Geometry 단계
기본 도형에서 정점을 추가하거나 삭제하여 모델을 변경할 수 있는 셰이더이다
Geometry Shader로 정점 정보를 조금 추가하여 표현할 수 있는 모델이라면
그만큼의 정점정보를 빼고 저장할 수 있으니 디스크 용량과 그래픽 메모리에 도움 될 수 있으며,
게임오브젝트를 여러 개가 만드는 것이니라 정점정보를 GPU안에서 복사하는 것이다
동일한 이펙트나 동일한 파티클, 캐릭터 잔상 같은 경우
이를 여러 개 반복 생성할 때,
실제로 게임 오브젝트를 여러 개 생성하는 것이 아닌
병렬 연산에 특성화를 지닌 GPU에서 복사해서 쉐이더로 처리하는 단계
Rasterizer 단계
정점 처리 단계를 지난 정점은 이제 랜더링 파이프라인의 다음 단계인 레스터라이즈 단계로 들어간다
정점들은 삼각형으로 묶어지는데 이 시점부터는 하나의 도형이 독자적으로 처리가 된다
화면에 그려질 2차원 삼각형의 세 정점이 결정되면 다음과 같은 일이 일어난다
1. 이 삼각형이 포함하는 모든 픽셀마다 픽셀셰이더가 실행된다
2. 삼각형의 세 정점에 할당되었던 여러 데이터(pos, uv, normal)들은 보간(interpolation)이 되어 삼각형 내부의
각각 픽셀셰이더로 넘어온다
Direct3D에서는 이러한 과정들을 통틀어서 레스터라이제이션이라고 부른다
이 레스터라이저는 고정 파이프라인 단계로 프로그래밍이 불가능하여 하드웨어 자체 알고리즘을 통해 동작하며
- 클리핑(Clipping)
- 원근 나눗셈(perpective division)
- 뒷면 제거(backface culling)
- 뷰보트 변환(viewport transform)
- 스캔 변환(ndc scan transform)
과정을 거친다
- 클리핑(Clipping)
투영변환 이후 클립공간 볼륨 바깥에 놓인 폴리곤들을 잘라내는 작업을 의미한다
이전부터 언급되었던 이 작업이 바로 레스터라이저 단계에서 일어난다
- 원근 나눗셈(perpective division)과 NDC 공간
현재 단계에서 투영변환을 통해 원근법이 적용된 3차원 물체들은 직육면체 클리핑 공간에서 정의되어 있다
우리가 최종적으로 필요로 하는 3차원 공간을 2차원 공간으로 수학적으로 변환하기 위해서
모든 성분(x, y, z)을 w좌표로 나눠주면 된다
(x, y, z, w)에서 w성분에 z값이 저장돼있기 때문에
나눈 값들은 z는 1이되고 x y 만 남게 하는 작업이며
원근 나눗셈이 적용된 이후에는 x, y, z, w > x, y, z의 좌표계로 변환되는데
이를 NDC(Normalize Device Cordinate) 공간이라고 부른다
여기서 정규화라는 이름이 붙는 이 좌표의 x y 범위는 -1~1 z의 범위는(0~1)이기 때문이다
- 뒷면 제거
다음으로 레스터라이저에서 하는 기능으로 뒷면 제거가 있다
카메라가 바라보고 있는 방향에 물체에 가려진 면적은 연산이 불필요하므로
외적(Cross product) 삼각형의 바라보고 있는 면의 방향을 구해
뒷면의 경우에 연산을 제외시킨다
- 뷰포트 변환
컴퓨터 화면상의 윈도우 스크린 공간에서 2차원 이미지가 그려질 뷰포트가 정의되는데
NDC 공간의 물체들을 스크린 공간으로 이전시키는 변환을 뷰포트 변환이라고 한다
- 스캔 변환
이전의 변환들은 자세한 사항을 몰라도 프로그래밍에 큰 문제가 없지만
스캔변환은 렌더링 프로그램에서 직접적인 영향을 미치기 때문에 매우 중요하다
삼각형 하나가 내부에 차지하는 모든 픽셀(fragment)들을 생성하는 작업이다
이때 정점데이터에 들어온 데이터들은 (선형) 보간 되어서 픽셀셰이더로 넘어간다
- Pixel Shader
레스터화 된 도형에 텍스쳐 매핑, 법선 매핑, 노말 매핑 기법들로 텍스쳐를 입혀
색을 표현한다
원한다면 특정 색깔로 표현이 가능하고 조명처리나 이미지 처리를 할 때 유용하게 사용된다
- Output Merger
겹치는 오브젝트 간 앞 뒤 (깊이)의 정보를 저장하는 깊이 버퍼, 깊이 스텐실 테스트와
블렌딩(물체 간의 색 혼합)이 일어나서
최종적인 렌더타겟(frame buffer) 물체를 그려주는 과정이다
'그래픽스 > [기초] DirectX' 카테고리의 다른 글
[DirectX Note] 랜더링 파이프라인 (1) (1) | 2023.05.17 |
---|---|
[DirectX Note] 애플리케이션 생성과 정적 라이브러리 추가 (0) | 2023.05.17 |
[DirectX Note] 그래픽스 공부 이유 (0) | 2023.05.17 |