Geometry Shader
카테고리: OpenGL
태그: Graphics
Main Reference
- Learn OpenGL
- Rinthel Kwon - OpenGL Lecture
Geometry Shader
Geometry Shader는 Vertex Shader와 Pixel Shader 중간에 존재하는 Shader이다. 먼저 geometry shader는 특정한 primitive와 vertex들을 input으로 받는다. 그 후 기존 vertex들을 기반으로 새로운 vertex들을 생성하고, 이들을 다시 특정한 primitive와 조합해 fragment shader로 전달해 준다. 이때 out으로 출력되는 primitive는 input primitive와 같지 않아도 된다. Geometry Shader를 잘 이용하면 아주 효과적으로 CPU의 부담을 GPU로 나눌 수 있다.
// Render()..
glDrawArrays(GL_POINTS, 0, 4);
// geometry shader
#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 2) out;
void main() {
gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0);
EmitVertex();
EndPrimitive();
}
layout (points) in
: input primitive는 GL_POINTSlayout (line_strip, max_vertices = 2) out
- output primitive는 line_strip
- 하나의 out primitive로 나가는 vertex의 최대 개수는 2개
EmitVertex
: gl_Position으로 vertex 하나의 위치를 지정하고, outstream에 추가EndPrimitive
: 현재까지 추가한 vertex들로 primitive 생성
- 위 예제를 보면 Point 4개를 vertex shader로 넘기고
- Geometry Shader 단계에서 point마다 vertex를 추가해 line primitive로 변경
Example
// VBO
float points[] = {
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // 좌측 상단
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // 우측 상단
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // 우측 하단
-0.5f, -0.5f, 1.0f, 1.0f, 0.0f // 좌측 하단
};
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec3 aColor;
out VS_OUT {
vec3 color;
} vs_out;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
vs_out.color = aColor;
}
- 먼저 화면을 4분면으로 나누고, 각 사분면마다 포인트 하나와 컬러 값을 지정해서 vertex shader로 전달
- vertex shader에서는 gl_Position과 color 구조체를 geometry shader로 전달
// geometry shader
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 5) out;
in VS_OUT {
vec3 color;
} gs_in[];
void main() {
fColor = gs_in[0].color;
gl_Position = position + vec4(-0.2, -0.2, 0.0, 0.0);
EmitVertex();
gl_Position = position + vec4( 0.2, -0.2, 0.0, 0.0);
EmitVertex();
gl_Position = position + vec4(-0.2, 0.2, 0.0, 0.0);
EmitVertex();
gl_Position = position + vec4( 0.2, 0.2, 0.0, 0.0);
EmitVertex();
gl_Position = position + vec4( 0.0, 0.4, 0.0, 0.0);
EmitVertex();
EndPrimitive();
}
in/out layout
지정in VS_OUT
: vertex shader에서 out으로 내보낸 interface block(구조체)와 동일한 block name으로 color 받아오기fColor = gs_in[0].color
: geometry shader로 새로 생성한 vertex들은 모두 기존의 색과 동일하니 한 번만 지정EmitVertex
: gl_Position을 지정하고 EmitVertex를 실행하면, position값과 fColo값이 output stream에 추가
fColor = gs_in[0].color;
gl_Position = position + vec4(-0.2, -0.2, 0.0, 0.0); // 1:좌측 하단
EmitVertex();
gl_Position = position + vec4( 0.2, -0.2, 0.0, 0.0); // 2:우측 하단
EmitVertex();
gl_Position = position + vec4(-0.2, 0.2, 0.0, 0.0); // 3:좌측 상단
EmitVertex();
gl_Position = position + vec4( 0.2, 0.2, 0.0, 0.0); // 4:우측 상단
EmitVertex();
gl_Position = position + vec4( 0.0, 0.4, 0.0, 0.0); // 5:꼭대기
fColor = vec3(1.0, 1.0, 1.0);
EmitVertex();
EndPrimitive();
- 지붕 꼭대기 vertex만 흰 색으로 컬러를 변경하면 눈 쌓인듯한 느낌 연출 가능
- 당연하지만, 이 결과를 보면 Rasterize 단계는 geometry shader 이후라는 것을 알 수 있음
Object Exploding | Visualize Normals |
---|---|
- 이 외에도, 오브젝트를 이루는 삼각형 면들을 normal 방향으로 들어올려 오브젝트가 폭팔되는 연출을 한다던가
- vertex마다 normal 방향으로 line을 하나 그려 noraml vector를 시각화하는 것도 가능
댓글 남기기