我对堆栈溢出和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);
}
答案 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()