VBO 不使用 UV 坐标

Posted

技术标签:

【中文标题】VBO 不使用 UV 坐标【英文标题】:VBO doesn't use UV coordinates 【发布时间】:2012-07-08 01:45:30 【问题描述】:

我的渲染方法目前是这样的:

void Renderer::render() 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    checkGlError("glClear");

    EntityCamera* camera = (EntityCamera*) resourceManager_->getResource(GHOST_CAMERA);

    mat4 proj;
    Matrix::projection3D(proj, 45.0f,
            (float) nScreenWidth_ / nScreenHeight_, GHOST_NEAR_DISTANCE, GHOST_FAR_DISTANCE);

    mat4 view;
    Matrix::multiply(proj, camera_->getMatrix(), view);
    camera->extractPlanes(view);

    for (vector<Node*>::const_iterator it = renderArray_.begin(); it != renderArray_.end();
            it++) 
        Node* node = *it;
        if (!node->isRenderable()) 
            continue;
        
        if (node->hasBV() && node->getBV()->isInFrustum(camera, node) == BoundingVolume::OUTSIDE) 
            LOGI("Node %s is outside :O", node->getName().c_str());
            continue;
        
        EntityModel* entity =
                static_cast<EntityModel*>(resourceManager_->getResource(
                        (*it)->getEntity()));
        if (entity == 0 || entity->getVertices() == 0 || entity->getVertices()->size() == 0) 
            LOGI("Empty entity %s.", node->getName().c_str());
            continue;
        
        Resource* resource = resourceManager_->getResource(node->getShader());
        Shader* shader = static_cast<Shader*>(resource);
        Resource* resource2 = resourceManager_->getResource(entity->getTexture());
        Image* image = static_cast<Image*>(resource2);
        mat4 res;
        Matrix::multiply(view, node->getMatrix(), res);

        // Select shader program to use.
        glUseProgram(shader->getId());
        checkGlError("glUseProgram");

        int matrix = glGetUniformLocation(shader->getId(), "uWVP");
        int texture = glGetUniformLocation(shader->getId(), "texture_0");
        checkGlError("glGetUniformLocation");
        int textureCoords = glGetAttribLocation(shader->getId(), "attrTexCoords");
        int vertices = glGetAttribLocation(shader->getId(), "attrPos");
        checkGlError("glGetAttribLocation");

        // Specify WVP matrix.
        glUniformMatrix4fv(matrix, 1, false, res);
        checkGlError("glUniformMatrix4fv");

        // Load vertex positions.
        if (!entity->isCompiled()) 
            //LOGI("Entity %s, not compiled.", entity->getName().c_str());
            continue;
        
        glEnableVertexAttribArray(vertices);
        checkGlError("glEnableVertexAttribArray");
        //glVertexAttribPointer(vertices, 3, GL_FLOAT, GL_FALSE, 0,
        //      &(*entity->getVertices())[0]);
        //LOGI("%s vbo id: %d", node->getName().c_str(), entity->getVBO());
        glBindBuffer(GL_ARRAY_BUFFER, entity->getVBO());
        checkGlError("glBindBuffer");
        glVertexAttribPointer(vertices, 3, GL_FLOAT, GL_FALSE, 0, 0);
        checkGlError("glVertexAttribPointer");
        // Load UV coordinates.
        glEnableVertexAttribArray(textureCoords);
        checkGlError("glEnableVertexAttribArray");
        glVertexAttribPointer(textureCoords, 2, GL_FLOAT, GL_FALSE, 0,
                &(*entity->getTextureCoords())[0]);
        checkGlError("glVertexAttribPointer");

        // Bind the texture.
        glActiveTexture(GL_TEXTURE0);
        checkGlError("glActiveTexture");
        glBindTexture(GL_TEXTURE_2D, image->getId());
        checkGlError("glBindTexture");
        glUniform1i(texture, 0);
        checkGlError("glUniform1i");

        if (entity->hasIndices()) 
            vector<vector<GLushort>*>* indices = entity->getIndices();
            for (unsigned int i = 0; i < indices->size(); i++) 
                if (entity->hasBoundingVolumes()) 
                    BoundingVolume* volume = (*entity->getBoundingVolumes())[i];
                    if (volume->isInFrustum(camera, node) == BoundingVolume::OUTSIDE) 
                        continue;
                    
                
                vector<GLushort>* ind = (*indices)[i];
                glDrawElements(GL_TRIANGLES, ind->size(), GL_UNSIGNED_SHORT, &(*ind)[0]);
                checkGlError("glDrawElements");
            
        
        else 
            glDrawArrays(GL_TRIANGLES, 0, entity->getVertices()->size() / 3);
            checkGlError("glDrawArrays");
        
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        checkGlError("glBindBuffer");
    


我最近刚尝试使用 VBO,在我直接发送顶点数据之前一切正常,纹理映射正确。现在我用 VBO 更改了顶点数组,即使它有效,也没有应用任何纹理,我只能看到黑色物体。


    我的纹理可能有什么问题? 为什么当我更改 glVertexAttribPointer(vertices, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, entity->getVBO()) 的行序;我得到毁容的物体?这是我使用的正确调用顺序吗?

【问题讨论】:

我还没有仔细研究你的代码,但是操作的一般顺序是 1. 绑定对象 2. 设置对象参数 3. 将数据加载到对象中。步骤 2 和 3 可以按规范互换,但给定的顺序触发的驱动程序错误较少。并不是说活动单元(如纹理单元或类似单元)甚至在绑定之前就已经存在。所以对于纹理首先设置活动单元,然后绑定。 【参考方案1】:

您是从普通内存发送 UV 坐标,而您似乎是从 VBO 发送顶点坐标。这可能效率不高,您应该在 VBO 中同时拥有两个数据集以利用 VBO 的优势。

话虽如此,我认为您的问题是您在发送 UV 坐标之前没有解除绑定 VBO。你的代码应该是:

glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribPointer(textureCoords, 2, GL_FLOAT, GL_FALSE, 0,
            &(*entity->getTextureCoords())[0]);

我认为您的 getTextureCoords() 不会在您的 VBO 中返回偏移量。

【讨论】:

这确实是解绑的情况,现在可以了。是的,我计划稍后将纹理坐标添加到同一个 VBO,我只想分几步完成,以便更好地了解它是如何工作的。谢谢。

以上是关于VBO 不使用 UV 坐标的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Blender 导出脚本中导出每个顶点的 UV 坐标

OpenGL 更新不同大小的 VBO 数据

LWJGL VBO 三角形纹理坐标不起作用

OpenGL |在 UV 坐标处渲染顶点

将 Blender 的 UV 向量转换为 3D 坐标

如何使用不同的 VAO、VBO 绘制 2 个或更多对象?