Graphics Programming

기하 셰이더(Geometry Shader) 본문

Season 1/OpenGL

기하 셰이더(Geometry Shader)

minseoklee 2015. 10. 3. 11:26

기하 셰이더의 특징

  • 매 실행마다 프리미티브 하나를 통째로 처리 (정점 셰이더는 매 실행마다 정점 하나만 처리)
  • OpenGL 파이프라인의 데이터 양을 프로그래밍으로 변경 가능
  • 기하 셰이더에 들어오는 정점의 수 ≠ 나오는 정점의 수
  • 기하 셰이더에 들어오는 프리미티브 타입 ≠ 나오는 프리미티브 타입


기하 셰이더의 기본 사양


// 그냥 거쳐가는 기하 셰이더
layout (triangles) in;

layout (triangle_strip) out;

layout (max_vertices = 3) out;

 

void main() {

  int i;

  for(i=0; i<gl_in.length(); i++){

    gl_Position = gl_in[i].gl_Position;

    EmitVertex();

  }

  EndPrimitive();

}


in 레이아웃에 가능한 입력 모드

대응하는 드로우 모드

 points

 GL_POINTS

 lines

 GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP

 triangles

 GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP

 lines_adjacency

 GL_LINES_ADJACENCY

 triangles_adjacency

 GL_TRIANGLES_ADJACENCY

 out 레이아웃에 가능한 출력 모드 : points, line_strip, triangles_strip


// gl_in[]의 정의

in gl_PerVertex {

  vec4 gl_Position;

  float gl_PointSize;

  float gl_ClipDistance[];

} gl_in[];


layout (max_vertices = n) out;

n은 생성할 최대 정점 개수. 가능한 한 작아야 실행 성능이 좋다.

n은 최소 256이 보장된다. 현재 하드웨어에서의 최대 n은 glGetIntegerv()에 GL_MAX_GEOMETRY_OUTPUT_VERTICES를 인자로 질의


EmitVertex()는 모든 출력 변수를 undefined로 만든다.

 

'triangle_strip' 설정 상태에서 두 정점만 가지고 EndPrimitive() => 아무것도 생성되지 않는다

 

정점 셰이더에서 기하 셰이더로 값 전달하기


// 정점 셰이더의 출력

out VS_OUT {

  vec4 color;

  vec3 normal;

} vs_out;


// 기하 셰이더의 입력

in VS_OUT {

  vec4 color;

  vec3 normal;

} gs_in[];


입력 프리미티브 타입

gs_in의 길이

 points

 1

 lines

 2

 triangles

 3

 lines_adjacency

 4

 triangles_adjacency

 6




Multiple Streams of Storage


정점 셰이더가 있으면 정점 => 셰이더 => 다음 단계

                                             ↓

                          transform feedback buffer

여기서 정점과 TFB는 일대일 대응 저장

 

- 기하 셰이더가 있으면 각 셰이더 실행은, 바인딩된 TFB에 임의 개수의 정점을 저장한다

- 출력 스트림 네 개를 구성하여 기하 셰이더가 이 중 하나에 출력하도록 할 수 있다

- 기하 셰이더에서 다중 출력 스트림을 사용할 때 제약

  - 모든 스트림의 출력 모드는 points여야 한다

  - 첫 번째 스트림만 렌더링할 수 있다. 다른 것들은 오직 저장용이다.

 

out vec4 foo; - stream0

layout (stream = 1) out vec4 bar; - stream1

layout (stream = 3) out;

out int apple; - stream3

out int orange; - stream3

layout (stream = 2) out MY_BLOCK {

  vec3 purple;

  vec3 green;

}

 

void EmitStreamVertex(int stream)

void EndStreamPrimitive(int stream)

 

기하 셰이더에서만 가능한 타입들

GL_LINE_ADJACENCY

GL_LINE_STRIP_ADJACENCY

GL_TRIANGLES

GL_TRIANGLES_STRIP

 

Comments