使用 glOrtho() 时 gluLookAt() 不起作用?

gluLookAt() not working when using glOrtho()?

我想用gluLookAt()移动我的相机,这样我就可以看到整个网格(在代码中是一个立方体)。

我在游戏循环中设置了ModelView矩阵。更改 glLookAt()gluPerspective() 对最终图像没有任何影响。我不断收到下面的图片。

我试过 glOrtho() 但还是不行...

这个问题是来自着色器还是绘图代码的其余部分?

#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"
                                 "}[=10=]";
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[=10=]";

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);
}

固定函数矩阵堆栈已弃用。参见 Fixed Function Pipeline and Legacy OpenGL

当您使用核心配置文件时

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

那你就不能用固定函数矩阵栈了

使用Uniform 个变量。使用投影矩阵统一 (u_proj) 和视图矩阵统一 (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);
}

获取着色器程序链接后统一变量的位置:

 glLinkProgram(shaderProgram);

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

使用像OpenGL Mathematics (GLM)这样的库来初始化投影矩阵和视图矩阵:

#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));

安装程序后设置统一变量的值:

glUseProgram(shaderProgram);

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