So where's an example tessellation shader?

I’ve got my engine set up to handle tessellation shaders. I can’t seem to find a GLSL example anywhere. Where can I find one?

I can’t find the example I used now, but when I got it, I got it pretty quickly:

No time has come for tessellation, Carmack still use OpenGL 2.1 xD

Here are some explanations/examples i have found.

http://prideout.net/blog/?p=48
http://codeflow.org/entries/2010/nov/07/opengl-4-tessellation/

Shaders from TessMark :whistle:

/////////////////////////////// Vertex shader
#version 400 core
in vec4 In_Position;
in vec4 In_Normal;
in vec4 In_UV;
uniform mat4 WorldMatrix;
uniform mat3 NormalMatrix;
uniform float UVScale;
out vec4 Color_VS_CS;
out vec4 Normal_VS_CS;
out vec4 UVMap_VS_CS;
void main()
{
    gl_Position = WorldMatrix * In_Position;
   UVMap_VS_CS = In_UV * UVScale;
   Normal_VS_CS = WorldMatrix * vec4(In_Normal.xyz, 0.0);
   Color_VS_CS = Normal_VS_CS;
   Color_VS_CS.w = 1.0;
}

//////////////////////////////// Fragment shader

#version 400 core
out vec4 Out_Color;
in vec4 lightDir1;
in vec4 lightDir2;
in vec4 eyeVec;
in vec2 texcoord;
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
uniform sampler2D normalMap;
uniform vec4 light0_diffuse;
uniform vec4 light1_diffuse;
uniform vec4 mat_specular;
void main()
{
   vec3 diffuseColor = texture(diffuseMap, texcoord).xyz; 
   vec3 bump = texture(bumpMap, texcoord).xyz;
   vec3 bN = normalize(texture(normalMap, texcoord).xyz * 2.0 - 1.0);   
   vec4 light0_ambient = vec4(0.1, 0.1, 0.1, 1.0);
   vec4 light0_specular = vec4(0.9, 0.9, 0.9, 1.0);
   vec4 light1_ambient = vec4(0.1, 0.1, 0.1, 1.0);
   vec4 light1_specular = vec4(0.9, 0.9, 0.9, 1.0);
   vec4 matAmbient = vec4(0.4, 0.4, 0.4, 1.0);
   vec4 matDiffuse = vec4(0.8, 0.8, 0.9, 1.0);
   vec3 final_color = vec3(0.0, 0.0, 0.0);
   vec3 L = normalize(lightDir1.xyz);
   final_color += (light0_ambient.rgb * matAmbient.rgb)  * diffuseColor.xyz;
   float lambertTerm = clamp(dot(bN,L), 0.0, 1.0);
   final_color += (light0_diffuse.rgb * matDiffuse.rgb) * lambertTerm * diffuseColor.xyz;   
   float matShininess = mat_specular.a;
   vec3 E = normalize(eyeVec.xyz);
   vec3 R = reflect(-L, bN);
   float specular = pow(max(dot(R, E), 0.0), matShininess);
   final_color += (light0_specular.rgb * mat_specular.rgb) * specular * lambertTerm  * bump.x;
   L = normalize(lightDir2.xyz);
   final_color += (light1_ambient.rgb * matAmbient.rgb)  * diffuseColor.xyz;
   lambertTerm = clamp(dot(bN,L), 0.0, 1.0);
   final_color += (light1_diffuse.rgb * matDiffuse.rgb) * lambertTerm  * diffuseColor.xyz;   
   E = normalize(eyeVec.xyz);
   R = reflect(-L, bN);
   specular = pow(max(dot(R, E), 0.0), matShininess);
   final_color += (light1_specular.rgb * mat_specular.rgb) * specular * lambertTerm  * bump.x;
   Out_Color = vec4(final_color.xyz, 1.0);   
}    

//////////////////////////////// Evaluation shader

#version 400 core
layout(triangles, equal_spacing, ccw) in;
in vec4 Colors_CS_ES[];
in vec4 Normal_CS_ES[];
in vec4 UVMap_CS_ES[];
patch in vec3 f3B210;
patch in vec3 f3B120;
patch in vec3 f3B021;
patch in vec3 f3B012;
patch in vec3 f3B102;
patch in vec3 f3B201;
patch in vec3 f3B111;
patch in vec3 f3N110;
patch in vec3 f3N011;
patch in vec3 f3N101;
uniform mat4 WorldMatrix;
uniform mat4 ViewProjectionMatrix;
uniform mat4 ViewMatrix;
uniform sampler2D bumpMap;
uniform sampler2D normalMap;
uniform vec4 light0_diffuse;
uniform vec4 light1_diffuse;
uniform vec4 mat_specular;
uniform float bumpScale;
out vec4 color;
out vec3 normal;
out vec4 lightDir1;
out vec4 lightDir2;
out vec4 eyeVec;
out vec2 texcoord;
vec4 interpolate(in vec4 v0, in vec4 v1, in vec4 v2, in vec4 v3)
{
  vec4 a = mix(v0, v1, gl_TessCoord.x);
  vec4 b = mix(v3, v2, gl_TessCoord.x);
  return mix(a, b, gl_TessCoord.y);
}
void main()
{
   float u = gl_TessCoord.x;
   float v = gl_TessCoord.y;
   float w = gl_TessCoord.z;
   color = vec4(0);
   color += u * Colors_CS_ES[0];
   color += v * Colors_CS_ES[1];
   color += w * Colors_CS_ES[2];
   texcoord = vec2(0);
   texcoord += w * UVMap_CS_ES[0].xy;
   texcoord += u * UVMap_CS_ES[1].xy;
   texcoord += v * UVMap_CS_ES[2].xy;
vec4 bump = texture(bumpMap, texcoord); 
float fU = gl_TessCoord.x;
float fV = gl_TessCoord.y;
float fW = gl_TessCoord.z;
float fUU = fU * fU;
float fVV = fV * fV;
float fWW = fW * fW;
float fUU3 = fUU * 3.0f;
float fVV3 = fVV * 3.0f;
float fWW3 = fWW * 3.0f;
vec4 pos;
pos.w = 1.0;
pos.xyz = gl_in[0].gl_Position.xyz * fWW * fW +
              gl_in[1].gl_Position.xyz * fUU * fU +
              gl_in[2].gl_Position.xyz * fVV * fV +
              f3B210 * fWW3 * fU +
              f3B120 * fW * fUU3 +
              f3B201 * fWW3 * fV +
              f3B021 * fUU3 * fV +
              f3B102 * fW * fVV3 +
              f3B012 * fU * fVV3 +
              f3B111 * 6.0f * fW * fU * fV;
normal =   Normal_CS_ES[0].xyz * fWW +
                    Normal_CS_ES[1].xyz * fUU +
                    Normal_CS_ES[2].xyz * fVV +
                    f3N110 * fW * fU +
                    f3N011 * fU * fV +
                    f3N101 * fW * fV;
   vec3 N = normalize(normal.xyz);
   pos.xyz += N * bump.x * bumpScale;
   gl_Position = ViewProjectionMatrix * pos;
   vec3 T;
   vec3 B; 
   vec4 v1 = WorldMatrix * vec4(0.0, 0.0, 1.0, 0.0);
   vec4 v2 = WorldMatrix * vec4(0.0, 1.0, 0.0, 0.0);
   vec3 c1 = cross(N, v1.xyz); 
   vec3 c2 = cross(N, v2.xyz); 
   if (length(c1) > length(c2))
     T = c1;   
   else
     T = c2;   
   B = cross(N, T); 
   T = normalize(vec3(ViewMatrix * vec4(T.xyz, 0.0)));
   B = normalize(vec3(ViewMatrix * vec4(B.xyz, 0.0)));
   N = normalize(vec3(ViewMatrix * vec4(N.xyz, 0.0)));
   vec4 vVertex = ViewMatrix * pos;
   eyeVec = -vVertex;
   vec4 l1 = vec4(-20.0, -20.0, 20.0, 1.0);
   vec4 l2 = vec4(20.0, 20.0, 20.0, 1.0);
   vec3 lp1 = vec3(ViewMatrix * l1);
   vec3 lp2 = vec3(ViewMatrix * l2);
   vec3 tmpVec;
   vec3 lVec = lp1 - vVertex.xyz;
   tmpVec.x = dot(lVec, T);
   tmpVec.y = dot(lVec, B);
   tmpVec.z = dot(lVec, N);
   lightDir1.xyz = tmpVec;
   lVec = lp2 - vVertex.xyz;
   tmpVec.x = dot(lVec, T);
   tmpVec.y = dot(lVec, B);
   tmpVec.z = dot(lVec, N);
   lightDir2.xyz = tmpVec;
   vec3 vVec = -vVertex.xyz;
   tmpVec.x = dot(vVec, T);
   tmpVec.y = dot(vVec, B);
   tmpVec.z = dot(vVec, N);
   eyeVec.xyz = tmpVec;
}

/////////////////////////////////// Control shader    

#version 400 core
layout(vertices = 3) out;
uniform float tessLevelOuter;
uniform float tessLevelInner;
uniform mat4 ViewMatrix;
in vec4 Color_VS_CS[];
in vec4 Normal_VS_CS[];
in vec4 UVMap_VS_CS[];
out vec4 Colors_CS_ES[];
out vec4 Normal_CS_ES[];
out vec4 UVMap_CS_ES[];
patch out vec3 f3B210;
patch out vec3 f3B120;
patch out vec3 f3B021;
patch out vec3 f3B012;
patch out vec3 f3B102;
patch out vec3 f3B201;
patch out vec3 f3B111;
patch out vec3 f3N110;
patch out vec3 f3N011;
patch out vec3 f3N101;
void main()
{
   gl_TessLevelOuter[0] = tessLevelOuter;
   gl_TessLevelOuter[1] = tessLevelOuter;
   gl_TessLevelOuter[2] = tessLevelOuter;
   gl_TessLevelInner[0] = tessLevelInner;
   gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
   Colors_CS_ES[gl_InvocationID] = Color_VS_CS[gl_InvocationID];
   Normal_CS_ES[gl_InvocationID] = Normal_VS_CS[gl_InvocationID];
   UVMap_CS_ES[gl_InvocationID] = UVMap_VS_CS[gl_InvocationID];
   vec3 f3B003 = gl_in[0].gl_Position.xyz;
   vec3 f3B030 = gl_in[1].gl_Position.xyz;
   vec3 f3B300 = gl_in[2].gl_Position.xyz;
   vec3 f3N002 = Normal_VS_CS[0].xyz;
   vec3 f3N020 = Normal_VS_CS[1].xyz;
   vec3 f3N200 = Normal_VS_CS[2].xyz;
   f3B210 = ( ( 2.0f * f3B003 ) + f3B030 - ( dot( ( f3B030 - f3B003 ), f3N002 ) * f3N002 ) ) / 3.0f;
   f3B120 = ( ( 2.0f * f3B030 ) + f3B003 - ( dot( ( f3B003 - f3B030 ), f3N020 ) * f3N020 ) ) / 3.0f;
   f3B021 = ( ( 2.0f * f3B030 ) + f3B300 - ( dot( ( f3B300 - f3B030 ), f3N020 ) * f3N020 ) ) / 3.0f;
   f3B012 = ( ( 2.0f * f3B300 ) + f3B030 - ( dot( ( f3B030 - f3B300 ), f3N200 ) * f3N200 ) ) / 3.0f;
   f3B102 = ( ( 2.0f * f3B300 ) + f3B003 - ( dot( ( f3B003 - f3B300 ), f3N200 ) * f3N200 ) ) / 3.0f;
   f3B201 = ( ( 2.0f * f3B003 ) + f3B300 - ( dot( ( f3B300 - f3B003 ), f3N002 ) * f3N002 ) ) / 3.0f;
   vec3 f3E = ( f3B210 + f3B120 + f3B021 + f3B012 + f3B102 + f3B201 ) / 6.0f;
   vec3 f3V = ( f3B003 + f3B030 + f3B300 ) / 3.0f;
   f3B111 = f3E + ( ( f3E - f3V ) / 2.0f );
   float fV12 = 2.0f * dot( f3B030 - f3B003, f3N002 + f3N020 ) / dot( f3B030 - f3B003, f3B030 - f3B003 );
   f3N110 = normalize( f3N002 + f3N020 - fV12 * ( f3B030 - f3B003 ) );
   float fV23 = 2.0f * dot( f3B300 - f3B030, f3N020 + f3N200 ) / dot( f3B300 - f3B030, f3B300 - f3B030 );
   f3N011 = normalize( f3N020 + f3N200 - fV23 * ( f3B300 - f3B030 ) );
   float fV31 = 2.0f * dot( f3B003 - f3B300, f3N200 + f3N002 ) / dot( f3B003 - f3B300, f3B003 - f3B300 );
   f3N101 = normalize( f3N200 + f3N002 - fV31 * ( f3B003 - f3B300 ) );
}

Have you please a very more basic example that display the first levels of a Sierpinski triangle with a tesselation shader for example ?

For example, how adapt this basic sample found at http://www.cis.scu.edu.tw/~chiang/course/CG/ProgramNotes/SourceProgram/gasket2.c for to use tesselation shaders for the handle of triangle subdivisions ?

gcc gasket2.c -o gasket2 -lGL -lm -lglut -lGLU

/* gasket2.c */

/* E. Angel, Interactive Computer Graphics /
/
A Top-Down Approach with OpenGL, Third Edition /
/
Addison-Wesley Longman, 2003 */

/* Recursive subdivision of triangle to form Sierpinski gasket */

#include <GL/glut.h>

typedef float point2[2];

/* initial triangle */

point2 v[]={{-1.0, -0.58}, {1.0, -0.58}, {0.0, 1.15}};

int n;

void triangle( point2 a, point2 b, point2 c)

/* display one triangle */
{
glBegin(GL_TRIANGLES);
glVertex2fv(a);
glVertex2fv(b);
glVertex2fv©;
glEnd();
}

void divide_triangle(point2 a, point2 b, point2 c, int m)
{

/* triangle subdivision using vertex numbers */

point2 v0, v1, v2;
int j;
if(m&gt;0) 
{
    for(j=0; j&lt;2; j++) v0[j]=(a[j]+b[j])/2;
    for(j=0; j&lt;2; j++) v1[j]=(a[j]+c[j])/2;
    for(j=0; j&lt;2; j++) v2[j]=(b[j]+c[j])/2;
    divide_triangle(a, v0, v1, m-1);
    divide_triangle(c, v1, v2, m-1);
    divide_triangle(b, v2, v0, m-1);
}
else(triangle(a,b,c)); /* draw triangle at end of recursion */

}

void display(void)
{

glClear(GL_COLOR_BUFFER_BIT);
divide_triangle(v[0], v[1], v[2], n);
glFlush();

}

void myinit()
{

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-2.0, 2.0, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
glClearColor (1.0, 1.0, 1.0, 1.0);
glColor3f(0.0,0.0,0.0);

}

void
main(int argc, char **argv)
{
n=4;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize(500, 500);
glutCreateWindow(“3D Gasket”);
glutDisplayFunc(display);
myinit();
glutMainLoop();
}

You don’t need tessellation shaders to hardware-accelerate that.
You can do it with geometry shaders and transform feedback, circa 2007:
http://developer.download.nvidia.com/SDK/10.5/opengl/samples.html#transform_feedback_fractal

Thanks, Arekkusu

The difference between Tesselation and Geometry shaders is that tesselation shaders have a fixed number of vertex in output and geometry shaders doesn’t have this limitation ?

Or the difference between this two types of shaders is about another thing ?

For Geometry shaders, I have found a tutorial that seem me very good at http://cirl.missouri.edu/gpu/glsl_lessons/glsl_geometry_shader/index.html
=> when I see how is make the Geometry shader into this tuto, I think that I can make alls computations on it (n is only equal to 4 so with a little chance, alls the 4 iterations can perhaps to be “unfactorised” and all this contained into a single Geometry shader)

After some reading, I begin with geometry shader (that I don’t find very hard to understand) and see after (but very very after) with tesselation shaders (because this seem me really more difficult to handle) :slight_smile:

This one is quite easy to understand:
http://forums.nvidia.com/index.php?showtopic=210979

You just forgot that geometry shaders have not been designed for tessellation thus they handle it very slowly as geometry shaders are usually output bound if used incorrectly.

I don’t say it is not possible to use it for tessellation but it is not efficient for that, especially on GL3 class hardware.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.