Rendering and rotating tetrahedron triangles in 3D


EDIT: SOLVED
In my vertex shader, I did
my_rotation2(my_rotation(position, t), t).xyw
instead of
my_rotation2(my_rotation(position, t), t).xyz
The W instead of the Z obviously messed some stuff up…

All in all, a silly, discouraging typo :wink:
Back to more learning…


Hi OpenGL forum,

I am learning OpenGL and have just started 3D stuff.
Previously I had done a few small 2D things, so the z axis has not been a concern.
I am partially using Edward Angel’s book on OpenGL among other resources, but trying to inject my own modifications to better learn the material. Angel’s book describes rendering a cube. I am trying something a bit more simple, a tetrahedron.
OpenGL specs at bottom of post.

I have searched through the forum, but can’t really find my exact problem.
Here is my issue:
I am drawing a tetrahedron using a set of 4 triangles. I have GL_DEPTH_TEST enabled, but OpenGL still decides to draw some triangles on top of others even when it shouldn’t.
Image attached at bottom.

Here is the list of points and vertex colors:

[code=cpp]
using vec4 = glm::vec4;
vec4 tetra_vertices[4] = {
vec4(-1.0, -1.0, -1.0, 1.0), // base bottom-left point
vec4( 0.0, 1.0, -1.0, 1.0), // base top point
vec4( 1.0, -1.0, -1.0, 1.0), // base right point
vec4( 0.0, 0.0, 1.0, 1.0)}; // tip point
vec4 tetra_colors[4] = {
vec4( 1.0, 1.0, 1.0, 1.0),
vec4( 1.0, 0.0, 0.0, 1.0),
vec4( 0.0, 1.0, 0.0, 1.0),
vec4( 0.0, 0.0, 1.0, 1.0)};


I populate my class's m_vertices and m_colors using
[code=cpp]
void Tetra::tri(int a, int b, int c)
{
    static int i = 0;
    m_vertices[i]   = tetra_vertices[a];
    m_vertices[i+1] = tetra_vertices[b];
    m_vertices[i+2] = tetra_vertices[c];
    m_colors[i]   = tetra_colors[a];
    m_colors[i+1] = tetra_colors[b];
    m_colors[i+2] = tetra_colors[c];
    i += 3;
}
// CTOR:
    tri(0, 1, 2); // bottom face, facing down
    tri(0, 3, 1);
    tri(1, 3, 2);
    tri(0, 2, 3);

where the number is the index of the tetra_* array.

Here is how I send the data to OpenGL:

[code=cpp]
void Tetra::send_to_GPU() const
{
// TODO: Have size set beforehand, i += 2 each time
std::vector render_vertices;
for (int i = 0; i < (3+3)*4; i++)
{
render_vertices.push_back(m_vertices[i]);
render_vertices.push_back(m_colors[i]);
}

const GLsizeiptr BufferSize = render_vertices.size()*sizeof(vec4);

GLuint vertexBufferID;
glGenBuffers(1, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, BufferSize, render_vertices.data(), GL_DYNAMIC_DRAW);

// just setting the offsets for {XYZW, RGBA, XYZW, RGBA} vec3 order
glEnableVertexAttribArray(Attrib_Position);
glVertexAttribPointer(Attrib_Position, XYZW, GL_FLOAT, GL_FALSE,
                      XYZW_RGBA_Stride, 0);

glEnableVertexAttribArray(Attrib_Color);
glVertexAttribPointer(Attrib_Color, RGBA, GL_FLOAT, GL_FALSE,
                      XYZW_RGBA_Stride, XYZW_RGBA_ColorOffset);

}


Here is how I draw my tetrahedron every frame:
[code=cpp]
    Tetra tetra;
    tetra.send_to_GPU();

    GLint timeParam = glGetUniformLocation(shader.getProgram(), "t");
    GLfloat t       = 0.0f;
    GLfloat t_delta = 0.01f;

    glEnable(GL_DEPTH_TEST);

    // Main Window Loop:
    while(window.isOpen())
    {
        //Edited event stuff out

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0, 0, window.getSize().x, window.getSize().y);

        shader.bind(); // simply calls glUseProgram
        glUniform1f(timeParam, t); // allows dynamic rotation

        t += t_delta;
        if (t > 2*3.1415926535)
            t -= 2*3.1415926535;

        //tetra.draw(); // simply calls:
        glDrawArrays(GL_TRIANGLES, 0, 4*3);

        glFlush();
        window.display();

    }

Here is my vertex shader, it also handles the rotations:

[code=cpp]
#version 430

vec4 my_rotation(vec4 v, float radians)
{
float temp_x = v.x;
float costh = cos(radians);
float sinth = sin(radians);

return vec4 (
    costh*temp_x + -sinth*v.y,
    sinth*temp_x +  costh*v.y,
    v.z,
    v.w     );

}
vec4 my_rotation2(vec4 v, float radians)
{
float temp_z = v.z;
float costh = cos(radians);
float sinth = sin(radians);

return vec4 (
    v.x,
    sinth*temp_z +  costh*v.y,
    costh*temp_z + -sinth*v.y,
    v.w     );

}

in layout(location=0) vec4 position;
in layout(location=1) vec4 vertexColor;
uniform float t;
out vec4 theColor;

void main()
{
gl_Position = vec4(0.5*my_rotation2(my_rotation(position, t), t).xyw, 1.0);

// pass data, for fragment shader    
theColor = vertexColor;                 

}


Here is my fragment shader:
[code=cpp]
#version 430

in vec4 theColor; // must be same name as .vert
out vec4 color;
void main()
{
    color = theColor;
}

SORRY I know that’s a lot of code to post.
Having a complete and minimal example would be time-consuming, but if someone wants I could take the time to make one.

I am on Windows 7, using OpenGL 4.3 (with SFML for window, glew for context).


GL Vendor : NVIDIA Corporation
GL Renderer : GeForce GT 555m/PCIe/SSE2
GL Version (string): 4.3.0
GL Version (integer) 4.3
GLSL Version: 4.30 NVIDIA via Cg compiler

Isn’t glEnable(GL_DEPTH_TEST) enough to make it correctly sort?