I implemented tessellation control and evaluation shaders in OpenGL, but the effect it has on my terrain was not what I expected.
I expected that the low poly-count curves and shapes on the terrain would be smoothed out with new vertices between the old ones but instead I get the effect shown below.
This tessellation seems to simply create a high poly-count version of the exact same model with no difference in shape.
How do I remedy this, or am I misunderstanding the purpose of tessellation?
Without Tessellation
With Tessellation
Tessellation Control Shader
#version 450
layout(vertices = 3) out;
in VS_OUT {
vec3 normal;
} tesc_in[];
out TESC_OUT {
vec3 normal;
} tesc_out[];
uniform vec3 view_position;
/* Return level of tessellation based on distance */
float tess_level(vec4 pos1, vec4 pos2) {
const float d = distance(pos1, pos2);
if(d < 0.5) { return 25; }
if(d < 1.0) { return 20; }
if(d < 1.5) { return 15; }
if(d < 2.0) { return 10; }
if(d < 2) { return 5; }
if(d < 3) { return 2; }
return 1;
}
float tess_level(vec3 pos1, vec3 pos2) {
return tess_level(vec4(pos1, 1.0), vec4(pos2, 1.0));
}
/* Sets tessellation levels */
void set_LoD() {
vec4 d1 = vec4(gl_in[1].gl_Position.xyz + (gl_in[2].gl_Position.xyz - gl_in[1].gl_Position.xyz) / 2, 1.0);
vec4 d2 = vec4(gl_in[0].gl_Position.xyz + (gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz) / 2, 1.0);
vec4 d3 = vec4(gl_in[0].gl_Position.xyz + (gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz) / 2, 1.0);
vec4 view_position_v4 = vec4(view_position, 1.0);
float e0 = tess_level(d1, view_position_v4);
float e1 = tess_level(d2, view_position_v4);
float e2 = tess_level(d3, view_position_v4);
float m = min(e0, min(e1, e2));
gl_TessLevelInner[0] = floor((min(e0, min(e1, e2)) + max(e0, max(e1, e2))) / 2);
gl_TessLevelOuter[0] = e0;
gl_TessLevelOuter[1] = e1;
gl_TessLevelOuter[2] = e2;
}
void main() {
if(gl_InvocationID == 0) {
set_LoD();
}
tesc_out[gl_InvocationID].normal = tesc_in[gl_InvocationID].normal;
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
Tessellation Evaluation Shader
#version 450
layout(triangles, fractional_even_spacing, ccw) in;
in TESC_OUT {
vec3 normal;
} tesc_in[];
out TESE_OUT {
vec3 normal;
float height;
vec4 shadow_position;
} tesc_out;
uniform mat4 model_view;
uniform mat4 model_view_perspective;
uniform mat3 normal_matrix;
uniform mat4 depth_matrix;
vec3 lerp(vec3 v0, vec3 v1, vec3 v2) {
return (
(vec3(gl_TessCoord.x) * v0) +
(vec3(gl_TessCoord.y) * v1) +
(vec3(gl_TessCoord.z) * v2)
);
}
vec4 lerp(vec4 v0, vec4 v1, vec4 v2) {
return (
(vec4(gl_TessCoord.x) * v0) +
(vec4(gl_TessCoord.y) * v1) +
(vec4(gl_TessCoord.z) * v2)
);
}
void main() {
gl_Position = lerp(
gl_in[0].gl_Position,
gl_in[1].gl_Position,
gl_in[2].gl_Position
);
tesc_out.normal = normal_matrix * lerp(
tesc_in[0].normal,
tesc_in[1].normal,
tesc_in[2].normal
);
tesc_out.height = gl_Position.y;
tesc_out.shadow_position = depth_matrix * gl_Position;
gl_Position = model_view_perspective * gl_Position;
}

