Opengl VAO和元素数组缓冲区状态

Opengl VAO和元素数组缓冲区状态,opengl,intel,nvidia,opengl-3,vertex-array,Opengl,Intel,Nvidia,Opengl 3,Vertex Array,我最近编写了一些使用顶点数组对象(VAO)的OpenGL 3.3代码,随后在Intel graphics adapter上对其进行了测试,结果令人失望的是,元素数组缓冲区绑定显然不是VAO状态的一部分,因为调用: glBindVertexArray(我的车); GLD元素(GLU三角形带,计数,GLU无符号整数,0); 没有效果,而: glBindVertexArray(我的车); glBindBuffer(GL_元素_数组_缓冲区,my_索引_缓冲区);/? GLD元素(GLU三角形带,计数

我最近编写了一些使用顶点数组对象(VAO)的OpenGL 3.3代码,随后在Intel graphics adapter上对其进行了测试,结果令人失望的是,元素数组缓冲区绑定显然不是VAO状态的一部分,因为调用:

glBindVertexArray(我的车);
GLD元素(GLU三角形带,计数,GLU无符号整数,0);
没有效果,而:

glBindVertexArray(我的车);
glBindBuffer(GL_元素_数组_缓冲区,my_索引_缓冲区);/?
GLD元素(GLU三角形带,计数,GLU无符号整数,0);
渲染几何体。我认为这仅仅是OpenGL的Intel实现中的一个bug(因为在GL_ARB_vertex_array_对象(甚至在GL_OES_vertex_array_对象)中明确指出元素数组是保存状态的一部分),但随后它出现在移动NVIDIA Quadro 4200上。那不好玩

它是驱动程序错误、规范错误还是代码中的某个错误?该代码在GeForce 260和480上完美地工作

有没有人有过类似的经历

同样奇怪的是,GL_EXT_direct_state_access没有一个将元素数组缓冲区绑定到VAO的函数(但它确实有指定顶点属性数组的函数,从而指定数组缓冲区)。GPU制造商是不是违反了规格,欺骗了我们,还是怎么了

编辑

我本来不打算显示任何源代码,因为我认为这里没有必要。但根据要求,以下是再现问题的最小测试用例:

static GLuint n_vertex_buffer_object,p_index_buffer_object_list[3];
静态胶合p_-vao[2];
bool InitGLObjects()
{
常量浮点p_四边形_顶点颜色[]={
1, 0, 0, -1, 1, 0,
1, 0, 0, 1, 1, 0,
1, 0, 0, 1, -1, 0,
1,0,0,-1,-1,0,//红色四边形
0, 0, 1, -1, 1, 0,
0, 0, 1, 1, 1, 0,
0, 0, 1, 1, -1, 0,
0,0,1,-1,-1,0,//蓝色四边形
0, 0, 0, -1, 1, 0,
0, 0, 0, 1, 1, 0,
0, 0, 0, 1, -1, 0,
0,0,0,-1,-1,0//黑色四元
};
常量无符号整数p_四元索引[][6]={
{0, 1, 2, 0, 2, 3},
{4, 5, 6, 4, 6, 7},
{8, 9, 10, 8, 10, 11}
};
glGenBuffers(1,&n\u顶点\u缓冲区\u对象);
glBindBuffer(GL_数组_BUFFER,n_顶点_BUFFER_对象);
glBufferData(GL_数组_缓冲区、大小(p_四边形_顶点颜色)、p_四边形_顶点颜色、GL_静态_绘制);
glGenBuffers(3,p_索引_buffer_对象_列表);
对于(int n=0;n<3;++n){
glBindBuffer(GL_元素_数组_BUFFER,p_索引_BUFFER_对象_列表[n]);
glBufferData(GL_元素数组缓冲区,sizeof(p_quad_索引[n]),p_quad_索引[n],GL_静态绘制);
}
Glgenvertexarray(2,p_vao);
glbindvatexarray(p_vao[0]);
{
glBindBuffer(GL_数组_BUFFER,n_顶点_BUFFER_对象);
GlenableVertexAttributeArray(0);
glvertexattributepointer(0,3,GL_FLOAT,GL_FALSE,6*sizeof(FLOAT),p_offsetingvbo(0));
GlenableVertexAttributeArray(1);
glvertexattributepointer(1,3,GL_FLOAT,GL_FALSE,6*sizeof(FLOAT),p_OffsetInVBO(3*sizeof(FLOAT));
glBindBuffer(GL_元素_数组_缓冲区,p_索引_缓冲区_对象_列表[0]);//红色
}
glBindVertexArray(0);
glBindVertexArray(p_vao[1]);
{
glBindBuffer(GL_数组_BUFFER,n_顶点_BUFFER_对象);
GlenableVertexAttributeArray(0);
glvertexattributepointer(0,3,GL_FLOAT,GL_FALSE,6*sizeof(FLOAT),p_offsetingvbo(0));
GlenableVertexAttributeArray(1);
glvertexattributepointer(1,3,GL_FLOAT,GL_FALSE,6*sizeof(FLOAT),p_OffsetInVBO(3*sizeof(FLOAT));
glBindBuffer(GL_元素_数组_缓冲区,p_索引_缓冲区_对象_列表[1]);//蓝色
}
glBindVertexArray(0);
#ifdef绑定\黑色\四元\元素\数组\缓冲区
glBindBuffer(GL_元素_数组_BUFFER,p_索引_BUFFER_对象_列表[2]);
//用黑色四元组绑定缓冲区(不在VAO内,不应看到)
#endif//绑定\黑色\四元\元素\数组\缓冲区
//[在此编译着色器]
返回true;//成功
}
上面的代码创建了一个包含三个四边形的顶点缓冲区,红色、蓝色和黑色。然后创建三个指向各个四边形的索引缓冲区。然后创建并设置两个VAO,一个包含红色四元索引,另一个包含蓝色四元索引。不应渲染黑色四边形(假设定义了绑定\黑色\四边形\元素\数组\缓冲区)

void onDraw()
{
glClearColor(.5f、.5f、.5f、0);
glClear(GLU颜色缓冲位);
glDisable(GLU深度测试);
glUseProgram(n_程序_对象);
静态int n_last_color=-1;
int n_color=(clock()/2000)%2;
如果(n\u最后一个颜色!=n\u颜色){
printf(“正在绘制%s四边形”;(n_颜色)?“蓝色”:“红色”);
n_last_color=n_color;
}
glBindVertexArray(p_vao[n_color]);
#如果定义VAO不存储元素数组缓冲区
glBindBuffer(GL_元素_数组_BUFFER,p_索引_BUFFER_对象_列表[n_颜色])//修复了该问题
#endif//VAO\u不存储\u元素\u数组\u缓冲区
gld元素(GL_三角形,6,GL_无符号,0);
glBindVertexArray(0);
}
这会将视口清除为灰色,并以重复方式渲染蓝色或红色四边形(它还会打印哪个四边形)。虽然这在桌面GPU上有效,但在笔记本GPU上不起作用(除非定义了VAO\u Doesnu\u STORE\u ELEMENT\u ARRAY\u BUFFER宏,否则会渲染黑色四元组)。取消定义BIND\u black\u quad\u ELEMENT\u ARRAY\u BUFFER宏会使四元组变为蓝色,因为蓝色索引缓冲区最后绑定。但无论如何,它都不会渲染红色四元组

所以在我看来,这要么是我对VAO应该如何工作的理解中的致命错误,要么是我的代码中的错误,要么是驱动程序错误


实际上,我认为arbvao缺少元素数组缓冲区绑定(或任何其他缓冲区绑定)状态

不需要相信;规范说明了事实

根据规范:

命令

void GenVertexArrays(sizei n, uint *arrays);
glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(0));
gBoundBuffer_GL_ARRAY_BUFFER=n_vertex_buffer_object;
currentVAO->enable|=(1<<0);
currentVAO->vertexBuffer=IndexToPointer(gBoundBuffer_GL_ARRAY_BUFFER);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[0]);
glBindVertexArray(0);
gBoundBuffer_GL_ELEMENT_ARRAY_BUFFER=p_index_buffer_object_list[0];
currentVAO=0;