I'm trying to set my vertices, indices and texture points to VBO:s and the draw them with my draw method, all this in C# under TAO/OpenGL TK framwork. But my screen shows only a black screen. I've tested without VBO:s, and then it works. But with my vertices, indices and texture points I can't success.
My code:
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();
}
The vertices/indices/texture points works in my C++ VBO enviroment, but not here. So I'm guessing I had missed something with the bind stuff.
Actually, I've been looking for this some weeks too. Now I have a correct working solution.
There are several problems you need to be aware of to successfully create a Vertex Buffer Object
. The first problem is that people mess things up. GL_INDEX_ARRAY
isn't for your indices
. You shall use GL_INDEX_ARRAY
when you use a color array for smoothing out the color(s) between your verts.
Another problem is that the Tao framework
uses IntPtr.Zero
for an offset and not an ordinary 0
. You're using the last parameter in the glDrawElements
call as Vertex Array
style when it's a Vertex Buffer Object
.
On the other hand, it looks like you're mixing two different concepts together. You're trying to load your data into a buffer, which you totally will success with if you're using your posted code. The problem here though is that you're using wrong GL_ARRAY_BUFFER
command. For your indices
you should use GL_ELEMENT_ARRAY_BUFFER
.
With that said I will show one solution using standard Vertex Arrays
and another using Vertex Buffer Objects
. I hope this will clear things out.
Vertex Arrays:
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);
}
Vertex Buffer Objects:
//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);
}
I hope this was useful, it took me a while to figure this out.