我已经阅读了很多关于此的内容,但还无法解决任何问题。我正在尝试使用OpenGL3绘制彩色三角形,但出现以下错误:
引发'std::runtime_error'实例之后终止调用what():顶点着色器的编译错误(来自文件./TP1/shaders/triangle.vs.glsl):0:1(10):错误:GLSL 3.30不支持。 支持的版本是:1.10、1.20、1.30、1.00 ES,3.00 ES,3.10 ES和3.20 ES
当我运行 glxinfo | grep -i opengl 我得到:
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 6000 (Broadwell GT3)
OpenGL core profile version string: 3.3 (Core Profile) Mesa 19.0.8
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL version string: 3.0 Mesa 19.0.8
OpenGL shading language version string: 4.50
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile
OpenGL extensions:
OpenGL ES profile version string:
OpenGL ES 3.1 Mesa 19.0.8
OpenGL ES profile shading language version string:
OpenGL ES GLSL ES 3.10
OpenGL ES profile extensions:
我尝试了导出MESA_GL_VERSION_OVERRIDE = 3.3 ,这使我能够执行代码,但是我只得到了一个怪异的三角形,而不是漂亮的等边多色三角形。
这是我的完整代码:
#include <glimac/SDLWindowManager.hpp>
#include <GL/glew.h>
#include <iostream>
#include <glimac/Program.hpp>
#include <glimac/FilePath.hpp>
using namespace glimac;
int main(int argc, char** argv) {
// Initialize SDL and open a window
SDLWindowManager windowManager(800, 600, "GLImac");
// Initialize glew for OpenGL3+ support
GLenum glewInitError = glewInit();
if(GLEW_OK != glewInitError) {
std::cerr << glewGetErrorString(glewInitError) << std::endl;
return EXIT_FAILURE;
}
std::cout << "OpenGL Version : " << glGetString(GL_VERSION) << std::endl;
std::cout << "GLEW Version : " << glewGetString(GLEW_VERSION) << std::endl;
//load shaders and tell OpenGL to use them
FilePath applicationPath(argv[0]);
Program program = loadProgram(applicationPath.dirPath() + "shaders/triangle.vs.glsl",
applicationPath.dirPath() + "shaders/triangle.fs.glsl");
program.use();
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//triangle data
GLfloat vertices[] = { -0.5f, -0.5f, 1.f, 0.f, 0.f, //2 coordinates + 1 0 0 color
0.5f, -0.5f, 0.f, 1.f, 0.f,
0.0f, 0.5f, 0.f, 0.f, 1.f };
glBufferData(GL_ARRAY_BUFFER, (15*(sizeof(float))), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
const GLuint VERTEX_ATTR_POSITION = 3;
const GLuint VERTEX_ATTR_COLOR = 8;
glEnableVertexAttribArray(VERTEX_ATTR_POSITION);
glEnableVertexAttribArray(VERTEX_ATTR_COLOR);
const GLvoid* bouche;
glVertexAttribPointer(VERTEX_ATTR_POSITION, 2, GL_FLOAT, GL_FALSE, (0*sizeof(GL_FLOAT)), bouche);
glVertexAttribPointer(VERTEX_ATTR_COLOR, 3, GL_FLOAT, GL_FALSE, (2*sizeof(GL_FLOAT)), bouche);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(VERTEX_ATTR_POSITION, 2, GL_FLOAT, GL_FALSE, (2*sizeof(GL_FLOAT)), 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Application loop:
bool done = false;
while(!done) {
// Event loop:
SDL_Event e;
while(windowManager.pollEvent(e)) {
if(e.type == SDL_QUIT) {
done = true; // Leave the loop after this iteration
}
}
//clean window
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
// Update the display
windowManager.swapBuffers();
}
//liberate allocated memory on GPU (the vbo and vao)
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
return EXIT_SUCCESS;
}
最佳答案
使用glew时,请通过glewExperimental = GL_TRUE;
启用其他扩展名。参见GLEW documentation,其中说:
glewExperimental = GL_TRUE;
GLenum glewInitError = glewInit();
if(GLEW_OK != glewInitError) {
std::cerr << glewGetErrorString(glewInitError) << std::endl;
return EXIT_FAILURE;
}
当命名缓冲区对象绑定(bind)到目标
GL_ARRAY_BUFFER
时, glVertexAttribPointer
的最后一个参数被视为该缓冲区的字节偏移量。调用
glVertexAttribPointer
时,顶点数组规范将存储在当前绑定(bind)的顶点数组对象的状态 vector 中。当前绑定(bind)到目标GL_ARRAY_BUFFER
的缓冲区与属性关联,并且对象的名称(值)存储在VAO的状态 vector 中。还要注意,
glVertexAttribPointer
的第5个参数(跨度)指定了连续通用顶点属性之间的字节偏移。这意味着在调用
glVertexAttribPointer
之前,必须绑定(bind)Vertex Array Object和Vertex Buffer Object。stride参数必须为
5*sizeof(Glfloat)
,因为顶点属性由5个GLfloat
值(x,y,r,g,b)组成。VERTEX_ATTR_POSITION
的偏移量是0,而VERTEX_ATTR_COLOR
的偏移量是2*sizeof(GLfloat)
,因为(r,g b)在(x,y)之后。请注意,GL_FLOAT
是枚举器常量,而不是数据类型,因此2*sizeof(GL_FLOAT)
不会执行您期望的操作。//triangle data
GLfloat vertices[] = { -0.5f, -0.5f, 1.f, 0.f, 0.f, //2 coordinates + 1 0 0 color
0.5f, -0.5f, 0.f, 1.f, 0.f,
0.0f, 0.5f, 0.f, 0.f, 1.f };
// create vertex buffer object
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// specify the array of generic vertex attribute data
glBindBuffer(GL_ARRAY_BUFFER, vbo); // if "vbo" is still bound then that would not be necessary
glVertexAttribPointer(VERTEX_ATTR_POSITION, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), nullptr);
glVertexAttribPointer(VERTEX_ATTR_COLOR, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), 2*sizeof(GLfloat));
glEnableVertexAttribArray(VERTEX_ATTR_POSITION);
glEnableVertexAttribArray(VERTEX_ATTR_COLOR);
// the following is not necessary, you can let them bound
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
确保顶点属性索引正确:
const GLuint VERTEX_ATTR_POSITION = 3;
const GLuint VERTEX_ATTR_COLOR = 8;
3和8是可能的,但看起来很奇怪。这不应该是属性的资源索引,该属性索引可以由Layout qualifier设置或可以在链接程序后由
glGetAttribLocation
获取。顺便说一下,等边三角形的坐标为:
GLfloat vertices[] = {
x y r g b
-0.866f, -0.5f, 1.f, 0.f, 0.f,
0.866f, -0.5f, 0.f, 1.f, 0.f,
0.0f, 1.0f, 0.f, 0.f, 1.f };