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 - 数组步幅错误?的主要内容,如果未能解决你的问题,请参考以下文章