OpenGL VBO - 数组步幅错误?

Posted

技术标签:

【中文标题】OpenGL VBO - 数组步幅错误?【英文标题】:OpenGL VBO - Array Stride wrong? 【发布时间】:2012-01-30 07:12:12 【问题描述】:

现在我希望你能帮助我解决这个问题,我已经好几天了,没有找到任何解决方案。我觉得,我已经尝试了所有方法来解决这个问题,但都没有奏效。

首先: 我的场景中有一些使用 VBO 进行渲染的对象。没有别的,没有其他四边形、多边形等。只有屏幕截图中的那些。

我的 VBO 生成代码非常简单,希望清晰易懂:

生成 VBO

public boolean buffer() 
    FloatBuffer[] vertexBuffer = new FloatBuffer[1];
    vertexBuffer[0] = FloatBufferFactory.create(this.triangles.size() * 3 * 11);

    for (Triangle triangle : this.triangles) 
        for (int i = 0; i < 3; i++) 
            vertexBuffer[0].put(triangle.vertex[i].position.x);
            vertexBuffer[0].put(triangle.vertex[i].position.y);
            vertexBuffer[0].put(triangle.vertex[i].position.z);

            vertexBuffer[0].put(triangle.vertex[i].normal.x);
            vertexBuffer[0].put(triangle.vertex[i].normal.y);
            vertexBuffer[0].put(triangle.vertex[i].normal.z);

            vertexBuffer[0].put(triangle.vertex[i].color.r);
            vertexBuffer[0].put(triangle.vertex[i].color.g);
            vertexBuffer[0].put(triangle.vertex[i].color.b);

            vertexBuffer[0].put(triangle.vertex[i].uvset.x);
            vertexBuffer[0].put(triangle.vertex[i].uvset.y);
        
    

    vertexBuffer[0].position(0);

    GLES20.glGenBuffers(1, this.buffer, 0);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.buffer[0]);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer[0].capacity() * 4, vertexBuffer[0], GLES20.GL_STATIC_DRAW);

    return true;

非常简单:我自己在 FloatBufferFactory 中的函数创建了一个具有三角形计数 * 3 * 11 * 4 字节的 Floatbuffer。 然后我将数据放入其中,用于三角形的每个顶点。

我的逻辑:12 个字节(3 * 4 个字节)用于一个顶点,12 个字节用于一个法线位置,12 个字节用于 Vertexcolordata,8 个字节用于 UV 坐标。

渲染

当我渲染网格时,我使用的函数和另一个一样简单:

public void render() 
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.buffer[0]);

    GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeVertex, 3, GLES20.GL_FLOAT, false, 44, this.buffer[0]);
    GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeNormal, 3, GLES20.GL_FLOAT, false, 44, this.buffer[0] + 12);
    GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeColor, 3, GLES20.GL_FLOAT, false, 44, this.buffer[0] + 24);
    GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeUV, 2, GLES20.GL_FLOAT, false, 44, this.buffer[0] + 36);        

    this.passMaterialUniforms();
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, this.triangles.size() * 3);

现在,按照我的理解,我的逻辑: 一个 Vertex 的所有 Bytes 数据为:12Bytes(位置)+ 12Bytes(正常)+ 12Bytes(颜色)+ 8Bytes(uv)-> 得出结论:每个 Vertex 44 Bytes,因此下一个 Vertex 应该在 44 Bytes 之后。 -> 步幅:每个数据 44 字节。

下一个想法是设置起始偏移量:0Bytes 用于位置,12Bytes 用于正常,24Bytes 用于颜色,36Bytes 用于 uv。 到目前为止一切顺利。

主要问题

现在程序中似乎发生了一些非常非常奇怪的事情。创建超过3个Objects后,前三个之后生成的objects显示错误。

截图如下: 第一个示例并尝试(生成:连续 5 个 Torus):

第二次尝试(生成 2 个球体,1 个圆环,另一个球体,另一个圆环):

如您所见,在第一张图片中,4. 和 5. Torus(Tori?!)被扭曲,看起来像豆子或镜头,或类似的东西。 在第二张图片中,3. Sphere(4.生成的对象)看起来很正常,当你只看位置时,但是纹理坐标很奇怪。

那是为什么呢?我该如何解决这个问题?

谢谢! :)

【问题讨论】:

【参考方案1】:

我认为这是由于您启用属性指针的方式。

这是你写的:

GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeVertex, 3, GLES20.GL_FLOAT, false, 44, this.buffer[0]);
GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeNormal, 3, GLES20.GL_FLOAT, false, 44, this.buffer[0] + 12);
GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeColor, 3, GLES20.GL_FLOAT, false, 44, this.buffer[0] + 24);
GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeUV, 2, GLES20.GL_FLOAT, false, 44, this.buffer[0] + 36);

应该是这样的:

GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeVertex, 3, GLES20.GL_FLOAT, false, 44, 0);
GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeNormal, 3, GLES20.GL_FLOAT, false, 44, 12);
GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeColor, 3, GLES20.GL_FLOAT, false, 44, 24);
GLES20.glVertexAttribPointer(BaseActivity.activeShader.attributeUV, 2, GLES20.GL_FLOAT, false, 44, 36);

无论如何,我建议为偏移计算定义一些常量。

在我的 C 引擎中,我以 sizeof 函数为基础

【讨论】:

这似乎是答案,因为当绑定 VBO 时,glVertexAttribPointer 的最后一个参数是当前绑定缓冲区的字节偏移量,从 0 开始。 @chrise:嘿,我们在两个 ;-) 我第一次接触这个话题时犯了同样的错误 ;-) 很高兴能提供帮助。 @MaurizioBenedetti 嗯,感觉不错;)我们俩都不会再犯同样的错误了! :D

以上是关于OpenGL VBO - 数组步幅错误?的主要内容,如果未能解决你的问题,请参考以下文章

优化流媒体vbo openg

opengl vbo建议[关闭]

opengl交错vbo不渲染到屏幕

切换到使用交错 VBO - 编译但没有绘制 - opengl es 2.0

C++/OpenGL - 绘制立方体 VBO

std::vector<MyClass*> 的 VBO 和正确的步幅