OpenGL 3.3 - glDrawArrays 后的无效操作错误 (1282)
Posted
技术标签:
【中文标题】OpenGL 3.3 - glDrawArrays 后的无效操作错误 (1282)【英文标题】:OpenGL 3.3 - invalid operation error (1282) after glDrawArrays 【发布时间】:2015-09-11 14:22:29 【问题描述】:我正在使用 freeglut。我之前使用着色器程序成功地在单个 VBO 中渲染了一个三角形。
着色器程序编译、链接和验证不会引发错误。我认为问题在于我存储和调用 VBO(其中 2 个)的方式,因为在我只使用 1 个 VBO 之前。
编辑:删除所有不必要的代码
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <string.h>
#include <stdio.h>
#define countof(x) sizeof(x) / sizeof(x[0])
#define NUM_BUFFERS 2
#define INFOLOG_SIZE 1024
GLuint VBO_ids[NUM_BUFFERS];
GLfloat VBO0[] = -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f;
GLfloat VBO1[] = -1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,-1.0f, 0.0f;
GLfloat *VBOs[NUM_BUFFERS] = VBO0, VBO1 ;
GLuint shader_prog_id;
const GLchar *vert_src =
"#version 330\n"
"layout (location = 0) in vec3 Pos;\n"
"void main() \n"
" gl_Position = vec4(Pos.x, Pos.y, Pos.z, 1.0); \n";
const GLchar *frag_src =
"#version 330\n"
"out vec4 FragColor;\n"
"void main() \n"
" FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n";
void vbo_init(void)
glGenBuffers(NUM_BUFFERS, VBO_ids);
glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(VBO0), VBOs[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(VBO1), VBOs[1], GL_STATIC_DRAW);
int shader_init(const GLchar **v_src, const GLchar **f_src, GLint *v_size, GLint *f_size)
GLint success;
shader_prog_id = glCreateProgram();
GLuint v_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint f_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(v_shader, 1, v_src, v_size);
glShaderSource(f_shader, 1, f_src, f_size);
glCompileShader(v_shader);
glCompileShader(f_shader);
glAttachShader(shader_prog_id, v_shader);
glAttachShader(shader_prog_id, f_shader);
glLinkProgram(shader_prog_id);
glValidateProgram(shader_prog_id);
return 1;
int draw_initialize(void)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
vbo_init();
GLint vsrcsize = strlen(vert_src);
GLint fsrcsize = strlen(frag_src);
shader_init(&vert_src, &frag_src, &vsrcsize, &fsrcsize);
return 1;
void draw_callback(void)
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader_prog_id);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_TRIANGLES, 0, countof(VBO0)/3);
puts((char*)gluErrorString(glGetError()));
glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[1]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_TRIANGLES, 0, countof(VBO1)/3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
int main(int argc, char **argv)
glutInit(&argc, argv);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInitContextVersion(3, 3);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(600, 600);
glutCreateWindow("title");
glewInit();
draw_initialize();
glutIdleFunc(draw_callback);
glutMainLoop();
return 0;
【问题讨论】:
如果有人想尝试重现该错误,链接器标志为-lglut -lGLEW
【参考方案1】:
您需要在核心上下文中提供Vertex Array Object (VAO):
int draw_initialize(void)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
vbo_init();
GLint vsrcsize = strlen(vert_src);
GLint fsrcsize = strlen(frag_src);
shader_init(&vert_src, &frag_src, &vsrcsize, &fsrcsize);
GLuint vao = 0;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
return 1;
它们封装了顶点属性启用 (glEnableVertexAttribArray()
) 和指针 (glVertexAttribPointer()
) 状态。
还有:
glewExperimental = GL_TRUE
在glewInit()
之前
设置一个实际的glutDisplayFunc()
,而不是希望 GLUT 通过只注册一个空闲回调来弄清楚你的意思
【讨论】:
非常感谢!核心背景是好是坏?我在某处读到过 1) 很好 2) VAO 不是那么便携,我不得不扭动glewExperimental
来使用它们。
@Xis88 它们是可移植的;它们包含在 3.0+ OpenGL 规范中。我不确定为什么需要设置glewExperimental
才能访问相关功能。
我注意到这里有一些额外的错误:glBufferData(GL_ARRAY_BUFFER, sizeof(VBO0), VBOs[0], GL_STATIC_DRAW);
这是坏的,我相信你需要上面的&VBOs[0]
,这样你才能得到一个指向缓冲区的实际指针。
@ChrisBeck 不,VBOs[0]
是一个指向GLfloat
值数组的指针。实际上,我也可以通过 VBO0
代替。见GLfloat *VBOs[NUM_BUFFERS] = VBO0, VBO1 ;
。
有些东西在这里并没有完全加起来。 OP 说相同的代码适用于单个 VBO。如果缺少的 VAO 是问题所在,那么它也不应该只与一个 VBO 一起工作。以上是关于OpenGL 3.3 - glDrawArrays 后的无效操作错误 (1282)的主要内容,如果未能解决你的问题,请参考以下文章
为啥 OpenGL 的 glDrawArrays() 在核心配置文件 3.2 下失败并显示 GL_INVALID_OPERATION 而不是 3.3 或 4.2?
我可以在调用 glDrawArrays 后删除 OpenGL 顶点数组吗?
调用 glDrawArrays() 时的 OpenGL VBO Segfault