OpenGL透视矩阵不起作用

OpenGL Perspective matrices not working

本文关键字:不起作用 透视 OpenGL      更新时间:2023-10-16

我对堆栈溢出和OpenGL都是新手。我正试图用自定义着色器创建我的第一个小三维程序,但我对所需的各种矩阵有问题。我不知道是什么原因导致了完全的黑屏,如果是我加载制服不正确,或者是我计算矩阵失败。不管怎样,我把代码贴在这里,如果有人能帮上忙,那就太棒了
主Cpp文件

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <GLglew.h>
#include <GLglut.h>
#include <glmglm.hpp>
#include <glmvec3.hpp>
#include <glmmat4x4.hpp>
#include <glmgtcmatrix_transform.hpp>
#include <glmgtctype_ptr.hpp>
GLuint programID, vbo;
using namespace glm;
void loadShaders(){
    char vertex_file_path[] = "vertex.glsl";
char fragment_file_path[] = "fragment.glsl";
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path);
if (VertexShaderStream.is_open()){
    std::string Line = "";
    while (std::getline(VertexShaderStream, Line))
        VertexShaderCode += "n" + Line;
    VertexShaderStream.close();
}
else{
    printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !n", vertex_file_path);
    getchar();
    throw new std::runtime_error("Shaders not found");
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if (FragmentShaderStream.is_open()){
    std::string Line = "";
    while (std::getline(FragmentShaderStream, Line))
        FragmentShaderCode += "n" + Line;
    FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %sn", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE){
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    char * VertexShaderErrorMessage = new char[InfoLogLength + 1];
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, VertexShaderErrorMessage);
    std::cout << VertexShaderErrorMessage << std::endl;
    printf("Could not compile vertex shader: %sn", VertexShaderErrorMessage);
    getchar();
    throw new std::runtime_error("Could not compile vertex shader");
}
// Compile Fragment Shader
std::cout << "Compiling shader : " << fragment_file_path << std::endl;
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE){
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    char * FragmentShaderErrorMessage = new char[InfoLogLength + 1];
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, FragmentShaderErrorMessage);
    printf("Could not compile fragment shader: %sn", FragmentShaderErrorMessage);
    getchar();
    throw new std::runtime_error("Could not compile fragment shader");
}
// Link the program
printf("Linking programn");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE){
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    printf("%sn", &ProgramErrorMessage[0]);
    throw new std::runtime_error("Could not compile program");
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
programID = ProgramID;
}
void loadMatrices(){
GLuint modelLoc = glGetUniformLocation(programID, "model");
GLuint viewLoc = glGetUniformLocation(programID, "view");
GLuint projLoc = glGetUniformLocation(programID, "projection");
mat4 model = scale(mat4(1.0f), vec3(1.0f));
mat4 view = lookAt(vec3(0.0f, 0.0f, 2.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f));
mat4 projection = perspective(45.0f, 16.0f / 9.0f, 0.01f,  100.0f);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, value_ptr(projection));
}
void renderLoop(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
    0,
    3,
    GL_FLOAT,
    GL_FALSE,
    0,
    (void *) 0
);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
int _tmain(int argc, _TCHAR* argv[])
{
int MY_ZERO = 0;
glutInit(&MY_ZERO, NULL);
glutInitWindowSize(1280, 720);
    glutInitDisplayMode(GLUT_DOBULE);
glutCreateWindow("Test");
glewExperimental = true;
glewInit();
glutIdleFunc(renderLoop);
glutDisplayFunc(renderLoop);
glMatrixMode(GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Nice perspective corrections
glDepthFunc(GL_LEQUAL);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_BLEND);
gluPerspective(75.0f, 16.0f / 9, 0.1f, 100.0f);
std::cout << "Setting blendFunc..." << std::endl;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
loadShaders();
loadMatrices();
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float vals[] = {
    0.0f, 1.0f, -10.0f,
    1.0f, 1.0f, -10.0f,
    1.0f, 0.0f, -10.0f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vals), vals, GL_STATIC_DRAW);
glutMainLoop();
system("pause");
return 0;
}

顶点着色器

layout (location = 0) in vec3 pos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
    gl_Position = projection * vec4(pos, 1.0f);
}

片段着色器

void main(){
    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}

代码的几个一般方面需要改进;例如

⊗它可以投掷但不能catch和清理:

// there's no try/catch block enclosing this
throw new std::runtime_error("Could not compile vertex shader");

⊗它准备泄漏:

char * VertexShaderErrorMessage = new char[InfoLogLength + 1];
/* ... */
throw new std::runtime_error("Could not compile vertex shader");

⊗它不必要地消耗CPU和GPU时间

glutIdleFunc(renderLoop); // boosts the frame rate for performance
                          // meters only

例如展开着色器创建和错误处理循环违反DRY。


OpenGL特定的pov来看,有几件事是不好的。

⊗这个

mat4 view = lookAt(vec3(0.0f, 0.0f, 2.0f),
                   vec3(0.0f, 0.0f, 0.0f), 
                   vec3(0.0f, 1.0f, 0.0f));

(右)准备用凸轮后退2个单元;但该矩阵未在着色器中使用

void main(){
    gl_Position = projection * vec4(pos, 1.0f);
}

⊗着色器首先被创建并附加到程序中,但一旦成功,就会从打算使用的程序中删除并再次分离

glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);

⊗这些调用

glMatrixMode(GL_PROJECTION);
/* ... */
gluPerspective(75.0f, 16.0f / 9, 0.1f, 100.0f);
/* ... */
glMatrixMode(GL_MODELVIEW);

适用于(已弃用的)固定管道;此处未使用的

⊗在代码中没有glClear()调用

可能还有更多的事情需要处理,但这是我第一眼看到的。

如果先处理这些事情,我们可以更深入地研究代码。

已解决

问题是我没有使用保存制服的程序,所以它无法加载制服。多亏了@BDL,我开始关注OpenGL错误,在每次glUniformMatrix4fv之后我都发现了GL_INVALID_OPERATION。我的调试很差。感谢所有提供帮助的人

TL;DRglUseProgram(program)置于任何glUniformMatrix4fv() 之前