본문 바로가기
게임 공부/HLSL

Geometry Shader Signature

by woohyeon 2021. 7. 14.
반응형

Geometry Shader란?

GS(Geometry Shader)는 VS, PS와 같은 셰이더의 한 종류이다. 실행 순서는 VS->GS->(Rasterizer)->PS 순이다.

VS가 하나의 정점에 대해 어떤 동작을 수행하는 프로그램이였다면, GS는 하나의 프리미티브에 대해 어떤 동작을 수행하는 프로그램이다. 즉 하나의 점(Point)도 입력이 될 수 있고 라인(Line)도 입력이 될 수 있고 삼각형(Triangle)도 입력이 될 수 있다. GS는 입력으로 들어온 프리미티브를 변경(modify) 및 제거(remove) 할 수 있고, 새로운 프리미티브를 생성(create)할 수도 있다. VS, PS와 달리 작성을 하지 않아도 실행하는 데는 문제가 없다. 

 

Shader Signature

GS를 작성하는 방법은 VS, PS와는 살짝 다르다. 우선 함수의 헤더에 다음과 같이 maxvertexcount라는 파라미터를 지정해 주어야 한다. 이 파라미터는 GS가 실행될 때마다 최대 몇 개의 버텍스를 append(잠시 후 살펴봄) 할 것인지 결정한다. 이 파라미터의 맥시멈은 18이다. 아래의 셰이더는 최대 3개의 버텍스를 append 한다.

[maxvertexcount(3)]
void GSMain(triangle GS_INPUT input[3], inout TriangleStream<GS_OUTPUT> TriStream)
{
...
}


다음으로 반환형을 살펴보면 void 타입인 것을 볼 수 있다. 즉 아무것도 반환하지 않는다. 대신 두 번째 인자인 스트림에 미리 생성한 프리미티브를 append 하거나, 값을 변경한 프리미티브를 append 함으로써 동작을 수행한다. 만약 어떤 프리미티브를 제거하려면 그냥 그 프리미티브를 append 하지 않으면 된다.

첫 번째 인자는 프리미티브를 구성하는 입력 데이터이다. 앞에 붙는 trianglePrimitive Type 타입으로 point, line, triangle 등이 있는데, 이를 명시해주어야 한다. 

두 번째 인자의 앞에 붙는 inout은 고정이다. 입력이기도 하고 여기에 값을 write해서 output 용도로 사용한다는 의미이다. 타입은 PointStream, LineStream, TriangleStream 중 알맞게 하나를 선택하면 된다.

LineStream이나 TriangleStream을 사용할 때 output은 항상 strip 기법이다. 따라서 list를 사용한다면 하나의 프리미티브에 대해 append가 완료되었을 때 Stream 타입의 RestartStrip() 함수를 통해 strip을 끊어주어야 한다.

아래 코드는 가져온 3개의 정점을 그대로 출력하는 아무 의미없는 코드이다. 예시를 위해 간단하게 작성하였다. 만약 아래에서 Append를 하지 않으면 해당 프리미티브는 제거된다. 하나의 프리미티브에 대한 동작을 완료한 뒤 RestartStrip을 통해 strip을 끊어줌으로써 strip을 사용하지 않고, 리스트 형태로 사용하게 된다.

[maxvertexcount(3)]
void GSMain(triangle GS_INPUT input[3], inout TriangleStream<GS_OUTPUT> TriStream)
{
  for(int v = 0; v < 3; ++v)
  {
    GS_OUTPUT output = {};
    output.Pos = input[i].Pos;
    TriStream.Append(output);
  }
  TriStream.RestartStrip();
}



댓글