【问题标题】:Using VBO to draw the cube by loading wavefront object使用VBO通过加载波前对象绘制立方体
【发布时间】:2018-05-17 03:11:50
【问题描述】:

我需要使用 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]

按照顶点|法线|颜色的顺序是24indices|18indices|36indices,我已经测试它工作得很好

我使用另一个数组来存储顶点索引信息,它是 36 个索引,例如: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);
    }

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

【问题讨论】:

    标签: c++ opengl wavefront


    【解决方案1】:

    vbo的类型是float*,所以sizeof(vbo)不是vbo指向的数组的大小,而是指针的大小。请参阅sizeof
    注意,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);
    

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


    你的假设是错误的。您不能将 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 );
    

    预览:

    【讨论】:

    • 您好,我按照您的说明进行操作,但是它崩溃了,应该使用 sizeof(*float) 还是 sizeof(*va.data())?它应该是 glDrawArrays( GL_TRIANGLES, 0, 12 )? ;我测试 va 有正确的输出。,
    猜你喜欢
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多