无法使OpenGL缓冲区阵列工作- glVertex工作

syqv5f0l  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(162)

我有一个本征::MatrixXf,它的顶点(N3)和面(N3)分别作为变量mvTemp2和mF。
如果我定期绘制顶点,它们会根据下面的代码给予正确的输出:

while(1){
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glEnable(GL_LIGHTING);
    glShadeModel( GL_SMOOTH );
    glEnable( GL_TEXTURE_2D );

    glViewport( 0, 0, (float)renderWidth/1, (float)renderHeight/1. );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60, (float)renderWidth/(float)renderHeight, 0.1, 10000. );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    glPushMatrix();
    glTranslatef(0,-0.5,-0.5);
//        glBindVertexArray(vao);
//        glDrawElements(GL_TRIANGLES, indexdata.size(), GL_UNSIGNED_BYTE,     (void*)0);

    for(int i=0; i<smpl.mF.rows(); i++){
        glBegin(GL_POLYGON);
        for(int j=0; j<smpl.mF.cols(); j++){
            indexdata.push_back(smpl.mF(i,j)+1);

        }
        glVertex3fv((const GLfloat*)&vertexdata[smpl.mF(i,0)].position);
        glVertex3fv((const GLfloat*)&vertexdata[smpl.mF(i,1)].position);
        glVertex3fv((const GLfloat*)&vertexdata[smpl.mF(i,2)].position);
        glEnd();
    }

    glPopMatrix();

    glutSwapBuffers();
    glutPostRedisplay();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    glutMainLoopEvent();
}

但是,如果我使用顶点缓冲区,我会得到垃圾输出:

// Iterate v
for(int i=0; i<smpl.mVTemp2.rows(); i++){
    Vertex v;
    for(int j=0; j<smpl.mVTemp2.cols(); j++){
        v.position[j] = smpl.mVTemp2(i,j);
    }
    vertexdata.push_back(v);
}

std::vector<GLubyte> indexdata;

// Iterate f
for(int i=0; i<smpl.mF.rows(); i++){
    for(int j=0; j<smpl.mF.cols(); j++){
        indexdata.push_back(smpl.mF(i,j));
    }
}

// Create and bind a VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// Create and bind a BO for vertex data
GLuint vbuffer;
glGenBuffers(1, &vbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vbuffer);

// copy data into the buffer object
glBufferData(GL_ARRAY_BUFFER, vertexdata.size() * sizeof(Vertex), &vertexdata[0], GL_STATIC_DRAW);

// set up vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position)); // vertices
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); // normals
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord)); // normals

// Create and bind a BO for index data
GLuint ibuffer;
glGenBuffers(1, &ibuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer);

// copy data into the buffer object
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexdata.size() * sizeof(GLubyte), &indexdata[0], GL_STATIC_DRAW);

glBindVertexArray(0);

while(1){
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glEnable(GL_LIGHTING);
    glShadeModel( GL_SMOOTH );
    glEnable( GL_TEXTURE_2D );

    glViewport( 0, 0, (float)renderWidth/1, (float)renderHeight/1. );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60, (float)renderWidth/(float)renderHeight, 0.1, 10000. );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    glPushMatrix();
    glTranslatef(0,-0.5,-0.5);
    glBindVertexArray(vao);
    glDrawElements(GL_TRIANGLES, indexdata.size(), GL_UNSIGNED_BYTE, (void*)0);
    glPopMatrix();

    glutSwapBuffers();
    glutPostRedisplay();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    glutMainLoopEvent();
}

我不明白我做错了什么。我可以用普通的glVertex正常地绘制人脸,但是速度太慢了。所以我想使用顶点缓冲区,但是代码总是给出垃圾输出。为什么会这样?编辑:
我已经解决了这个问题,但是我的法线现在是错误的。如果我用顶点和法线调用正常地绘制它,它会工作:

std::vector<Vertex> vertexdata;
for(int i=0; i<object.vertices.size(); i++){
    Vertex v;
    v.position[0] = object.vertices.at(i).coords[0];
    v.position[1] = object.vertices.at(i).coords[1];
    v.position[2] = object.vertices.at(i).coords[2];
    v.normal[0] = object.computedNormals.at(i).coords[0];
    v.normal[1] = object.computedNormals.at(i).coords[1];
    v.normal[2] = object.computedNormals.at(i).coords[2];
    vertexdata.push_back(v);
}

std::vector<GLushort> indexdata;
for(int i=0; i<object.faces.size(); i++){
    OBJFace& face = object.faces.at(i);
    indexdata.push_back(face.items[0].vertexIndex);
    indexdata.push_back(face.items[1].vertexIndex);
    indexdata.push_back(face.items[2].vertexIndex);

    glBegin(GL_POLYGON);
    glNormal3fv(vertexdata[face.items[0].vertexIndex].normal);
    glVertex3fv(vertexdata[face.items[0].vertexIndex].position);
    glNormal3fv(vertexdata[face.items[1].vertexIndex].normal);
    glVertex3fv(vertexdata[face.items[1].vertexIndex].position);
    glNormal3fv(vertexdata[face.items[2].vertexIndex].normal);
    glVertex3fv(vertexdata[face.items[2].vertexIndex].position);
    glEnd();
}

但是,如果将其与“顶点缓冲区”一起使用,则不会:

std::vector<Vertex> vertexdata;
for(int i=0; i<object.vertices.size(); i++){
    Vertex v;
    v.position[0] = object.vertices.at(i).coords[0];
    v.position[1] = object.vertices.at(i).coords[1];
    v.position[2] = object.vertices.at(i).coords[2];
    v.normal[0] = object.computedNormals.at(i).coords[0];
    v.normal[1] = object.computedNormals.at(i).coords[1];
    v.normal[2] = object.computedNormals.at(i).coords[2];
    vertexdata.push_back(v);
}

std::vector<GLushort> indexdata;
for(int i=0; i<object.faces.size(); i++){
    OBJFace& face = object.faces.at(i);
    indexdata.push_back(face.items[0].vertexIndex);
    indexdata.push_back(face.items[1].vertexIndex);
    indexdata.push_back(face.items[2].vertexIndex);
}

glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbuffer);

// copy data into the buffer object
glBufferData(GL_ARRAY_BUFFER, vertexdata.size() * sizeof(Vertex), &vertexdata[0], GL_STATIC_DRAW);

// set up vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position)); // vertices
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); // normals
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord)); // normals

// Create and bind a BO for index data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer);

// copy data into the buffer object
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexdata.size() * sizeof(GLushort), &indexdata[0], GL_STATIC_DRAW);

glBindVertexArray(0);

glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, indexdata.size(), GL_UNSIGNED_SHORT,     (void*)0);

2ekbmq32

2ekbmq321#

除了尼可波拉斯的回答之外

看起来像是因为索引的数量太多,无法以字节(GLubyte)来编码。一个字节可以存储[0,255]范围内的数据,因此一个字节只能编码256个索引。请改用GLushortGLushort的范围是[0,65535]:

std::vector<GLushort> indexdata;

....

GLuint ibuffer;
glGenBuffers(1, &ibuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexdata.size()*sizeof(GLushort),
    indexdata.data(), GL_STATIC_DRAW);

....

glDrawElements(GL_TRIANGLES, indexdata.size(), GL_UNSIGNED_SHORT, (void*)0);
qzwqbdag

qzwqbdag2#

您没有使用着色器进行顶点处理。因此,不能使用通用顶点属性(由VertexAttrib函数提供)。因此,您可以切换到使用着色器,或者使用固定函数属性:

// set up vertex attributes
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, position)); // vertices
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, normal)); // normals
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, texcoord)); // normals

相关问题