我正在尝试将我的顶点,索引和纹理点设置为VBO:s并使用我的draw方法绘制它们,所有这些都是在TAO / OpenGL TK框架下的C#中完成的。但我的屏幕只显示黑屏。我已经测试过没有VBO:s,然后它可以工作。但是凭借我的顶点,索引和纹理点,我无法成功。
我的代码:
private float[] vertices;
private byte[] indices;
private float[] texture;
private int[] mVertexBuffer;
private int[] mIndicesBuffer;
private int[] mTextureBuffer;
//...Constructor start
vertices = new float[] {
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
};
texture = new float[] {
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
indices = new byte[] {
0, 1, 3, 0, 3, 2, 4, 5, 7, 4, 7, 6,
8, 9, 11, 8, 11, 10,
12, 13, 15, 12, 15, 14,
16, 17, 19, 16, 19, 18,
20, 21, 23, 20, 23, 22,
};
mVertexBuffer = new int[1];
mIndicesBuffer = new int[1];
mTextureBuffer = new int[1];
//...Constructor end
public void setBuffers() {
gl.glGenBuffersARB(1, mVertexBuffer);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mVertexBuffer[0]);
gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB,
(IntPtr)(vertices.Length * sizeof(float)),
vertices, GL.GL_STATIC_DRAW_ARB);
gl.glGenBuffersARB(1, mIndicesBuffer);
gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, mIndicesBuffer[0]);
gl.glBufferDataARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB,
(IntPtr)(indices.Length * sizeof(float)),
indices, GL.GL_DYNAMIC_DRAW_ARB);
gl.glGenBuffersARB(1, mTextureBuffer);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mTextureBuffer[0]);
gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB,
(IntPtr)(texture.Length * sizeof(float)),
texture, GL.GL_STATIC_DRAW_ARB);
}
public void draw()
{
gl.glBegin(gl.GL_TRIANGLES);
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mVertexBuffer[0]);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, mVertexBuffer);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mTextureBuffer[0]);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, mTextureBuffer);
gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, mIndicesBuffer[0]);
gl.glDrawElements(GL.GL_TRIANGLES, indices.Length,
gl.GL_UNSIGNED_BYTE, mIndicesBuffer);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
gl.glEnd();
}
顶点/索引/纹理点在我的C ++ VBO环境中有效,但不在此处。所以我猜我错过了绑定的东西。
答案 0 :(得分:6)
实际上,我也一直在寻找这个星期。现在我有一个正确的工作解决方案。
要成功创建Vertex Buffer Object
,您需要注意几个问题。第一个问题是人们搞砸了。 GL_INDEX_ARRAY
不适用于indices
。使用颜色数组平滑颜色之间的颜色时,应使用GL_INDEX_ARRAY
。
另一个问题是Tao framework
使用IntPtr.Zero
作为偏移而不是普通0
。当glDrawElements
为Vertex Array
时,您将Vertex Buffer Object
调用中的最后一个参数用作GL_ARRAY_BUFFER
。
另一方面,看起来你将两个不同的概念混合在一起。您正在尝试将数据加载到缓冲区中,如果您使用已发布的代码,那么您将完全成功。这里的问题是你使用了错误的indices
命令。对于GL_ELEMENT_ARRAY_BUFFER
,您应该使用Vertex Arrays
。
据说我会使用标准Vertex Buffer Objects
显示一个解决方案,使用public void draw()
{
gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, gl.GL_FLOAT, 0, verticesArray);
gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, textureArray);
//With Vertex Arrays, the last parameter is your pointer to your indices
gl.glDrawElements(gl.GL_TRIANGLES, indices.Length,
gl.GL_UNSIGNED_SHORT, indicesArray);
gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(gl.GL_VERTEX_ARRAY);
}
显示另一个解决方案。我希望这能解决问题。
顶点阵列:
//This should be used in the constructor
//or in another method than the draw method
mVertexBuffer = new int[1];
mTextureBuffer = new int[1];
mIndexBuffer = new int[1];
gl.glGenBuffers(1, mVertexBuffer);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mVertexBuffer[0]);
gl.glBufferData(gl.GL_ARRAY_BUFFER,
(IntPtr)(verticesArray.Length * sizeof(float)),
verticesArray, gl.GL_STATIC_DRAW);
gl.glGenBuffers(1, mTextureBuffer);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mTextureBuffer[0]);
gl.glBufferData(gl.GL_ARRAY_BUFFER,
(IntPtr)(textureArray.Length * sizeof(float)),
textureArray, gl.GL_STATIC_DRAW);
gl.glGenBuffers(1, mIndexBuffer);
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer[0]);
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
(IntPtr)(indicesArray.Length * sizeof(short)),
indicesArray, gl.GL_STATIC_DRAW);
//Your draw method
public void draw()
{
gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mVertexBuffer[0]);
//Notice: IntPtr.Zero is used...
gl.glVertexPointer(3, gl.GL_FLOAT, 0, IntPtr.Zero);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mTextureBuffer[0]);
//Notice: IntPtr.Zero is used...
gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, IntPtr.Zero);
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer[0]);
//Notice: IntPtr.Zero is used. Last parameter is
//an offset using Vertex Buffer Objects and in Vertex Arrays
//it is a pointer
gl.glDrawElements(gl.GL_TRIANGLES, indices.Length,
gl.GL_UNSIGNED_SHORT, IntPtr.Zero);
//Remember to unbind your buffer to prevent it to destroy
//other draw calls or objects
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0);
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0);
gl.glDisableClientState(gl.GL_VERTEX_ARRAY);
gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY);
}
顶点缓冲区对象:
{{1}}
我希望这很有用,我花了一段时间才弄清楚这一点。
答案 1 :(得分:1)
内联评论/修改。我没有设置测试这个,但它已经接近了:
public void draw()
{
//gl.glBegin(gl.GL_TRIANGLES); // no glBegin/glEnd at all -- that's immediate mode
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
gl.glEnableClientState(GL.GL_INDEX_ARRAY); // also using index array
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mVertexBuffer[0]);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0); // with vertex arrays the last argument is a pointer, with VBOs it's an *offset*
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mTextureBuffer[0]);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0); // ditto
gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, mIndicesBuffer[0]);
//gl.glDrawElements(GL.GL_TRIANGLES, indices.Length, gl.GL_UNSIGNED_BYTE, mIndicesBuffer); // this is vertex-array style
gl.glIndexPointer(GL.GL_UNSIGNED_BYTE, 0, 0); // as above for all pointers
gl.glDrawArrays(GL.GL_TRIANGLES, 0, indices.length);
// You can probably leave these enabled to save time:
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL.GL_INDEX_ARRAY);
//gl.glEnd();
}
答案 2 :(得分:1)
这是一个基于Shelly答案的工人阶级示例:
class Vbo {
private float[] vertices;
private ushort[] indices;
private float[] texture;
private int[] mVertexBuffer;
private int[] mIndicesBuffer;
private int[] mTextureBuffer;
public Vbo() {
vertices = new float[] {
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
};
texture = new float[] {
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
indices = new ushort[] {
0, 1, 3, 0, 3, 2, 4, 5, 7, 4, 7, 6,
8, 9, 11, 8, 11, 10,
12, 13, 15, 12, 15, 14,
16, 17, 19, 16, 19, 18,
20, 21, 23, 20, 23, 22,
};
for (int i = 0; i < vertices.Length; i++) {
vertices[i] *= 2;
}
mVertexBuffer = new int[1];
mIndicesBuffer = new int[1];
mTextureBuffer = new int[1];
Gl.glGenBuffers(1, mVertexBuffer);
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, mVertexBuffer[0]);
Gl.glBufferData(Gl.GL_ARRAY_BUFFER,
(IntPtr)(vertices.Length * sizeof(float)),
vertices, Gl.GL_STATIC_DRAW);
Gl.glGenBuffers(1, mTextureBuffer);
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, mTextureBuffer[0]);
Gl.glBufferData(Gl.GL_ARRAY_BUFFER,
(IntPtr)(texture.Length * sizeof(float)),
texture, Gl.GL_STATIC_DRAW);
Gl.glGenBuffers(1, mIndicesBuffer);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, mIndicesBuffer[0]);
Gl.glBufferData(Gl.GL_ELEMENT_ARRAY_BUFFER,
(IntPtr)(indices.Length * sizeof(ushort)),
indices, Gl.GL_STATIC_DRAW);
}
public void Render() {
Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY);
Gl.glEnableClientState(Gl.GL_TEXTURE_COORD_ARRAY);
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, mVertexBuffer[0]);
//Notice: IntPtr.Zero is used...
Gl.glVertexPointer(3, Gl.GL_FLOAT, 0, IntPtr.Zero);
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, mTextureBuffer[0]);
//Notice: IntPtr.Zero is used...
Gl.glTexCoordPointer(2, Gl.GL_FLOAT, 0, IntPtr.Zero);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, mIndicesBuffer[0]);
//Notice: IntPtr.Zero is used. Last parameter is
//an offset using Vertex Buffer Objects and in Vertex Arrays
//it is a pointer
Gl.glDrawElements(Gl.GL_TRIANGLES, indices.Length, Gl.GL_UNSIGNED_SHORT, IntPtr.Zero);
//Remember to unbind your buffer to prevent it to destroy
//other draw calls or objects
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, 0);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, 0);
Gl.glDisableClientState(Gl.GL_VERTEX_ARRAY);
Gl.glDisableClientState(Gl.GL_TEXTURE_COORD_ARRAY);
}
}