OpenGL透视矩阵无法正常工作

时间:2015-11-24 09:57:53

标签: c++ opengl matrix glsl

我对堆栈溢出和OpenGL都不熟悉。 我尝试使用自定义着色器创建我的第一个小3d程序,但我遇到了所需的各种矩阵的问题。我不知道究竟是什么原因造成了完整的黑屏,如果是我错误地装了制服或者我没有计算矩阵。无论如何,我在这里发布代码,如果有人可以帮助它将是惊人的。
主要Cpp文件

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <GL\glew.h>
#include <GL\glut.h>
#include <glm\glm.hpp>
#include <glm\vec3.hpp>
#include <glm\mat4x4.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtc\type_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 : %s\n", 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: %s\n", 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: %s\n", FragmentShaderErrorMessage);
    getchar();
    throw new std::runtime_error("Could not compile fragment shader");
}

// Link the program
printf("Linking program\n");
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("%s\n", &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);
}

2 个答案:

答案 0 :(得分:1)

代码有几个一般方面需要改进; e.g。

⊗它可以投掷,但不会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");

needlessly消耗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);

适用于(已弃用)固定管道;这里没有使用,

the代码中没有glClear()调用

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

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

答案 1 :(得分:0)

<强>解决!

问题是我没有使用持有制服的程序,因此无法加载它们。感谢@BDL我开始关注OpenGL错误,并在每glUniformMatrix4fv后找到GL_INVALID_OPERATION。我的调试很糟糕。感谢所有帮助过的人

TL; DR glUseProgram(program)置于任何glUniformMatrix4fv()

之前