Chapter 8 page 304

Bezier Surfaces - Tessellation Shaders
supplement to Ch 8
in display():
gl.glPatchParameteri(GL_PATCH_VERTICES, 16);
gl.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // FILL or LINE
gl.glDrawArrays(GL_PATCHES, 0, 16);
Vertex shader:
#version 430 core
out vec2 tc;
uniform mat4 mvp;
// out vertex attributes are scalars
void main(void)
{ // cubic bezier patch is 16 control points
const vec4 vertices[] =
vec4[] (vec4(-1.0, 0.5, -1.0, 1.0), vec4(-0.5, 0.5, -1.0, 1.0),
vec4( 0.5, 0.5, -1.0, 1.0), vec4( 1.0, 0.5, -1.0, 1.0),
vec4(-1.0, 0.0, -0.5, 1.0), vec4(-0.5, 0.0, -0.5, 1.0),
vec4( 0.5, 0.0, -0.5, 1.0), vec4( 1.0, 0.0, -0.5, 1.0),
vec4(-1.0, 0.0, 0.5, 1.0), vec4(-0.5, 0.0, 0.5, 1.0),
vec4( 0.5, 0.0, 0.5, 1.0), vec4( 1.0, 0.0, 0.5, 1.0),
vec4(-1.0, -0.5, 1.0, 1.0), vec4(-0.5, 0.3, 1.0, 1.0),
vec4( 0.5, 0.3, 1.0, 1.0), vec4( 1.0, 0.3, 1.0, 1.0));
Tessellation Evaluation shader:
#version 430
layout (quads, equal_spacing, ccw) in;
uniform mat4 mvp;
in vec2 tcs_out[];
// in vertex attributes are arrays
out vec2 tes_out;
// out vertex attributes are scalars
void main (void)
{ vec3 p00 = (gl_in[0].gl_Position).xyz; // control points, from TCS
vec3 p10 = (gl_in[1].gl_Position).xyz;
vec3 p20 = (gl_in[2].gl_Position).xyz;
vec3 p30 = (gl_in[3].gl_Position).xyz;
vec3 p01 = (gl_in[4].gl_Position).xyz;
vec3 p11 = (gl_in[5].gl_Position).xyz;
vec3 p21 = (gl_in[6].gl_Position).xyz;
vec3 p31 = (gl_in[7].gl_Position).xyz;
vec3 p02 = (gl_in[8].gl_Position).xyz;
vec3 p12 = (gl_in[9].gl_Position).xyz;
vec3 p22 = (gl_in[10].gl_Position).xyz;
vec3 p32 = (gl_in[11].gl_Position).xyz;
vec3 p03 = (gl_in[12].gl_Position).xyz;
vec3 p13 = (gl_in[13].gl_Position).xyz;
vec3 p23 = (gl_in[14].gl_Position).xyz;
vec3 p33 = (gl_in[15].gl_Position).xyz;
// grid coordinates from tessellator processed one at a time
float u = gl_TessCoord.x ;
float v = gl_TessCoord.y ;
// build terrain coordinates by moving to range [0,1]
tc = vec2((vertices[gl_VertexID].x + 1.0)/2.0,
(vertices[gl_VertexID].z + 1.0)/2.0);
// cubic Bezier weighting functions
float bu0 = (1.0-u) * (1.0-u) * (1.0-u);
float bu1 = 3.0 * u * (1.0-u) * (1.0-u);
float bu2 = 3. * u * u * (1.0-u);
float bu3 = u * u * u;
float bv0 = (1.0-v) * (1.0-v) * (1.0-v);
float bv1 = 3.0 * v * (1.0-v) * (1.0-v);
float bv2 = 3. * v * v * (1.0-v);
float bv3 = v * v * v;
// send control points to the TCS
gl_Position = vertices[gl_VertexID];
}
Tessellation Control Shader:
#version 430 core
in vec2 tc[];
out vec2 tcs_out[];
uniform float uOuter02;
uniform float uOuter13;
uniform float uInner0;
uniform float uInner1;
// vertex attributes are now arrays
vec3 outputPosition =
bu0 * ( bv0*p00 + bv1*p01 + bv2*p02 + bv3*p03 )
+ bu1 * ( bv0*p10 + bv1*p11 + bv2*p12 + bv3*p13 )
+ bu2 * ( bv0*p20 + bv1*p21 + bv2*p22 + bv3*p23 )
+ bu3 * ( bv0*p30 + bv1*p31 + bv2*p32 + bv3*p33 );
gl_Position = mvp * vec4(outputPosition,1.0f);
// patch tesselation levels
// (get from application)
// also output the interpolated texture coordinates
vec2 tc1 = mix(tcs_out[0], tcs_out[3], gl_TessCoord.x);
vec2 tc2 = mix(tcs_out[12], tcs_out[15], gl_TessCoord.x);
vec2 tc = mix(tc2, tc1, gl_TessCoord.y);
tes_out = tc;
layout (vertices = 16) out;
void main(void)
{ // tessellation levels sent to the tessellator
gl_TessLevelOuter[0] = uOuter02;
gl_TessLevelOuter[2] = uOuter02;
gl_TessLevelOuter[1] = uOuter13;
gl_TessLevelOuter[3] = uOuter13;
gl_TessLevelInner[0] = uInner0;
gl_TessLevelInner[1] = uInner1;
// forward the position for this control point to the TES
gl_out[gl_InvocationID].gl_Position =
gl_in[gl_InvocationID].gl_Position;
// also forward the texture coordinates
tcs_out[gl_InvocationID] = tc[gl_InvocationID];
}
// (1-u)^3
// 3u(1-u)^2
// 3u^2(1-u)
// u^3
// (1-v)^3
// 3v(1-v)^2
// 3v^2(1-v)
// v^3
}
Fragment Shader:
#version 430 core
in vec2 tes_out;
out vec4 color;
layout (binding = 0) uniform sampler2D tex_color;
void main(void)
{ color = texture2D(tex_color, tes_out);
}