1

当我使用顶点数组对象时,我在使用 OpenGL ES2 的 nexus 4 上遇到了一个奇怪的错误。

以下是一些信息:

  • 当我不使用 VAO 时一切正常
  • 一切都可以在其他设备和 Ipad 2 上使用和不使用 VAO
  • glGetError() 没有返回错误
  • 由于错误,游戏中出现了一些故障(某些元素出现了另一种现象)
  • 我的 VBO 是动态的(我用 glBufferData 更新它们)

这是错误:

Adreno-ES20(16818): : validate_vertex_attrib_state: 在绘图调用中没有启用顶点属性!

这是我的代码:

void Renderer::setVertexBuffer( Uint32 stream, const Base* vertexBuffer, std::size_t stride, Uint32 startVertex, Uint32 endVertex )
{
    static const bool VAOSupported = this->isExtensionPresent(VertexArrayObject);
    if( VAOSupported )
    {
        if( vertexBuffer->vao.isReady() == false )
        {
            // Bind VAO.
            glBindVertexArrayOES( vertexBuffer->vao.getId() );

            // Bind filled VBO.
            glCheck( glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer->getId() ) );

            // Set attributs with vertex format.
            this->applyVertexFormat( startVertex, endVertex );

            // Unbind buffer and VAO.
            glBindVertexArrayOES(0);

            vertexBuffer->vao.isReady(true);
        }

        glBindVertexArrayOES( vertexBuffer->vao.getId() );
    }
    else
    {
        glBindVertexArrayOES(0);
        glCheck( glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer->getId() ) );
        this->applyVertexFormat( startVertex, endVertex );
    }
}

////////////////////////////////////////////////////////////
void Renderer::setIndexBuffer( const Buffer* indexBuffer, std::size_t stride )
{
    glCheck( glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer->getId() ) );
    this->usedIndexBufferStride = stride;
}

////////////////////////////////////////////////////////////
void Renderer::applyVertexFormat( Uint32 startVertex, Uint32 endVertex )
{
    const Uint32 stride = this->vertexFormat->getStride();
    for( Uint32 i = 0; i < this->vertexFormat->getAttributCount(); i++ )
    {
        const VertexElement& element = this->vertexFormat->getAttribut(i);

        glCheck( glEnableVertexAttribArray( element.usage ) );
        glCheck( glVertexAttribPointer( element.usage,
                                       element.type,
                                       element.type,
                                       element.normalize,
                                       stride,
                                       BUFFER_OFFSET(element.offset + startVertex * stride ) ) );
    }
}

这是我使用它的方式:

renderer->setFormat(geometry->getFormat()); // Only save a pointer to the format to use in apply method.
renderer->setVertexBuffer(geometry->getVertexBuffer());
renderer->setIndexBuffer(geometry->getIndexBuffer());
renderer->draw(GL_TRIANGLES, geometry->indiceCount);
4

1 回答 1

0

您确定usage该字段的名称是合适的名称吗?该名称定义了将指针与哪个属性数组关联?缓冲区对象已经有一个称为使用的属性(例如GL_DYNAMIC_DRAW)。location可能更有意义。

但是,您的代码中有一个更严重的问题:

element.type不能既是数据的类型又是组件的数量。glVertexAttribPointer (...)仅接受1234 个组件,枚举类型的GL_FLOAT远大于4

假设glCheck( ... )正确换glGetError (...)行,这种情况应该是可以说明GL_INVALID_VALUE的。

这让我相信你的循环void Renderer::applyVertexFormat( Uint32 startVertex, Uint32 endVertex )永远不会被触发。

于 2014-02-02T01:38:59.007 回答