1. 개요
기하 셰이더(GS)는 그래픽스 파이프라인에서 정점 처리(VS 또는 DS)와 래스터라이저(RS) 사이에 위치하는 선택적인 프로그래밍 가능 스테이지이다.
GS의 특징은, 파이프라인의 다른 셰이더 단계와 달리 개별 정점(Vertex)이 아닌 완성된 기본 도형(Primitive) 전체를 입력으로 받는다는 것이다.
- VS/DS: 정점 1개를 입력받아 정점 1개를 출력한다. (1:1)
- GS: 기본 도형 1개(예: 삼각형 1개 = 정점 3개)를 통째로 입력받아, 0개, 1개, 또는 그 이상의 기본 도형을 출력할 수 있다. (1:N)
2. GS의 3가지 핵심 기능
GS는 입력받은 기본 도형(점, 선, 삼각형)에 대해 세 가지 작업을 수행할 수 있다.
2.1. 기본 도형 전달 (Pass-through)
- 입력받은 기본 도형(예: 삼각형 1개)을 아무런 수정 없이 그대로 래스터라이저(RS)로 전달한다.
2.2. 기본 도형 폐기 (Discard / Culling)
- GS의 강력한 기능이다. GS는 입력받은 기본 도형의 정점들을 모두 검사할 수 있다.
- 예를 들어, GS는 삼각형의 세 정점을 이용해 법선 벡터(Normal)를 계산하고, 이 삼각형이 카메라를 등지고 있는지(후면인지) 판별할 수 있다.
- 만약 특정 조건(예: 너무 작거나, 뒷면이거나)에 해당하면, GS는 아무것도 출력하지 않고 실행을 종료하여 래스터라이저로 넘어가는 지오메트리를 **폐기(Cull)**시킬 수 있다.
- 이는 RS의 고정 기능(Fixed-Function) 컬링보다 더 복잡하고 유연한 사용자 정의 컬링을 가능하게 한다.
2.3. 기본 도형 생성 (Generate / Amplify)
- GS의 가장 유명한 기능이다. GS는 입력받은 기본 도형을 기반으로 완전히 새로운 정점과 기본 도형을 생성할 수 있다.
- **출력 스트림(Output Stream)**이라는 특별한 객체에 Append()(정점 추가)와 RestartStrip()(도형 재시작) 명령을 사용하여 새 지오메트리를 '즉석에서' 만들어낸다.
3. 주요 사용 사례
이 "생성" 및 "폐기" 기능을 통해 다음과 같은 작업들이 가능했다.
3.1. 포인트 스프라이트 확장 (Point Sprite Expansion)
- 입력: point 1개.
- 작동: VS에서 점(파티클 위치) 1개를 GS로 보낸다. GS는 이 점을 중심으로 2D 사각형(Quad, 즉 삼각형 2개)을 구성하는 새로운 정점 4개를 생성하여 래스터라이저로 보낸다.
- 이점: RS의 자동 포인트 스프라이팅보다 더 정교한 제어(예: 파티클 회전, 크기 조절)가 가능하다.
3.2. 동적 빌보딩 (Dynamic Billboarding)
- 잔디, 나무 잎사귀 등을 그릴 때 사용된다.
- 입력: point 1개 (잔디 뿌리 위치).
- 작동: GS가 이 점을 입력받아 카메라를 항상 바라보는 사각형(빌보드)을 즉석에서 생성한다.
3.3. 지오메트리 증폭 (Geometry Amplification)
- 입력: triangle 1개.
- 작동: (예: "폭발" 효과) GS가 삼각형 1개를 입력받아, 각 면을 바깥쪽으로 밀어낸 3개의 삼각형을 새로 생성하여 출력할 수 있다.
3.4. 렌더 타겟 배열 / 계층 렌더링 (Layered Rendering)
- GS의 매우 중요하고 효율적인 사용처이다.
- 작동: GS는 SV_RenderTargetArrayIndex라는 시스템 값을 출력할 수 있다. 이를 통해 GS는 **단 한 번의 그리기 명령(Draw Call)**으로, 6개의 큐브맵(Cube Map) 면 또는 여러 텍스처 배열 슬라이스에 지오메트리를 동시에 렌더링할 수 있다.
- 예시: 점 광원(Point Light)의 옴니디렉셔널(Omni-directional) 섀도우 맵을 생성할 때, 6개 방향(큐브맵 6면)에 대해 6번 그리는 대신, GS를 이용해 단 1번만 그릴 수 있다.
4. 입력과 출력
- 입력 (Input): 셰이더 코드에 명시된 기본 도형 타입.
- point (정점 1개)
- line (정점 2개)
- triangle (정점 3개)
- 출력 (Output): 셰이더 코드에 명시된 출력 스트림 타입.
- PointStream<...>
- LineStream<...>
- TriangleStream<...> (가장 일반적)
5. 성능 및 현대적 관점 ⚠️
기하 셰이더는 매우 강력하지만, 성능에 심각한 문제를 야기할 수 있어 현대 게임 개발에서는 사용을 기피하는 추세이다.
- 병렬성 저해: GS는 1:1이 아닌 1:N 출력을 가진다. GPU는 GS가 몇 개의 정점을 출력할지 미리 알 수 없으므로, 병렬 처리를 위한 메모리 할당과 스레드 스케줄링이 매우 비효율적으로 변한다.
- 정점 순서 변경: GS는 정점의 순서를 재구성하여 GPU의 정점 캐시 효율성을 떨어뜨린다.
대안:
- 지오메트리 생성: **컴퓨트 셰이더(Compute Shader)**를 사용하여 지오메트리를 미리 생성(Culling/Amplification)하고 버퍼에 저장한 뒤, 일반 VS/RS 파이프라인으로 그리는 방식이 훨씬 빠르다.
- 빌보딩/확장: 간단한 확장은 정점 셰이더(VS) 내에서 SV_VertexID를 이용한 트릭으로도 구현할 수 있다.
- 계층 렌더링: GS의 유일한 장점이었으나, 최신 API(DX12/Vulkan)에서는 GS 없이도 SV_RenderTargetArrayIndex를 VS에서 직접 제어할 수 있는 기능이 도입되어 GS의 필요성이 더욱 줄어들었다.
'그래픽스' 카테고리의 다른 글
| 08. Pixel Shader - Image Texturing (0) | 2025.11.04 |
|---|---|
| 07. Rasterizer (0) | 2025.11.04 |
| 05. Domain Shader (0) | 2025.11.04 |
| 04. Tessellator (0) | 2025.11.04 |
| 03. Hull Shader (0) | 2025.11.04 |