我有一个如下所示的程序:
#include <iostream>
#include <fstream>
#include <sstream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
GLuint prog, verShader, fragShader;
GLint attrPos, attrNor;
GLint uniModelView, uniProjection, uniModelViewTransposeInverse;
glm::mat4 modelMatrix, viewMatrix, projectionMatrix, MV, MVP;
glm::mat3 MVI;
const string loadFile(string name)
{
ifstream in(name.c_str(), ios::in);
if (in.fail()) {
cout << "File: '" << name << "' could not exist!!" << endl;
return "";
}
stringstream data;
data << in.rdbuf();
in.close();
return data.str();
}
GLuint createShader(GLenum type, const string name)
{
GLint isCompileOk;
GLuint shader;
string shaderText, shaderType;
const char *shaderSource;
switch(type)
{
case GL_VERTEX_SHADER:
shaderType = "GL_VERTEX_SHADER";
break;
case GL_FRAGMENT_SHADER:
shaderType = "GL_FRAGMENT_SHADER";
break;
}
shaderText = loadFile(name);
shaderSource = shaderText.c_str();
shader = glCreateShader(type);
glShaderSource(shader, 1, &shaderSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompileOk);
if (isCompileOk == GL_FALSE) {
char *shaderErr;
int errLength, errRetrieve;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errLength);
shaderErr = new char [errLength + 1];
glGetShaderInfoLog(shader, errLength, &errRetrieve, shaderErr);
cout << "Compile '" << shaderType << "' error:" << endl;
cout << shaderErr << endl;
delete [] shaderErr;
return 0;
} else {
cout << "Compile '" << shaderType << "' ok!" << endl;
}
return shader;
}
bool makeShader()
{
GLint isLinkOk;
verShader = createShader(GL_VERTEX_SHADER, "vert.glsl");
fragShader = createShader(GL_FRAGMENT_SHADER, "frag.glsl");
prog = glCreateProgram();
glAttachShader(prog, verShader);
glAttachShader(prog, fragShader);
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &isLinkOk);
if (isLinkOk == GL_FALSE) {
char *progErr;
int errLenght, errRetrieve;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &errLenght);
progErr = new char[errLenght + 1];
glGetProgramInfoLog(prog, errLenght, &errRetrieve, progErr);
cout << "Link program error:" << endl;
cout << progErr << endl;
delete [] progErr;
return false;
} else {
cout << "Link program Ok!" << endl;
}
attrPos = glGetAttribLocation(prog, "position");
uniModelView = glGetUniformLocation(prog, "ModelViewMatrix");
uniProjection = glGetUniformLocation(prog, "ProjectionMatrix");
uniModelViewTransposeInverse = glGetUniformLocation(prog, "ModelViewTransposeInverseMatrix");
return true;
}
float vertexs[] = {
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f
};
unsigned short indicates[] = {
0, 1, 2,
2, 3, 0
};
GLuint vao, vbo, ibo;
void display()
{
MV = viewMatrix * modelMatrix;
MVP = projectionMatrix * MV;
MVI = glm::transpose(glm::inverse(glm::mat3(MV)));
glUseProgram(prog);
glUniformMatrix4fv(uniModelView, 1, GL_FALSE, glm::value_ptr(MV));
glUniformMatrix3fv(uniModelViewTransposeInverse, 1, GL_FALSE, glm::value_ptr(MVI));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, sizeof(indicates)/sizeof(unsigned short), GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
projectionMatrix = glm::perspective(45.0f, float(w)/h, 0.1f, 1000.0f);
glUseProgram(prog);
glUniformMatrix4fv(uniProjection, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
}
void idle()
{
glutPostRedisplay();
}
void Init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
modelMatrix = glm::mat4(1.0f);
viewMatrix = glm::lookAt(
glm::vec3(0.0f, 5.0f, 10.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f)
);
projectionMatrix = glm::mat4(1.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
glEnableVertexAttribArray(attrPos);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicates), indicates, GL_STATIC_DRAW);
glBindVertexArray(0);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("Rectangle!");
if (glewInit() != GLEW_OK) {
cout << "glewInit() fail!" << endl;
return -1;
}
if (!makeShader()) {
cout << "makeShader() error!!" << endl;
return -1;
}
Init();
reshape(WINDOW_WIDTH, WINDOW_HEIGHT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
当我添加
VAO
缓冲区时,freeglut
将在 glutMainLoop()
中崩溃,如果我删除 glGenVertexArrays
调用(当然,也删除了 VAO 的亲戚),它运行正常,所以我猜测是 glGenVertexArrays
的 freeglut 问题。问题: 我的问题是什么?
ps:我的图形校准支持 opengl 2.1,我使用 Visual Studio 2008。
更新: 使用 VAO,上面的程序运行良好,但只有在我关闭 freeglut 窗口时才会崩溃。
更新着色器: 我的着色器非常简单:
顶点着色器:
#version 120
attribute vec3 position;
// attribute vec3 normal;
uniform mat4 ModelViewMatrix;
uniform mat3 ModelViewTransposeInverseMatrix;
uniform mat4 ProjectionMatrix;
void main(void)
{
gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(position, 1.0);
}
片段着色器:
#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
最佳答案
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
您的顶点数据是紧密包装的。使用
0
而不是 sizeof(float) * 3
的步幅。此外,VAO 只变成了 core in 3.0 。在使用该功能之前,您应该检查
ARB_vertex_array_object
支持。