그래픽스/DirectX12

[Directx12][14장]테셀레이션

우향우@ 2023. 3. 21. 21:48

개요

테셀레이션은 정점셰이더와 기하셰이더 사이에 존재하는 단계로 각 도형들을 더 세분화된 도형으로 나누는 역할을 한다. 테셀레이션에서는 분리되기전의 한 기하도형을 패치라는 단위로 부른다. 이는 단순 삼각형같은 도형뿐 아닌 여러 제어점으로 곡면등의 특수한 기하도형을 나타내기도 하기 때문이다.

테셀레이션은 다음 세단계로 구성된다.

덮개 셰이더 단계 : 실제 세분화전에 테셀레이션 세부 정도와 제어점들의 수정 및 추가를 하는 셰이더이다.

테셀 레이션 단계 : 덮개 셰이더의 입력을 토대로 실제 테셀레이션을 수행하는 자동으로 처리되는 단계이다.

영역 셰이더 단계 : 테셀레이션 된 후의 각 정점들에 대해 호출되는 정점셰이더 역할을 하는 셰이더이다.

테셀레이션의 필요성

테셀레이션은 거리나 픽셀 포함 정도등의 정보에 따라 기하구조의 세부성을 동적으로 다르게 렌더링하는 LOD 기법에 유용하며 물리 및 애니메이션 계산을 낮은 정점개수에 수행하고 이후 세부적으로 렌더링하는 최적화 기법에도 유용하다. 또한 실제 디스크나 메모리에 저장되는 메쉬 크기를 줄일 수 있어 공간절약에도 도움이 된다.

패치 기본도형 위상구조

테셀레이션을 사용할때는 n개의 제어점으로 이루어지는 n 제어점 패치를 기하구조로 사용해야한다. 3개의 제어점은 보통 삼각형을 나타내고 4개의 제어점은 사각형을 나타낸다. 그 이상의 제어점은 곡면 삼각형, 곡면 사각형등을 각자의 방식으로 표현하는 기하구조이다. 이렇게 입력된 패치는 덮개셰이더에서 더 많은 제어점으로 확장될 수 있음을 기억하자.

패치를 기하구조로 쓰면 당연히 정점셰이더에는 각 제어점에 대해 호출되며 주로 애니메이션이나 물리처리등이 이루어 지고 지역 포지션으로 테셀레이션에 바로 넘어가는 것이 일반적이다. 테셀레이션이 이루어 진후 영역셰이더에서 지역 포지션을 동차 절단 공간으로 변환하는 것이 일반적이다.

덮개 셰이더

덮개 셰이더는 특이하게 다음의 두 개의 셰이더 함수로 구성된다.

상수 덮개 셰이더 : 각 패치 별로 호출되며 테셀레이션 계수(세분화 정도) 및 패치별 추가 커스텀 정보를 출력한다.

제어점 덮개 셰이더 : 출력 제어점 별로 호출되며 테셀레이션전 제어점 수정 및 확장 역할을 한다.

상수 덮개 셰이더

상수 덮개 셰이더는 각 패치별로 호출되며 패치의 모든 입력 제어점(정점 셰이더의 출력)과 패치 ID를 받아 테셀레이션 계수 및 패치별 추가 커스텀 정보를 출력할 수 있다. 이는 테셀레이션 단계에서 테셀레이션 정도에 사용하며 패치 별 정보는 영역셰이더에 전달된다.

테셀레이션 계수는 기하구조에 따라 다르지만 보통 기하구조의 각 변, 내부 uv 별로 계수를 따로 줄 수 있다.

제어점 덮개 셰이더

제어점 덮개 셰이더는 각 출력 제어점 별로 호출된다. 셰이더 함수 위의 대괄호 추가 정보에 정수값을 넣어 한 패치 별로 출력하게 될 제이점 수를 적을 수 있다. 예를 들어 [outputcontrolpoint(6)]을 적으면 한 패치당 6개의 제어점을 출력하게 된다. 이때 입력 제어점 수와 출력 제어점 수는 당연히 다를 수 있다.

제어점 덮개 셰이더는 각 출력 제어점 별로 호출되는데 해당 출력 제어점의 소속 패치의 입력 제어점 모두와 해당 패치에서 출력 제어점의 인덱스 ID, 패치 ID등을 입력 받아 한 출력 제어점 정보를 출력한다.

해당 출력 제어점 정보는 이후 영역셰이더의 제어점 정보로 전달된다.

영역 셰이더

영역 셰이더는 테셀레이션 후 테셀레이션 된 각 정점에 대해 호출된다.

영역 셰이더는 해당 정점의 소속 패치의 테셀레이션 계수와 해당 패치에 모든 제어점 덮개 셰이더의 출력 제어점들을 입력으로 받는다. 거기에 0~1로 정규화된 패치 내의 해당 정점의 상대 좌표가 주어진다. 이 좌표는 기존 제어점들의 위치에는 전혀 영향없이 기본적인 기하구조 형태와 테셀레이션 계수에 의해 0~1로 정규화된 값으로 계산되며 이 값과 제어점들을 이용하여 해당 정점의 로컬 좌표를 구하는 것은 셰이더 프로그래머의 몫이다.

보통 해당 정점의 상대 좌표와 제어점들의 로컬 좌표로 해당 정점의 로컬 좌표를 구하고 월드행렬 및 투영행렬을 통해 동차 절단 공간으로 변환하여 출력하는 것이 일반적이다. 여기에 법선이나 텍스처 좌표등의 정점별 추가 정보가 있다면 그 정보들 역시 제어점 덮개 셰이더에서 유효한 제어점들에(제어점 모두에 들었을 수도 있고 아닐 수도 있다.) 그 값들을 담아 넘겨주고 영역셰이더에서는 상대 좌표와 패치 제어점들의 그 값을 이용해 해당 정점의 추가 정보를 계산하여 넘겨주는 것이 일반적이다.

베지에 곡선 곡면

2차 베지에 곡선은 점 세개로 표현된다. 점 a b c가 있을때 (1-t)a + tb, (1-t)b + tc으로 정의 된 매개 변수 t에서의 두점을 똑같이 t로 선형 보간한 점이 점 a b c에 매개변수 t로 표현되는 2차 베지에 곡선이다.

마찬 가지로 점 a b c d에서 t 매개변수에 대한 점 세개를 구하고 그 세개의 점에서 점 두개를, 마지막으로 그 점 두개에서 하나의 점을 매개변수에 대해 구해서 얻을 수 있는 곡선이 a b c d 에 대한 3차 베지에 곡선이다.

이는 n차 베지에 곡선으로 일반화 된다.

베지에 곡면은 3차를 예로 들면 16개의 점으로 한 사각형 곡면이 표현된다. 각 점을 4x4 격자로 인덱싱 할때 각 행의 점들로 3차 베지에 곡선을 만든다. 그리고 한 매개변수 u에 대해 각 곡선에서의 점을 얻고 그 점들로 3차 베지에 곡선을 만든다. 그 곡선에서 매개변수 v의 점이 바로 3차 베지에 곡면 (u,v)에 점의 3차원 좌표가 된다.

이렇게 16개의 점으로 삼차 베지에 곡면을 표현할 수 있다. 이를 이용하여 16 제어점 패치를 입력으로 하고 이후 이를 사각형 격자로 테셀레이션 한 뒤 영역셰이더의 각 정점에 대해 패치의 16 제어점과 패치 내 해당 정점의 uv 상대좌표를 이용하여 베지에 곡면 상 로컬 좌표를 구할 수 있다. 이를 이용하여 거리에 따라 세분화되는 3차 베지에 곡면을 렌더링 할 수 있다. 

참고서적

DirectX 12를 이용한 3D 게임 프로그래밍 입문