서의 공간

제11장 기하 셰이더 본문

Graphics API/DirectX 11 - Luna

제11장 기하 셰이더

홍서의 2020. 12. 23. 06:47

목표

1. 기하 셰이더를 프로그래밍하는 방법을 배운다.

2. 기하 셰이더를 이용해서 빌보드를 효율적으로 구현하는 방법을 파악한다.

3. 자동으로 생성되는 기본도형 ID 및 그것의 용도 몇 가지를 알아본다.

4. 텍스처 배열을 생성하고 사용하는 방법을 파악하고, 텍스처 배열이 왜 유용한지 이해한다.

5. 알파-포괄도 변환이 알파 잘림의 앨리어싱 문제에 어떻게 도움이 되는지 이해한다.

11.1 기하 셰이더 프로그래밍

다음은 기하 셰이더 프로그램의 일반적인 틀이다.

[maxvertexcount(N)]
void ShaderName(
	PrimitiveType InputVertexType InputName [NumElements],
    inout StreamOutputObject<OutputVertexType> OutputName)
{
	// ...기하 셰이더 함수 본문...   
}

기하 셰이더 프로그램을 작성할 때에는 우선 기하 셰이더의 한 실행(호출)에서 출력할 정점들의 최대 개수를 지정해야 한다(기하 셰이더는 기본도형마다 실행된다). 이를 위해 기하 셰이더 주 함수 이전에 다음과 같은 구문을 최대 정점 개수 특성(attribute)을 지정해 주어야 한다.

[maxvertexcount(N)]

여기서 N은 기하 셰이더가 한 번의 실행에서 출력할 최대 정점 개수이다. 기하 셰이더가 실행 당 출력할 수 있는 정점의 개수는 가변적이나, 여기서 정의된 최대 개수를 넘지는 못한다. 성능을 위해서는 이 maxvertexcount 특성의 값을 최소한으로 잡는 것이 바람직하다.

기하 셰이더는 두 종류의 매개변수를 받는다. 하나는 입력 매개변수이고 또 하나는 출력 매개변수이다(사실은 그 외의 매개변수도 있지만, 이는 특별한 주제이다). 입력 매개변수는 항상 기본도형을 정의하는 정점들의 배열로, 기본도형이 점이면 정점이 하나, 선(선분)이면 두 개, 삼각형이면 세 개, 인접성 정보를 가진 선이면 네 개, 인접성 정보를 가진 삼각형이면 여섯 개이다. 입력 정점들의 정점 형식은 정점 셰이더가 출력한 정점의 형식(이를테면 VertexOut)이다.

입력 매개변수 앞에는 반드시 기하 셰이더가 받는 기본도형의 종류를 뜻하는 키워드를 붙여 주어야 한다. 사용 가능한 키워드는 다음과 같다.

  1. point: 입력 기본도형이 점인 경우.
  2. line: 입력 기본도형이 선(리스트 또는 스트립)인 경우.
  3. triangle: 입력 기본도형이 삼각형(리스트 또는 스트립)인 경우.
  4. lineadj: 입력 기본도형이 인접성 정보를 가진 선(리스트 또는 스트립)인 경우.
  5. triangleadj: 입력 기본도형이 인접성 정보를 가진 삼각형(리스트 또는 스트립)인 경우.

출력 매개변수 앞에는 항상 inout 수정자가 붙는다. 또한 출력 매개변수는 항상 스트림 형식이다. 스트림 형식은 기하 셰이더가 출력하는 기본도형을 정의하는 정점들의 목록을 담는다. 기하 셰이더에서 출력 스트림 목록에 정점을 추가할 때에는 다음과 같은 내장 Append 메서드를 사용한다.

void StreamOutputObject<OutputVertexType>::Append(OutputVertexType v);

스트림 형식은 템플릿 형식으로, 템플릿 인수는 출력 정점의 정점 형식(이를테면 GeoOut)을 지정한다. 사용 가능한 스트림 형식은 다음 세 가지이다.

  1. PointStream<OutputVertexType>: 점 리스트를 정의하는 정점들의 목록.
  2. LineStream<OutputVertexType>: 선 스트립을 정의하는 정점들의 목록.
  3. TriangleStream<OutputVertexType>: 삼각형 스트립을 정의하는 정점들의 목록.

기하 셰이더가 출력하는 정점들은 기본도형들을 형성하는데, 그 기본도형들의 종류는 스트림 형식(PointStream, LineStream, TriangleStream)에 의해 결정된다. 선과 삼각형의 경우 출력 기본도형은 항상 스트립이다. 그러나 RestartStrip 메서드를 이용하면 선 리스트나 삼각형 리스트를 흉내 낼 수 있다.

void StreamOutputObject<OutputVertexType>::RestartStreip();

예를 들어 삼각형 리스트를 출력하고 싶다면 출력 스트림에 정점 세 개를 추가할 때마다 RestartStrip을 호출해 주면 된다.

11.2 나무 빌보드 예제

HLSL에서 매개변수의 시맨틱 이름이 SV_PrimitiveID로 지정하면 입력 조립기 단계는 각 기본도형마다 자동으로 기본도형 ID(식별 번호)를 생성한다.

11.3 텍스처 배열

텍스처 배열(texture array)은 말 그대로 텍스처들의 배열을 담는 자원이다. C++코드에서 텍스처 배열은 ID3D11Texture2D 인터페이스로 대표된다(한 장짜리 텍스처에 쓰이는 것과 같은 인터페이스이다). ID3D11Texture2D 객체에는 저장할 텍스처 원소들의 개수를 뜻하는 ArraySize라는 속성(자료 멤버)이 있다. HLSL에서는 텍스처 배열을 Texture2DArray 형식으로 나타낸다.

파일로부터 일단의 이미지들을 텍스처 배열로 로드해 주는 함수는 없다. 따라서 응용 프로그램이 직접 로드해야 한다. 텍스처 배열 로드 과정을 요약하자면 다음과 같다.

  1. 시스템 메모리 안에서 각각의 텍스처를 파일로부터 생성한다.
  2. 텍스처 배열을 생성한다.
  3. 각 텍스처를 텍스처 배열의 각 원소에 복사한다.
  4. 텍스처 배열에 대한 셰이더 자원 뷰를 생성한다.

11.4 알파-포괄도 변환

 

 

'Graphics API > DirectX 11 - Luna' 카테고리의 다른 글

제18장 노멀 매핑과 변위 매핑  (0) 2020.12.23
제12장 계산 셰이더  (0) 2020.12.23
제10장 스텐실 적용  (0) 2020.12.23
제9장 혼합  (0) 2020.12.23
제8장 텍스처 적용  (0) 2020.12.22
Comments