Блог
GameDev.ru / Страницы / Майн Блог / GLSL Geometry Shaders, Простенькая тесселляция :)

GLSL Geometry Shaders, Простенькая тесселляция :)

Автор:

Решил изучить геометрические шейдеры, ну и заодно добавить их в движок, решил сделать простенькую тесселляцию :)

Subdivision Level 2 - (6 вершин на входе, 2 треугольника на входе), (48 вершин на выходе, 16 треугольников на выходе)

Демка(Необходима поддержка OpenGL 3.3):
BloodyGS2

Картинка:
GSTESS2 | GLSL Geometry Shaders, Простенькая тесселляция :)

Шейдир:

#vertex_shader

layout(location = 0) in vec2 iPosition;
layout(location = 1) in vec2 iTexcoord;

out vec2 vTexcoord;

#if defined(TEXTURE_TRANSFORM)
uniform mat4 uTextureMatrix;
#endif

void main() {
  gl_Position = vec4(iPosition.xy, 0.0, 1.0);
#if defined(TEXTURE_TRANSFORM)
  vTexcoord.s = dot(iTexcoord, uTextureMatrix[0].st);
  vTexcoord.t = dot(iTexcoord, uTextureMatrix[1].st);
#else
  vTexcoord = iTexcoord;
#endif
}

#fragment_shader

layout(location = 0) out vec4 oFragmentColor0;

uniform vec4 uColor;

in vec2 vTexcoord;

void main() {
  oFragmentColor0 = uColor;
}

#geometry_shader


layout(triangles) in;
layout(triangle_strip, max_vertices = 48) out;
in  vec2 iTexcoord[3];
out vec2 vTexcoord;

struct Triangle {
  vec4 position;
  vec2 texcoord;
};

void EmitTriangle( in Triangle v0, in Triangle v1, in Triangle v2 ) {
  gl_Position = v0.position;
  vTexcoord = v0.texcoord;
  EmitVertex();

  gl_Position = v1.position;
  vTexcoord = v1.texcoord;
  EmitVertex();

  gl_Position = v2.position;
  vTexcoord = v2.texcoord;
  EmitVertex();

  EndPrimitive();
}

void SubdivideTriangle2( in Triangle v0, in Triangle v1, in Triangle v2, int level ) {
  Triangle v3;
  v3.position = mix(v0.position, v1.position, 0.5);
  v3.texcoord = mix(v0.texcoord, v1.texcoord, 0.5);

  Triangle v4;
  v4.position = mix(v1.position, v2.position, 0.5);
  v4.texcoord = mix(v1.texcoord, v2.texcoord, 0.5);

  Triangle v5;
  v5.position = mix(v2.position, v0.position, 0.5);
  v5.texcoord = mix(v2.texcoord, v0.texcoord, 0.5);

  EmitTriangle(v0, v3, v5);
  EmitTriangle(v3, v4, v5);
  EmitTriangle(v3, v1, v4);
  EmitTriangle(v5, v4, v2);
}

void SubdivideTriangle( in Triangle v0, in Triangle v1, in Triangle v2, int level ) {
  Triangle v3;
  v3.position = mix(v0.position, v1.position, 0.5);
  v3.texcoord = mix(v0.texcoord, v1.texcoord, 0.5);

  Triangle v4;
  v4.position = mix(v1.position, v2.position, 0.5);
  v4.texcoord = mix(v1.texcoord, v2.texcoord, 0.5);

  Triangle v5;
  v5.position = mix(v2.position, v0.position, 0.5);
  v5.texcoord = mix(v2.texcoord, v0.texcoord, 0.5);

  if( level > 1 ) {
    SubdivideTriangle2(v0, v3, v5, level);
    SubdivideTriangle2(v3, v4, v5, level);
    SubdivideTriangle2(v3, v1, v4, level);
    SubdivideTriangle2(v5, v4, v2, level);
  } else {
    EmitTriangle(v0, v3, v5);
    EmitTriangle(v3, v4, v5);
    EmitTriangle(v3, v1, v4);
    EmitTriangle(v5, v4, v2);
  }
}

void main() {

  Triangle v0;
  v0.position = gl_in[0].gl_Position;
  v0.texcoord = iTexcoord[0];

  Triangle v1;
  v1.position = gl_in[1].gl_Position;
  v1.texcoord = iTexcoord[1];

  Triangle v2;
  v2.position = gl_in[2].gl_Position;
  v2.texcoord = iTexcoord[2];

  int subdivisionLevel = 2;

  if( subdivisionLevel == 0 ) {
    EmitTriangle(v0, v1, v2);
  } else
    SubdivideTriangle(v0, v1, v2, subdivisionLevel);
}

Насколько оно медленно я не мерял, но то что медленно это точно ;)

23 августа 2011

#Geometry Shaders, #GLSL, #OpenGL, #tessellation

2001—2018 © GameDev.ru — Разработка игр