I'm working on a program where I need to make spheres. My chosen method is to create an octahedron
https://i.stack.imgur.com/xHpcm.png[
^]
and through tessellation shaders, subdividing it and then normalizing the coordinates into an octa sphere (sphere created from tessellating an octahedron). However, my problem is this is only partially working as shown below, and I want a full sphere instead of a 80% sphere. Oh and it's not just when it's in sphere form. This is when I stop normalizing the uvw coordinates of the octahedron
https://i.stack.imgur.com/v1SB0.png[
^
https://i.stack.imgur.com/BXmpD.png
Below is my tessellation eval shader (GLSL)
#version 450 core
layout(triangles, equal_spacing, cw) in;
in vec3 vertex_coord[];
out vec3 vert;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
vec3 u = gl_TessCoord.x * vertex_coord[0];
vec3 v = gl_TessCoord.y * vertex_coord[1];
vec3 w = gl_TessCoord.z * vertex_coord[2];
vec3 pos = normalize(u + v + w);
gl_Position = projection * view * model * vec4(pos, 1.0);
}
and my tessellation control shader, also GLSL
#version 450 core
layout(vertices=3) out;
in vec3 vert_coord[];
out vec3 vertex_coord[];
uniform mat4 view;
uniform mat4 model;
void main()
{
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];
if(gl_InvocationID==0)
{
const float MIN_TESS_LEVEL = 4;
const float MAX_TESS_LEVEL = 64;
const float MIN_DISTANCE = 20;
const float MAX_DISTANCE = 800;
vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;
vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;
vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;
float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);
float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);
float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);
float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));
float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));
float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));
gl_TessLevelOuter[0] = tess_level_1;
gl_TessLevelOuter[1] = tess_level_2;
gl_TessLevelOuter[2] = tess_level_3;
gl_TessLevelInner[0] = max(tess_level_1, tess_level_3);
gl_TessLevelInner[1] = max(tess_level_2, tess_level_1);
}
}
my vertex shader
#version 450 core
layout (location = 0) in vec3 pos;
out vec3 vert_coord;
void main()
{
gl_Position = vec4(pos, 1.0f);
vert_coord = pos;
}
My octahedron vertices and indices
float vertices[] = {
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, -1.0f,
-1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f,
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
-1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, -1.0f,
1.0f, 0.0f, 0.0f
};
unsigned int indices[] = {
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
18, 19, 20,
21, 22, 23
};
And my buffers and draw calls
unsigned int vbo, vao, ebo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glPatchParameteri(GL_PATCH_VERTICES, 3);
glBindVertexArray(vao);
glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);
What I have tried:
Scoured the internet for weeks, changed around all shaders, vertices, math, tried this with different shapes such as cubes, icosahedrons, dodecahedrons, UV spheres (spheres generated on the CPU then uploaded to the GPU) and also asked around several different forums, used any and every single computer graphics debugger (like Render Doc), compared my sphere code with at least 50 other code bases, asked professional graphics programmers through DM's and stuff, pretty much anything and everything I tried before this.