PDA

View Full Version : Question about Tessellation Control Shader



Angela
09-18-2017, 01:53 AM
Heyy!

I've been learning about tessellation shaders recently and I got stuck implementing the Levels Of Details (LOD) technique! :sorrow:

I implemented a tessellation shader program on one of my triangles in my scene. I am trying to control the LOD where I want the quality of the triangle to drop as the camera moves farther away.

I'll just show some shaders:

Vertex Shader:

#version 430 core

// Attributes
layout (location = 0) in vec3 vertexPos;
layout (location = 1) in vec3 vertexColor;

// Output
out vec3 Color;
out float Distance; // To store the distance between the camera and the triangle

// Uniforms
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
uniform vec3 CameraPos; // Passing the camera's position from CPU
uniform vec3 TrianglePos; // Passing the triangle's position from CPU

void main()
{
Distance = distance(TrianglePos.xyz, CameraPos); // Calculating the distance using glsl's distance() function
gl_Position = Projection * View * Model * vec4(vertexPos, 1.0f); // Transform the object from model space to world space to view space...
Color = vertexColor; // Store the color...
}


Tessellation Control Shader:

#version 430 core
layout (vertices = 3) out;

in float Distance; // This is meant to hold the distance between the camera and the triangle
// Note: I'm not doing anything with it just yet

void main()
{
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 3.0;
gl_TessLevelOuter[1] = 3.0;
gl_TessLevelOuter[2] = 3.0;
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}

In the TCS above, I want to be able to adjust the tessellation based on the distance, so I was thinking maybe something like this would work...?


if (Distance > 15.0f)
{
// Adjust gl_TessLevelInner and gl_TessLevelOuter here maybe...? :confused:
} else if (Distance > 25.0f)
{
// ...
}

When I tried doing that, the triangle disappears if the distance is > 0 or even < 0, honestly, I don't even know whether the glsl's distance() function is doing the right thing or not. :(
I don't even know whether the TCS is being called every frame in order to update the adjustments I am making, but it does make sense to do these things in the TCS instead of the TES no? :confused:

Tessellation Evaluation Shader:

#version 430 core

layout (triangles, equal_spacing, cw) in;

void main()
{
gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position +
gl_TessCoord.y * gl_in[1].gl_Position +
gl_TessCoord.z * gl_in[2].gl_Position);
}

Sorry for the lengthy post, I hope someone could me understand things better. :)

Thank you!

GClements
09-18-2017, 07:54 AM
Tessellation Control Shader:


in float Distance; // This is meant to hold the distance between the camera and the triangle


Tessellation control shader inputs should be declared as arrays, as you'll get a value for each patch vertex. The number of array elements is set by glPatchParameteri(GL_PATCH_VERTICES,n); the initial value is 3.



In the TCS above, I want to be able to adjust the tessellation based on the distance, so I was thinking maybe something like this would work...?


if (Distance > 15.0f)
{
// Adjust gl_TessLevelInner and gl_TessLevelOuter here maybe...?
} else if (Distance > 25.0f)
{
// ...
}

When I tried doing that, the triangle disappears if the distance is > 0 or even < 0, honestly, I don't even know whether the glsl's distance() function is doing the right thing or not.
I don't even know whether the TCS is being called every frame in order to update the adjustments I am making, but it does make sense to do these things in the TCS instead of the TES no?

The TCS shouldn't even compile, as Distance needs to be an array.

The main thing to bear in mind when calculating tessellation levels is that for the edges which are shared between patches, the calculated outer level needs to be the same for both patches, so that the generated vertices for the shared edge match up.

For self-contained patches, this typically means that the calculation should only use the input vertices for the shared edge, so that the TCS inevitably calculates the same outer level for both patches sharing the edge. However, there are other options if you use the "adjacency" modes (GL_TRIANGLES_ADJACENCY etc) or do something similar with patches (i.e. some of the input vertices "belong" to adjacent patches).

The inner levels can use all of the input vertices.

Angela
09-19-2017, 11:16 PM
Thank you so much GClements.

I think the reason why it wasn't issuing any compilation errors is because I was using an older machine. I am able to calculate the LOD just fine now so thanks :)