欢迎访问我的论坛帖:http://hongwgw.com/image/forum.php?mod=viewthread&tid=3&page=1&extra=#pid3
问题: 很多的例子中VBO中数据格式为 XnYnZnUnVnRnGnBn.......,代表 XYZ, UV and RGB的值。 问题一:能不能传入XYZ数据在一个VBO中,而在另一个VBO中传入UV值,第三个传入Color值? 问题二:能不能在一个VBO中传入500个顶点数据,而在另一个VBO中传入另外的500个顶点数据? 回答一: 答案都是肯定的。 第一个问题:先用 glBindBuffer绑定一个合适的缓存区,然后分别调用 glVertexAttribPointer。 第二个问题:调用两个draw() 接着问问题二: 对于第一个问题我们做一个test如下:
public draw( int vertices, FloatBuffer xyz_in, IntBuffer idx_in, FloatBuffer rgb_in) { int vao = glGenVertexArray(vao); glBindVertexArray (vao); // Does this have to happen before glGenBuffer calls? I don't think so. // Does it have to happen befire the glBindBuffer calls? Dunno. int index_buf = glGenBuffers(); //allocate a vbo for the xyz data int index_buf = glGenBuffers(); //allocate a vbo for the index data int color_buf = glGenBuffers(); // allocatea a vbo for the color data assert (vertices == xyz_ in.length / 3); // 3 floats per vertex assert (vertices == rgb_in.length / 3); // 3 floats per vertex assert (vertices >= idx_in.length); // No more indices than vertices. That would be silly. // put the xyz data into the first (position) vbo glBindBuffer(GL_ARRAY_BUFFER, xyz_buf); glBufferData(GL_ARRAY_BUFFER, xyz_in, vertices * 3 * sizeof(float) , GL_STATIC_DRAW); // put the color data into the second (color) vbo glBindBuffer(GL_ARRAY_BUFFER, color_buf); glBufferData(GL_ARRAY_BUFFER, color_in, vertices * 3 * sizeof(float) , GL_STATIC_DRAW); // put the index data into the third (index) vbo. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_in, idx_in.length() * sizeof(unsigned int), GL_STATIC_DRAW);
复制代码
有一个函数是
glEnableClientState,
使用的参数看上去是如何使用数据的,比如
GL_COLOR_ARRAY和
GL_INDEX_ARRAY。它和
glColorPointer
and
glIndexPointer一起调用,我想
glIndexPointer更多的是颜色调色板的索引而非顶点索引。我注意到
glVertexAttribPointer 是
glXXXPointer的成员函数,并且
glEnableClientState()可以运用
GL_VERTEX_ARRAY。
对于
glEnableClientState/glXXXPointer
以上我说的对吗?如果是这样,那么
glVertexAttribPointer的slot是什么意思,在例子中一般都为0?
接下来
glDrawXXX
如何使用以上我产生的缓冲区呢?
回答二:
Opengl的特性由扩展演变过来。可以参考
https://www.khronos.org/registry/OpenGL/index_gl.php,这上面列出了所有的扩展。仔细看看
ARB_vertex_buffer_object
,描述的与核心说明书中使用类似。
回答三:
让我们回到最初状态,在Opengl1.0中,问题可以通过调用
glColor, glNormal, glTexCoord解决。opengl有个“current”概念,这样你使用当前颜色、法线和纹理,并且调用
glColor/glNormal/glTexCoord。
glVertex会使用当前的数值、使用指定的位置,组成一个复杂的顶点,然后传递到驱动中,在下一阶段的管线中使用。
在很多材料中,你经常可以看到vertex意味着位置。
在固定管线中,每一个顶点属性有着特别的目标,如:
colour, normal, texcoord, position, etc.
OpenGL 1.1引进了vertex数组,它用了相同的模型和术语。使用数组而不是单个单个的输入。接下来是
glEnableClientState所做的,提供一个告诉opengl从一个数组中获取特性替代直接指定。
glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_NORMAL_ARRAY); glEnableClientState (GL_COLOR_ARRAY); glEnableClientState (GL_TEXTURE_COORD_ARRAY);
复制代码
接下来定义一些数组:
float positions[200 * 3]; float normals[200 * 3]; unsigned char colors[200 * 4]; float texcoords[200 * 2];
复制代码
最后我们建立指向这些数组的指针:
glVertexPointer (3, GL_FLOAT, 0, positions); glNormalPointer (GL_FLOAT, 0, normals); glColorPointer (4, GL_UNSIGNED_BYTE, 0, colors); glTexCoordPointer (2, GL_FLOAT, 0, texcoords);
复制代码
以上是建立单独特性的一种方法,还有一种交叉的方式(
interleaving
):
struct Vertex { float position[3]; float normal[3]; unsigned char color[4]; float texcoord[2]; }; Vertex vertices[200]; glVertexPointer (3, GL_FLOAT, sizeof (Vertex), vertices->position); glNormalPointer (GL_FLOAT, sizeof (Vertex), vertices->normal); glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (Vertex), vertices->color); glTexCoordPointer (2, GL_FLOAT, sizeof (Vertex), vertices->texcoord);
复制代码
以上是非VBO的形式,那么VBO的形式是这样的,初始化数组如下:
glBindBuffer (GL_ARRAY_BUFFER, positionsVBO); glBufferData (GL_ARRAY_BUFFER, sizeof (positions), positions, GL_STATIC_DRAW); glBindBuffer (GL_ARRAY_BUFFER, normalsVBO); glBufferData (GL_ARRAY_BUFFER, sizeof (normals), normals, GL_STATIC_DRAW); glBindBuffer (GL_ARRAY_BUFFER, colorsVBO); glBufferData (GL_ARRAY_BUFFER, sizeof (colors), colors, GL_STATIC_DRAW); glBindBuffer (GL_ARRAY_BUFFER, texcoordsVBO); glBufferData (GL_ARRAY_BUFFER, sizeof (texcoords), texcoords, GL_STATIC_DRAW);
复制代码
然后建立指针去使用这些vbo:
glBindBuffer (GL_ARRAY_BUFFER, positionsVBO); glVertexPointer (3, GL_FLOAT, 0, 0); glBindBuffer (GL_ARRAY_BUFFER, normalsVBO); glNormalPointer (GL_FLOAT, 0, 0); glBindBuffer (GL_ARRAY_BUFFER, colorsVBO); glColorPointer (4, GL_UNSIGNED_BYTE, 0, 0); glBindBuffer (GL_ARRAY_BUFFER, texcoordsVBO); glTexCoordPointer (2, GL_FLOAT, 0, 0);
复制代码
看到如何工作了吗?
gl*Pointer调用之前绑定的VBO,可以直接修改VBO,而不需要断开这个联系,因为显示驱动已经知道了改如何使用这些数据。
接下来该轮到
glEnableVertexAttribArray and glVertexAttribPointer如何插进来了。
You'll remember that I mentioned "legacy" or "fixed-function" vertex attributes above?
lEnableVertexAttribArray and glVertexAttribPointer提供普遍的顶点属性。从另一方面来讲,顶点属性不再含有固定的意思。你可以在着色器代码中自由解释这些顶点。通常vertex放在0 slot
最后忽视
index arrays (and glIndexPointer) 的存在,现在已经没人用它了。