使用VBO通过加载波前对象绘制立方体

Using VBO to draw the cube by loading wavefront object

我需要使用 VBO 通过加载波前对象来绘制立方体。 通过绘制三角形。 这是对象:

v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
f 2//1 3//1 1//1
f 4//2 7//2 3//2
f 8//3 5//3 7//3
f 6//4 1//4 5//4
f 7//5 1//5 3//5
f 4//6 6//6 8//6
f 2//1 4//1 3//1
f 4//2 8//2 7//2
f 8//3 6//3 5//3
f 6//4 2//4 1//4
f 7//5 5//5 1//5
f 4//6 2//6 6//6  

我还有一个自己填的更酷的数组,等于3倍的面数,也就是36个索引

float colours[] = {
    0.583f,  0.771f,  0.014f,
    0.609f,  0.115f,  0.436f,
    0.327f,  0.483f,  0.844f,
    0.822f,  0.569f,  0.201f,
    0.435f,  0.602f,  0.223f,
    0.310f,  0.747f,  0.185f,
    0.597f,  0.770f,  0.761f,
    0.559f,  0.436f,  0.730f,
    0.359f,  0.583f,  0.152f,
    0.483f,  0.596f,  0.789f,
    0.559f,  0.861f,  0.639f,
    0.195f,  0.548f,  0.859f,
    }

我将我的顶点、法线、颜色信息存储到绑定到 VBO 缓冲区的数组中:

 float* vbo = new float[78]

按照vertices|normals|colours的顺序是24indices|18indices|36indices,我测试过效果很好

我使用另一个数组来存储顶点索引信息,它是 36indices ,例如: f 2//1 3//1 1//1 我在我的数组中存储为 2/3/1

 int *element = new int[36];

我已经测试过它运行良好,我将我的 vbo 初始化如下:

 static void init(void){
 .......
Gluint vbo_id,index_id;

glGenBuffers(1,&vbo_id);
glGenBuffers(1,&index_id);
glBindBuffer(GL_ARRAY_BUFFER,vbo_id); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);

glBufferData(GL_ARRAY_BUFFER,sizeof(vbo),vbo,GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(element),element,GL_STATIC_DRAW); } 

我的画在这里

 static void display(void){
  .......
 glBindBuffer(GL_ARRAY_BUFFER,vbo_id);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glVertexPointer(3,GL_FLOAT,0,0);
    glNormalPointer(GL_FLOAT,0,(void*)(24*sizeof(float)));//binding 
    glColorPointer(3,GL_FLOAT,0,(void*)(42*sizeof(float)));

    for(int i=0;i<12;i++){

    glBegin(GL_TRIANGLES);
    glArrayElement(element[i]);
    glArrayElement(element[i+1]);
    glArrayElement(element[i+2]);
    glEnd();

    }
    /* have try this one too:
    glDrawElements(GL_TRIANGLES,3,GL_INT,0) */


    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    }

但是屏幕上没有显示任何内容。我的绑定方法是否正确,我的导师告诉我当我用索引绘制时,如果我绑定顶点和法线,并且颜色正确,它会通过绘制顶点索引自动匹配。

vbo的类型是float*,所以sizeof(vbo)不是vbo指向的数组的大小,而是指针的大小.请参阅 sizeof.
Note, the 3rd parameter of glBufferData 必须是以字节为单位的缓冲区大小。

float* vbo = new float[78]的大小是78 * sizeof(float)78 * sizeof(*vbo)
int *element = new int[36] 的大小是 36 * sizeof(int)36 * sizeof(*element)
但是sizeof(vbo)是数组指针的大小还是和sizeof(float*).

一样

这意味着您必须像这样更改代码:

glBufferData(GL_ARRAY_BUFFER, 78*sizeof(float), vbo, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36*sizeof(int), element, GL_STATIC_DRAW); 

glDrawElements 的第二个参数必须是索引的数量,第三个参数必须是 GL_UNSIGNED_BYTEGL_UNSIGNED_SHORTGL_UNSIGNED_INT,具体取决于索引的数据类型:

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL);

注意,对于索引数组的数据类型 (element),您应该更喜欢使用 unsigned int * 而不是 int*


你的假设是错误的。您不能将 24 个顶点坐标、18 个法向量和 36 种颜色与不同的索引数组直接混合在一个 Vertex Array Object.

每个顶点位置的顶点属性构成一组数据。这意味着您必须创建顶点坐标、法向量和颜色的元组。

进一步查看Rendering meshes with multiple indices

我建议使用 std::vector 并像这样使用它:

#include <vector>

// 8  vertex coordiantes: 8 * 3 float 
std::vector<float> v{
  -1.0f, -1.0f,  1.0f,
  -1.0f,  1.0f,  1.0f,
  -1.0f, -1.0f, -1.0f,
  -1.0f,  1.0f, -1.0f,
   1.0f, -1.0f,  1.0f,
   1.0f,  1.0f,  1.0f,
   1.0f, -1.0f, -1.0f,
   1.0f,  1.0f, -1.0f };

// 6  normal vectors: 6 * 3 float
std::vector<float> nv{
   -1.0f,  0.0f,  0.0f,
    0.0f,  0.0f, -1.0f,
    1.0f,  0.0f,  0.0f,
    0.0f,  0.0f,  1.0f,
    0.0f, -1.0f,  0.0f,
    0.0f,  1.0f,  0.0f };

// 12 colors coordiantes: 12 * 3 float 
std::vector<float> c{
    0.583f,  0.771f,  0.014f,
    0.609f,  0.115f,  0.436f,
    0.327f,  0.483f,  0.844f,
    0.822f,  0.569f,  0.201f,
    0.435f,  0.602f,  0.223f,
    0.310f,  0.747f,  0.185f,
    0.597f,  0.770f,  0.761f,
    0.559f,  0.436f,  0.730f,
    0.359f,  0.583f,  0.152f,
    0.483f,  0.596f,  0.789f,
    0.559f,  0.861f,  0.639f,
    0.195f,  0.548f,  0.859f };

// 12 faces 3*2 indices/face: 12 * 3 * 2 unsigned int 
std::vector<unsigned int> indices{
    2, 1,    3, 1,    1, 1,
    4, 2,    7, 2,    3, 2,
    8, 3,    5, 3,    7, 3,
    6, 4,    1, 4,    5, 4,
    7, 5,    1, 5,    3, 5,
    4, 6,    6, 6,    8, 6,
    2, 1,    4, 1,    3, 1,
    4, 2,    8, 2,    7, 2,
    8, 3,    6, 3,    5, 3,
    6, 4,    2, 4,    1, 4,
    7, 5,    5, 5,    1, 5,
    4, 6,    2, 6,    6, 6 };

创建顶点数组数据

// final vertex attributes 12 * 3 *(3 + 3 + 3) floats
// x0 y0 z0    nvx0 nvy0 nvz0    cr0 cg0 cb0
// x1 y1 z1    nvx1 nvy1 nvz1    cr1 cg1 cb1
std::vector<float> va; 

const unsigned int no_of_faces = 12;
for (unsigned int f=0; f<no_of_faces; ++f )
{
    for (unsigned int t=0; t<3; ++t )
    {
        unsigned int vi = indices[(f*3+t)*2]-1;   // vertex index
        unsigned int ni = indices[(f*3+t)*2+1]-1; // normal vector index
        unsigned int ci = f;                      // color index

        va.insert(va.end(), v.begin()  + vi*3, v.begin()  + vi*3+3); // insert vertex coordinate
        va.insert(va.end(), nv.begin() + ni*3, nv.begin() + ni*3+3); // insert normal vector
        va.insert(va.end(), c.begin()  + ci*3, c.begin()  + ci*3+3); // insert color
    }
}

创建 Vertex Buffer Object:

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, va.size()*sizeof(*va.data()), va.data(), GL_STATIC_DRAW );

定义通用顶点属性数据数组:

glVertexPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glNormalPointer( GL_FLOAT, 9*sizeof(*va.data()), (void*)(3*sizeof(*va.data())) ); 
glEnableClientState( GL_NORMAL_ARRAY );
glColorPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), (void*)(6*sizeof(*va.data())) ); 
glEnableClientState( GL_COLOR_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

绘制数组:

glDrawArrays( GL_TRIANGLES, 0, 36 );

预览: