c++openglglfwglu

gluLookAt() not working when using glOrtho()?


I want to use gluLookAt() to move my camera so that I can see the entire mesh (in the code is a cube).

I set ModelView matrix in the game loop. Both changing glLookAt() and gluPerspective() do nothing to the final image. I kept getting the below image.

I've tried to use glOrtho() but it was still not working...

Is this problem from shader, or the rest of the drawing code?

enter image description here

#include <GLFW/glfw3.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>

#include <iostream>
#include <fstream>

int window_width = 800, window_height = 600;

GLuint loadShader(const char *vs_path, const char *fs_path);
const char *vertexShaderSource = "#version 330 core\n"
                                 "layout (location = 0) in vec3 aPos;\n"
                                 "void main()\n"
                                 "{\n"
                                 "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
                                 "}\0";
const char *fragmentShaderSource = "#version 330 core\n"
                                   "out vec4 FragColor;\n"
                                   "void main()\n"
                                   "{\n"
                                   "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
                                   "}\n\0";

int main() {
    if (!glfwInit())
        return -1;
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    GLFWwindow* window;
    window = glfwCreateWindow(window_width, window_height, "Hello World", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // fragment shader
    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // check for shader compile errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // link shaders
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    // check for linking errors
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    float vertices[] = {
            -1, 0.0,  0.0,
            -1, 0.0,  1.0,
            -1,  1.0,  0.0,
            -1,  1.0,  1.0,
            1.0,  0.0,  0.0,
            1.0,  0.0,  1.0,
            1.0,  1.0,  0.0,
            1.0,  1.0,  1.0,
    };
    unsigned int indices[] = {
            0, 6, 4,
            0, 2, 6,
            0, 3, 2,
            0, 1, 3,
            2, 7, 6,
            2, 3, 7,
            4, 6, 7,
            4, 7, 5,
            0, 4, 5,
            0, 5, 1,
            1, 5, 7,
            1, 7, 3,
    };

    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), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

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

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    while (!glfwWindowShouldClose(window)) {
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(
                0, 0, 10,
                0, 0, 0,
                0, 1, 0);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-10, 10, -10, 10, 0.1, 10);
        glViewport(0, 0, window_width, window_height);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
        //glDrawArrays(GL_TRIANGLES, 0, 6);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        // glBindVertexArray(0); // no need to unbind it every time

        glfwSwapBuffers(window);
        glfwPollEvents();
    }


    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;

}

GLuint loadShader(const char *vs_path, const char *fs_path) {
    GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    std::string vsCode;
    std::ifstream vsStream(vs_path, std::ios::in);
    if (vsStream.is_open()) {
        std::string line;
        while (std::getline(vsStream, line)) {
            vsCode += line + "\n";
        }
        vsStream.close();
    } else {
        std::cerr << "ERROR::GUI::LOAD_SHADER::VERTEX::FILE_OPEN_FAILED\n" << std::endl;
        exit(-1);
    }

    std::string fsCode;
    std::ifstream fsStream(fs_path, std::ios::in);
    if (fsStream.is_open()) {
        std::string line;
        while (std::getline(fsStream, line)) {
            fsCode += line + "\n";
        }
        fsStream.close();
    } else {
        std::cerr << "ERROR::GUI::LOAD_SHADER::FRAGMENT::FILE_OPEN_FAILED\n" << std::endl;
        exit(-1);
    }

    int success;
    char info[1024];

    const char *vs = vsCode.c_str();
    glShaderSource(vertexShaderID, 1, &vs, NULL);
    glCompileShader(vertexShaderID);
    glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShaderID, 1024, NULL, info);
        std::cerr << "ERROR::GUI::LOAD_SHADER::VERTEX::COMPILATION_FAILED\n" << info << std::endl;
    }

    const char *fs = fsCode.c_str();
    glShaderSource(fragmentShaderID, 1, &fs, NULL);
    glCompileShader(fragmentShaderID);
    glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShaderID, 1024, NULL, info);
        std::cerr << "ERROR::GUI::LOAD_SHADER::FRAGMENT::COMPILATION_FAILED\n" << info << std::endl;
    }

    GLuint programID = glCreateProgram();
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, fragmentShaderID);

    glLinkProgram(programID);
    glGetProgramiv(programID, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(programID, 1024, NULL, info);
        std::cerr << "ERROR::GUI::LOAD_SHADER::PROGRAM::LINKING_FAILED\n" << info << std::endl;
    }

    glDetachShader(programID, vertexShaderID);
    glDetachShader(programID, fragmentShaderID);
    glDeleteShader(vertexShaderID);
    glDeleteShader(fragmentShaderID);
}

Solution

  • The fixed function matrix stack is deprecated. See Fixed Function Pipeline and Legacy OpenGL.

    When you use a core profile

    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    

    then you can't use the fixed function matrix stack.

    Use Uniform variables. Create a shader program with a projection matrix uniform (u_proj) and a view matrix uniform (u_view):

    #version 330 core
    
    layout (location = 0) in vec3 aPos;
    
    uniform mat4 u_proj;
    uniform mat4 u_view;
    
    void main()
    {
        gl_Position = u_proj * u_view * vec4(aPos.xyz, 1.0);
    }
    

    Get the locations of the uniform variables after the shader progrma was linked:

     glLinkProgram(shaderProgram);
    
     GLint projLoc = glGetUniformLocation(shaderProgram, "u_proj");
     GLint viewLoc = glGetUniformLocation(shaderProgram, "u_view");
    

    Use a library like OpenGL Mathematics (GLM), to initialize the projection matrix and view matrix:

    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    
    glm::mat4 proj = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f);
    glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    

    Set the values of the uniform variables after the program was installed:

    glUseProgram(shaderProgram);
    
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));