Search code examples
c++openglglslshadertessellation

What can I do to position the new vertices from my Tessellation Evaluation Shader into a sphere?


I am about a quarter and a half away from the solution; I am able to generate one of the eight octants of a sphere using a tessellation evaluation shader, but I am unable to orient them in the correct way.

Here is the code for my first attempt. I figured out that the normalized tessellation coordinate is important to repositioning the new vertices along the circumference of a sphere, but I cannot for the life of me figure out how to position and orient these quarter spheres correctly.

#version 460 core

// Triangles
layout (triangles, equal_spacing , ccw) in;
layout(location = 0) uniform mat4 modelMatrix;
layout(location = 1) uniform mat4 camMatrix;

void main()
{
    vec3 pos = normalize(gl_TessCoord);

    gl_Position = camMatrix * modelMatrix * vec4(pos, 1.f);
}

The resulting quarter sphere (A "single" quarter sphere, but it's actually all of the quarters stacked on one another):

Image

Here is the code for my second attempt. I am getting closer to the solution because the quarters are adjusted to their correct locations, but they are still not oriented correctly to form a sphere.

#version 460 core

// Triangles
layout (triangles, equal_spacing , ccw) in;
layout(location = 0) uniform mat4 modelMatrix;
layout(location = 1) uniform mat4 camMatrix;


void main()
{
    vec4 pos0 = gl_in[0].gl_Position;
    vec4 pos1 = gl_in[1].gl_Position;
    vec4 pos2 = gl_in[2].gl_Position;

    vec3 pos = normalize(gl_TessCoord) + pos0.xyz + pos1.xyz +pos2.xyz;

    gl_Position = camMatrix * modelMatrix * vec4(pos, 1.f);
}

The resulting quarter spheres are now located in their respective positions, but they are not oriented correctly.Sphere quarters are now in their correct locations but are not oriented right:

image

I hope that the lack of color contrast doesn't make the images too difficult to see. I have yet to add a light source to the scene, as I would like to get the spheres generating properly first.


Solution

  • I suppose my total failure to find the solution yesterday was the result of a long day of coding and a lotta bit of doy-ness.

    So, after a getting a good night's sleep, I took another look at the problem with fresh eyes. This time around, I played with the normalization function and applied it to every possible vector that would take it, and I found that the solution was to just multiply the triangle vertex vectors by the tessellated triangle vertex coordinates (to put the new primitives in their respective octants) and then normalize the sum (to make the vectors lie on a sphere).

    The tessellation evaluation shader code looks as follows:

    #version 460 core
    
    // Triangles
    layout (triangles, equal_spacing , ccw) in;
    layout(location = 0) uniform mat4 modelMatrix;
    layout(location = 1) uniform mat4 camMatrix;
    
    void main()
    {
        vec3 TC  = gl_TessCoord;
        vec4 pos0 = gl_in[0].gl_Position;
        vec4 pos1 = gl_in[1].gl_Position;
        vec4 pos2 = gl_in[2].gl_Position;
    
        vec3 pos = normalize( TC.x * pos0.xyz + TC.y * pos1.xyz + TC.z * pos2.xyz);
    
        gl_Position = camMatrix * modelMatrix * vec4(pos, 1.f);
    }
    

    For those tuning in, the camMatrix is a product of the view and projection matrices, so that the tessellated sphere has a dynamic level of detail.

    The dynamic LOD can be seen as follows: Minimum tessellation at long distance

    Moderate tessellation at medium distance

    Maximum tessellation at close distance

    Overall, I am very happy with the results. The tessellation amount can be edited in the tessellation control shader, as well as the minimum and maximum distances for the tessellation.

    Sometimes the solution is just waiting behind the door of tomorrow!