0

I recently faced a problem I still cannot overcome for the reason I don't understand its nature.

I created a sphere, assigned vertices and normals and indices and built DSA vao (Opengl 4.5). Having rendered, I found out that quad borders are highlighted: the diffuse color seemed to spread normally but the quads themselves have slightly visible lightened edges.

I excluded most of the shader and cut to passing to fragment shader normals as color and got this:

5 by 5 sphere

Sphere creation:

float sectorStep = 2.0f * glmpi / sphereX;
float stackStep = glmpi / sphereY;
float piByTwo = glmpi / 2.0f;
float sectorAngle, stackAngle;
float x, y, z, xy;
float limit = 0.000000001f;

// building up basic sphere vertices, arrayed to slots_horizontal + 1 by slots_vertical + 1 vertices
for (int i = 0; i <= sphereY; ++i)
{
    stackAngle = /*glmpi / 2.0f*/piByTwo - i * stackStep; // starting from pi/2 to -pi/2
    xy = cosf(stackAngle); // r * cos(u)
    z = sinf(stackAngle); // r * sin(u)


    float xf, yf;
    for (int j = 0; j <= sphereX; ++j)
    {
        sectorAngle = j * sectorStep; // starting from 0 to 2pi

        // vertex position (x, y, z)
        x = xy * cosf(sectorAngle); // r * cos(u) * cos(v)
        y = xy * sinf(sectorAngle); // r * cos(u) * sin(v)

        struct_vertex_pos_normal vert(axv3(x, y, z), norma(axv3(x, y, z)));
        vertices_sphere_smooth.push_back(vert);
    };
};

DSA objects built:

// allocate and fill vertices buffer
glCreateBuffers(1, &vbo);
glNamedBufferStorage(vbo, sizeof(struct_vertex_pos_normal) * vertecis.size(), vertecis.data(), GL_DYNAMIC_STORAGE_BIT);

// allocate and fill indices buffer
glCreateBuffers(1, &ibo);
glNamedBufferStorage(ibo, sizeof(uint) * indices.size(), indices.data(), GL_DYNAMIC_STORAGE_BIT);

// create font vao and set its vbo and ibo parameters
glCreateVertexArrays(1, &vao);
glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(struct_vertex_pos_normal)); // connect font_vbo to binding point 0
glVertexArrayElementBuffer(vao, ibo);

// enable color and uv attributes for the font vao
glEnableVertexArrayAttrib(vao, 0);
glEnableVertexArrayAttrib(vao, 1);

glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, offsetof(struct_vertex_pos_normal, position)); // offset in BYTES
glVertexArrayAttribFormat(vao, 1, 3, GL_FLOAT, GL_TRUE, offsetof(struct_vertex_pos_normal, normal)); // offset in BYTES

// connect color (0) and uv (1) attribute with the buffer binded to binding point 0: font_vbo
glVertexArrayAttribBinding(vao, 0, 0);
glVertexArrayAttribBinding(vao, 1, 0);

Vertex shader:

const char* d3vbo_sphere_VS = {
    "#version 430 core\n"

    "layout (location = 0) uniform mat4 uniform_modelmatrix;\n"
    "layout (location = 1) uniform vec4 uniform_color;\n"
    "layout (location = 2) uniform mat4 uniform_normalmatrix;\n"

    "layout (location = 0) in vec3 vbo_pos;\n"
    "layout (location = 1) in vec3 vbo_normal;\n"

    // camera ubo, binding 0
    "layout(std140, binding = 0) uniform ubo_main {\n"
    "   mat4 ubo_global_cameraMat4;\n"
    "   mat4 ubo_global_orthographicProjectionMat4;\n"
    "   mat4 ubo_global_perspectiveProjectionMat4;\n"
    "};\n"

    "out vec3 space_pos;\n"
    "out vec3 normal;\n"

    "void main()\n"
    "{\n"
    "   gl_Position = ubo_global_perspectiveProjectionMat4 * ubo_global_cameraMat4 * uniform_modelmatrix * vec4(vbo_pos, 1.0f);\n"
    "   space_pos = vec3(uniform_modelmatrix * vec4(vbo_pos, 1.0));"
    "   normal = vbo_normal; \n"
    "}\n" };

Fragment:

const char* d3vbo_sphere_FS = {
    "#version 430 core \n"

    "layout (location = 0) uniform mat4 uniform_modelmatrix;\n"
    "layout (location = 1) uniform vec4 uniform_color;\n"
    "layout (location = 2) uniform mat4 uniform_normalmatrix;\n"

    // camera ubo, binding 0
    "layout(std140, binding = 0) uniform ubo_main {\n"
    "   mat4 ubo_global_cameraMat4;\n"
    "   mat4 ubo_global_orthographicProjectionMat4;\n"
    "   mat4 ubo_global_perspectiveProjectionMat4;\n"
    "};\n"

    // lights ubo, binding 1
    "layout(std140, binding = 1) uniform ubo_lights\n" 
    "{\n"
    "   vec4 ubo_light_ambient;\n" // xyz - color, w - sensitivity
    "   vec4 ubo_light_diffuse;\n" // xyz - color, w - sensitivity
    "   vec4 ubo_light_diffuse_position;\n" // xyz - position, w - padded
    "};\n"

    "in vec3 space_pos;\n"
    "in vec3 normal;\n"

    "out vec4 color; \n"

    "void main() \n"

    "{ \n"

    "   color = vec4(abs(normal), 1.0f); \n" // uniform_color; \n"

    "}; \n" };

As I can see the lightning effect is an issue with the normals. But I cant get the point why - might it be just a normal behaviour? Because I see the same effect while rendering a cube. Lets say Blender renders smoothed meshes without this kind of edges.

Video card: Inter(R) Iris(R) Graphics family

Another PC with Intel videocard produce the same results...

1
  • FWIW it's a fundamental artifact of the technique of interpolating vertex normals linearly (a.k.a. Gouraud shading). See the image at stackoverflow.com/a/63958763/1563833 Commented Apr 27 at 21:07

1 Answer 1

1

Looking at your code and the visual artifacts you're seeing, this is likely caused by the way normals are being interpolated across triangular faces. Here are several potential issues and solutions:

Normal calculation: While your normal calculation looks correct for a unit sphere, ensure that normals are properly normalized. Try modifying your normal calculation:

// Instead of just using the position, explicitly normalize
axv3 position(x, y, z);
axv3 normal = normalize(position);  // Make sure normals are unit vectors
struct_vertex_pos_normal vert(position, normal);

Normalization in fragment shader: Even if normals are normalized per-vertex, they should be re-normalized in the fragment shader after interpolation

void main() 
{ 
    vec3 normalized_normal = normalize(normal);
    color = vec4(abs(normalized_normal), 1.0f);
}

The most likely culprit is that normals need to be re-normalized in the fragment shader. The interpolation process can cause them to lose their unit length, creating visible artifacts at triangle boundaries.

Sign up to request clarification or add additional context in comments.

2 Comments

Awsome hint about the re-normalizing in the fragment shader, mate. The "ribs" got removed! Thanks a lot, will keep this fact! <3
Glad it worked!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.