GLSL Geometry Shaders, Простенькая тесселляция :)
Автор: Игорь Устинов
Решил изучить геометрические шейдеры, ну и заодно добавить их в движок, решил сделать простенькую тесселляцию :)
Subdivision Level 2 - (6 вершин на входе, 2 треугольника на входе), (48 вершин на выходе, 16 треугольников на выходе)
Демка(Необходима поддержка OpenGL 3.3):
BloodyGS2
Картинка:

Шейдир:
#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); }
Насколько оно медленно я не мерял, но то что медленно это точно ;)
#Geometry Shaders, #GLSL, #OpenGL, #tessellation
23 августа 2011