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

Time:12-20

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.

CodePudding user response:

What is input to your shaders what are you rendering a single triangle? placed where in respect to sphere? what exactly is in gl_TessCoord ? I asume output from tesselation shader however you shared only vertex shaders ...

Looks like you are offsetting the octant instead of mirroring! What you should do is just negate the coordinates (all 7 combinations so to get one octant you just multiply the position by (-1, 1, 1) ... another octant is multiplied by ( 1,-1, 1) and so on until last octant is multiplied by (-1,-1,-1) no offsetting at all if you have integer number of octant i then its lowest 3 bits represent which axis to negate ... putting all together:

#version 460 core

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

void main()
{
    vec3 pos = normalize(gl_TessCoord);
    if ((octant&1)!=0) pos.x=-pos.x;
    if ((octant&2)!=0) pos.y=-pos.y;
    if ((octant&4)!=0) pos.z=-pos.z;

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

Beware did not test this and not sure if bit operations like this are allowed in GLSL however to do this branchlessly you could simply pass the multiplication vec3 as uniform holding these values for the original octant and its 7 mirrors:

octant0:( 1.0, 1.0, 1.0)
octant1:(-1.0, 1.0, 1.0)
octant2:( 1.0,-1.0, 1.0)
octant3:(-1.0,-1.0, 1.0)
octant4:( 1.0, 1.0,-1.0)
octant5:(-1.0, 1.0,-1.0)
octant6:( 1.0,-1.0,-1.0)
octant7:(-1.0,-1.0,-1.0)

and just multilply the pos with it instead of those 3 if expressions ...

CodePudding user response:

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!

  • Related