误区一:
给 VBO 赋予数据时,即 调用
glBindBuffer(GL_ARRAY_BUFFER,vbo)
glBufferData(GL_ARRAY_BUFFER,sizeof(data),GL_STATIC_DRAW)
这两个函数时,需要事先 通过glBindVertexArray() 绑定到一个 VAO 上。
勘误:
实际上,glBufferData(),把 数组数据 写入 一个 vbo 时,完全没有必要绑定 glBindVertexArray() 一个 VAO.
道理也很简单:我要给一个 vbo 写入数据,其实并不关心 vao是哪个,跟我要写数据这件事完全没有关系!
只有在 把 vbo 的数据,真正传递到 shader 时候,也就是 调用 glVertexAttribPointer() 等针对 shader 的操作时(比如 glUseProgram,glEnableVertexAttribArray )时,才必须明确指定绑定到哪个 VAO 上.
在 glBufferData() 时,只是简答的给一个 vbo 传数据,跟 shader 无关,完全没有必要 bind 任何 VAO.
误区二:
关于 glVertexAttribPointer() 调用时,给 shader 传递数据时的 stride 参数的问题。
比如有这样的数据:
GLfloat vertexData[18] = {
-1,-1,0,//p1 pos
1,0,0,//p1 color red
1,-1,0,//p2 pos
0,1,0,//p2 color green
0,1,0,//p3 pos
0,0,1.//p3 color blue
};
前3个float表示顶点位置,后3个float表示顶点颜色时。
在给 shader 里的 pos 传递数据时,这个 stride 我本来以为 是 ,位置数据之间 ,隔着 一个 color 数据,即 3个 sizeof(GL_FLOAT), 所以 stride 要传3.
其实结果是 错误的,这个 stride 的含义是,前一个顶点的 第一个位置数据,与后一个顶点的 第一个位置数据,数据之间内存地址的差距。这个差距,应该是 1个 pos 的数据(3 * sizeof(GL_FLOAT)) 和 一个 (3 * sizeof(GL_FLOAT)),结果是 3 + 3 = 6. 所以这个 stride 需要传 6.
但是具体 有些教程里面, 只有 pos 或者 color 等一种数据,这时数据之间相联,没有间隔时,stride 竟然会传0,让我有些困惑。难道不应该传 当前 这1个 顶点 所占用的数据 的 跨度吗 ?比如 对只有3个 GL_FLOAT 组成 pos 数据的 VBO 来说,这时候 stride 不应该传 3*sizeof(GL_FLOAT) 吗?
经过实验, 这种情况stride 传 3*sizeof(GL_FLOAT) 完全没有问题(这个我理解),但是传0 也没有问题,让我很困惑,不太明白其中与原理 。
误区三:
opengl 我记得在固定管线的时候,需要开启/关闭 饶向剔除功能,否则很可能你设置的所有参数都没有问题,仅仅是因为 opengl默认会 不显示某一种顶点绕向(顺时针 逆时针 我忘记了) ,导致你的 GL 程序画不出来东西。
但是,目前测试来看,在自定义渲染管线的 新时代 OpenGL 里面,已经抛弃了 这一设定,只要 fragment shader 里给了颜色,就会正常显示,而不必关心 VBO 里 顶点数据 顶点 位置之间的绕序问题了。
以上3个误区,是今天重新再系统缕了一遍 VAO VBO 的基础用法得出来的。在此记录备忘。