Search code examples
c++openglglslglfwglm-math

How to draw a line along the Z axis in openGL


I'm stuck drawing a line along the Z-axis. I have checked the related topic that OpenGL Can't draw z axis but even if I change my camera position, I still can't see my line; meanwhile, I can see a square draw in XZ-plane.

here is my code:

int main()
{
    glfwInit();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);

    GLFWwindow* window = glfwCreateWindow(1024, 768, "some program", NULL, NULL);

    glfwMakeContextCurrent(window);

    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        std::cerr << "Failed to create GLEW" << std::endl;
        glfwTerminate();
        return -1;
    }

    glClearColor(0.2f, 0.298f, 0.298f, 1.0f);

    // Compile and link shaders here ...
    int shaderProgram = compileAndLinkShaders();

    int lineVao = createLineVertexArrayObject(LineArray, sizeof(LineArray));

    while (!glfwWindowShouldClose(window))
    {
        GLuint worldMatrixLocation = glGetUniformLocation(shaderProgram, "worldMatrix");
        // Each frame, reset color of each pixel to glClearColor
        glClear(GL_COLOR_BUFFER_BIT);
        glm::mat4 translationMatrix = glm::mat4(1.0f);
        glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, &translationMatrix[0][0]);

        glUseProgram(shaderProgram);

        glBindVertexArray(lineVao);

        glDrawArrays(GL_LINES, 0, 2);

        glBindVertexArray(0);

        glfwSwapBuffers(window);

        // Detect inputs
        glfwPollEvents();


        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);

        if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS)//see the object in other direction
        {
            glm::mat4 viewMatrix = glm::lookAt(glm::vec3(0.0f, 1.0f, 0.0f),  // eye
                glm::vec3(0.0f, 0.0f, -1.0f),  // center
                glm::vec3(0.0f, 1.0f, 0.0f));// up

            GLuint viewMatrixLocation = glGetUniformLocation(shaderProgram, "viewMatrix");
            glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]);
        }
    }
    // Shutdown GLFW
    glfwTerminate();
    return 0;
}

int createLineVertexArrayObject()

int createLineVertexArrayObject(const glm::vec3* vertexArray, int arraySize)
{
    // Create a vertex array
    GLuint vertexArrayObject;
    glGenVertexArrays(1, &vertexArrayObject);
    glBindVertexArray(vertexArrayObject);

    // Upload Vertex Buffer to the GPU, keep a reference to it (vertexBufferObject)
    GLuint vertexBufferObject;
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, arraySize, vertexArray, GL_STATIC_DRAW);

    glVertexAttribPointer(0,                   // attribute 0 matches aPos in Vertex Shader
        2,                   // size
        GL_FLOAT,            // type
        GL_FALSE,            // normalized?
        2 * sizeof(glm::vec3), // stride - each vertex contain 2 vec3 (position, color)
        (void*)0             // array buffer offset
    );
    glEnableVertexAttribArray(0);


    glVertexAttribPointer(1,                            // attribute 1 matches aColor in Vertex Shader
        2,
        GL_FLOAT,
        GL_FALSE,
        2 * sizeof(glm::vec3),
        (void*)sizeof(glm::vec3)      // color is offseted a vec3 (comes after position)
    );
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    return vertexArrayObject;
}

my lineArray[] was like this

glm::vec3 LineArray[] = {
        glm::vec3(-0.5f, 0.0f, -0.5f), // position
        glm::vec3(1.0f, 0.0f, 0.0f), // color (yellow)
        glm::vec3(0.0f, 0.0f, 0.0f), // position
        glm::vec3(1.0f, 0.0f, 0.0f), // color (yellow)
};

But I can only see a horizontal line if I change my camera position.


Solution

  • Assuming that you want to draw a 3D line, the size argument of glVertexAttribPointer is wrong. By setting it to two, you tell OpenGL to read only two values and add 0 for z.

    Set the size to 3 as in

    glVertexAttribPointer(0,                   // attribute 0 matches aPos in Vertex Shader
        3,                   // size
        GL_FLOAT,            // type
        GL_FALSE,            // normalized?
        2 * sizeof(glm::vec3), // stride - each vertex contain 2 vec3 (position, color)
        (void*)0             // array buffer offset
    );
    

    and the z-value will also be read.

    Note, that your color binding has the same problem. You only read the read and green value, but not the blue value.