비타Cpp

렌더링 파이프 라인 - VS(Vertex Shader) Stage - World Space & Local Space 본문

DirectX12/메모

렌더링 파이프 라인 - VS(Vertex Shader) Stage - World Space & Local Space

멍C 2021. 8. 1. 16:18

IA(Input Assembler) 단계에서 Primitive를 조립한 후 해당 Vertex들은 VS(Vertex Shader)단계로 넘겨진다. VS단계를 한 개의 Vertex를 받아서 한 개의 Vertex를 출력하는 단계라고 생각하면 된다. 이러한 작업을 화면에 그려지는 모든 Vertex에 대하여 수행이 된다. 개념적으로 아래와 같은 일이 벌어지는 것이다.

for(UINT i = 0, i < numVerticesl i++)
{
	outputVertex[i] = VertexShader(inputVertex[i]);
}

VertexShader함수의 내용은 프로그래머가 구현하여 GPU에 제출한다(HLSL : High-Level Shader Language). 이러한 함수는 각 정점에 대해 GPU에서 실행되기 때문에 아주 빠르다.

 

변환(Transform), 조명(Lighting), 변위 매핑(Displacement Mapping) 등 수많은 특수 효과를 정점 셰이더에서 수행할 수 있다. 일단 변환을 위한 World SpaceLocal Space의 개념에 대해 알아본다.

 

World Space와 Local Space는 3D 아티스트들의 관점에서 보면 이해하기 쉽다. 게임 또는 영상의 한 장면에 나오는 오브젝트를 만드는 역할을 한다고 했을 때, 그 오브젝트를 상영할 장면에서 작업을 하는 것보다는 별도의 그 오브젝트를 만드는 작업대에서 해당 오브젝트를 완성한 뒤에 장면에서 크기와 위치, 방향 등을 조절하여 배치해 주는 것이 지형이나 다른 오브젝트를 고려하지 않아도 되어 작업하기가 수월하다.

그런 것처럼 물체 자체의 기하 구조를 바로 세계 공간(World Space; 전역 공간)에 구성하는 것이 아니라 각 물체의 중심의 국소 공간(Local Space; 지역 공간)에 대하여 따로 구성을 한 뒤에 각 물체를 세계 공간에서 원하는 위치에 이동(Translate)시키고, 크기를 조절(Scaling)하고, 회전(Rotate)시키는 것이다.  이를 위해서는 Local Space와 World Space 간의 관계를 정의해야 한다. 좀 더 구체적으로는, World Space 좌표계에 상대적인 Local Space 좌표계의 원점 위치와 축 방향들을 지정하고, 그에 해당하는 좌표 변경 변환을 수행해야 하는 것이다.

Local Space 좌표계에 상대적인 좌표를 World Space 좌표계에 상대적인 좌표로 바꾸는 것을 세계 변환(World Transform)이라고 하고, 해당 행렬을 세계 행렬(World Matrix)라고 한다.

 

 

이렇게 각 오브젝트를 각각의 Local 좌표로 정의하면 여러 장점이 있다.

 

1. 더 쉽다. 입방체(정육면체)를 정의한다고 가정했을 때 Local 좌표에서 정점을 정의할 때와 바로 해당 World 좌표의 임의의 위치, 크기, 방향에 맞춰진 정점의 좌표를 정의하는 것의 난이도 차이는 엄청나다. 아래 이미지를 보면 이해하기 좋다.

오브젝트의 중심을 원점(0, 0, 0)으로 잡으면 모서리의 정점 좌표가 정의하기가 쉬워지는 반면, 임의의 위치, 크기, 방향의 오브젝트의 정점 좌표는 정의하기가 힘들다.

2. 한 물체가 여러 장면에 재사용될 수 있는데, 그런 경우 물체의 좌표들을 특정 장면 기준으로 고정시키는 것은 바람직하지 않다. 각 좌표들을 하나의 Local 좌표계를 기준으로 저장하고, 각 장면마다 Local 좌표계를 해당 World 좌표계로 적절히 변환하는 좌표 변경 행렬을 적용하는 것이 효율적이다.

 

3. 한 물체를 하나의 장면 안에 위치나 방향, 크기를 달리해서 여러 번 그리기도 한다. 이를 인스턴스라고 하는데 인스턴스 물체마다 정점 자료를 중복하여 지정하기보다는 하나의 물체만 Local좌표로 생성하고 이를 World 좌표에 맞춰 변환한 위치, 크기, 방향 값만 정의하여 그리는 방법이 효율적이다. 이를 인스턴싱(Instancing)기법 이라고 한다.

 

물체의 local 공간을 world 공간에 상대적인 좌표를 서술하고 그 좌표들을 행들로 하는 하나의 행렬을 만들면 그물체의 세계 행렬(World Matrix)가 된다. 다시 말해, Qw = (Qx, Qy, Qz, 1)과 uw = (ux, uy, uz, 0), vw = (vx, vy, vz, 0), ww=(wx, wy, wz, 0)이 각각 local 공간의 원점과 x, y, z축들을  World 공간에 상대적인 동차좌표를 나타낸 것이라고 할때, local 공간을 World 공간으로 변환하는 좌표 변경 행렬은 다음과 같다.

 

$$W = \begin{bmatrix}u_x & u_y & u_z & 0 \\ v_x & v_y & v_z & 0\\ w_x & w_y & w_z & 0\\ Q_x & Q_y & Q_z & 1\end{bmatrix}$$

 

이러한 World Matrix를 만들기 위해서는 local 공간 원점 및 축들의 World 공간에 상대적인 좌표를 알아야 한다. 그런데 그런 좌표들을 구하기가 쉽지 않거나 직관적이지 않은 경우가 있다. 좀더 흔한 접근방식은 W를 일련의 변환들의 형태로 정의 하는 것이다. 예를 들어 W = SRT로 둘 수 있다. 즉, 물체를 World 공간 안에서 적절한 크기가 되게 만드는 비례행렬 S에 local좌표의 물체를 World 공간에 상대적인 방향으로 회전시키는 회전 행렬R을 곱하고, 이동 행렬 T를 곱한 것을 World Matrix로 사용할 수 있다.

Comments