개요
기하셰이더는 정점셰이더와 래스터화단계 사이에서 입력 기본 도형마다 한 번씩 처리되는 셰이더이다. 기하셰이더는 입력으로 렌더링에 사용된 기본 도형들을 입력받고 원하는 종류의 0~n개의 기본 도형들을 출력할 수 있다.
예를 들어 점들을 기본 입력 도형으로 하는 렌더링에서 기하셰이더는 한 점을 받아 두개의 삼각형으로 변환하여 출력할 수 있다.
이렇게 기하셰이더는 도형을 확장하거나 반대로 줄이거나 폐기하는 용도로 주로 사용된다.
코드 구조
기하셰이더의 기본구조는 다음과 같다.
[maxvertexcount(n)]
void GS(line GSInputVertexType gin[2], inout TriangleStream<GSOutputVetexType> triStream)
{
...
}
[maxvertexcount(n)]는 이 기하셰이더에서 출력할 수 있는 총 정점 갯수이다. 성능에 큰 영향을 미치기에 가능한 적게 적어야한다.
line GSInputVertexType gin[2]은 정점셰이더에서 넘어온 정점들이 기본도형별로 묶여서 정점구조체 배열로 넘어온다. 점이면 point GSInputVertexType gin[1], 삼각형이면 triangle GSInputVertexType gin[3]이다.
inout TriangleStream<GSOutputVetexType> triStream은 출력 기본도형띠이다.
출력은 점,선,삼각형 띠중 하나이며 각각
PointStream<GSOutputVetexType>
LineStream<GSOutputVetexType>
TriangleStream<GSOutputVetexType>
이며 GSOutputVetexType는 출력 정점 타입이다. 이는 픽셀셰이더에 입력으로 들어갈 타입이된다.
OOOStream.append(버텍스)로 스트림에 정점을 추가하여 채울 수 있다.
또한 출력은 비록 띠로 고정이지만 OOOStream.RestartStrip()으로 띠를 끊고 새로운 띠로 시작할 수 있기에 모든 표현이 가능하다.
빌보드 예제
기하셰이더의 대표적인 사용 예시는 빌보드이다. 빌보드는 3D 물체를 렌더링 하는 대신 2D 이미지를 3차원 공간에 띄어 근사적으로 3D물체를 표현하는 방법이다. 보통 거리가 먼 나무같은 물체에 대해 2D 이미지를 해당 위치에 넣고 카메라를 향해 서도록 구현함으로써 먼거리의 물체를 근사한다.
이러한 빌보드는 기하셰이더로 효과적으로 구현할 수 있다.
다음은 그 과정이다.
빌보드들은 텍스처와 중심 위치점만으로 표현이 가능하기에 이로 표현한다.
- 정점 구조체를 빌보드 월드 좌표의 중점 위치와 사각형 크기 정보를 가지도록 하고 기본 입력 도형을 점으로 한다.
- 각 빌보드의 정보를 담은 점들과 텍스처, 여러 패스정보(카메라 정보 포함)를 파이프라인에 달고 렌더링을 한다.
- 정점셰이더에서는 정보를 그대로 넘겨준다.
- 기하셰이더에서 카메라 위치, 빌보드 중심 위치, 사각형 크기로 빌보드를 만들 4개의 정점의 월드 좌표, 텍스처 좌표, 법선벡터등을 계산하고 동차 절단 공간 좌표도 구하여 두개의 삼각형, 즉 하나의 사각형 빌보드 도형으로 만들어 픽셀셰이더에 넘겨준다.
- 픽셀 셰이더에서 정상적으로 처리한다.
이를 통해 점으로 빌보드를 표현하고 파이프라인에서 이를 확장하도록 할 수 있다.
텍스처 배열
텍스처 배열은 말그대로 텍스처를 담은 배열이다. DDS를 만들때 여러 텍스처를 담은 텍스처 배열로 파일을 만들 수 있으며 이를 DirectX에서 가져와 자원 객체에 텍스처 배열 자원으로써 담아 사용할 수 있다. 자원을 생성할 때 배열의 크기를 지정해주면 텍스처 배열로써 사용되게 된다. 이러한 텍스처 배열은 셰이더에서 Texture2DArray타입으로 받아 사용할 수 있다. 이러한 텍스처 배열은 표본 추출시 3차원 좌표로 추출할 수 있다. xy는 기존의 xy좌표를 사용하고 z를 0,1,2..으로 n번째 텍스처의 xy좌표를 추출한다는 의미로 사용가능하다.
텍스처배열의 부분자원이라는 용어가 있다. 이는 텍스처 배열의 한 텍스처의 한 밉맵수준을 지칭하는 말이다. 이때 한 텍스처의 모든 밉맵수준의 모음을 배열 조각이라 하며 모든 텍스처의 한 밉맵수준의 모음을 밉 조각이라한다.
알파 포괄도 변환
기존의 다중표본화만을 사용하면 알파배경과 중간 이미지를 이용한 빌보드들은 중간 이미지들의 테두리가 다중표본화가 적용되지않아 계단현상이 발생한다. 이는 우리가 기존에 쓰던 다중표본화는 해당 화면 픽셀에 도형의 테두리가 얼마나 걸쳐있는지, 즉 화면 픽셀을 실제 개념적인 도형이 얼마나 채우는지를 토대로 픽셀의 진하기를 설정하는 방식을 사용했다. 이를 포괄도라 한다. 이때 알파 배경의 빌보드는 빌보드 사각형의 끝부분에만 의미없는 다중표본화가 적용될뿐 중앙 이미지에는 적용되지않는다.
이는 알파 포괄도 기법으로 해결 할 수 있다. 알파포괄도는 픽셀셰이더가 출력한 알파값을 포괄도로 취급하여 처리하는 다중표본화 기법이다. 알파 배경을 사용하는 빌보드를 표본추출하여 사용하면 이미지의 중앙부분들은 정상적으로 rgb1의 색으로 추출되어 정상 출력되고 테두리 근처의 픽셀들은 투명한 색과 끝 색깔이 선형 필터링되어 중간의 색과 알파값을 가지게 된다. 이때 다중표본화가 중간 알파를 포괄도로 취급하여 색을 연하게 해주면 이미지의 테두리부분은 선형적인 색을 가지게 되어 부드러운 다중표본화가 이루어지게된다.
알파포괄도는 PSO의 BLEND 구조체의 알파포괄도활성화 멤버를 true로 하여 활성화 할 수 있다.
참고서적
DirectX 12를 이용한 3D 게임 프로그래밍 입문
'그래픽스 > DirectX12' 카테고리의 다른 글
[Directx12][14장]테셀레이션 (0) | 2023.03.21 |
---|---|
[Directx12][13장]계산셰이더 (0) | 2023.03.21 |
[Directx12][11장]스텐실 (0) | 2023.03.21 |
[Directx12][10장]혼합 (0) | 2023.03.21 |
[Directx12][~9장][실습]Block Game (0) | 2023.03.21 |