raiderred's picture

Problem loading models with VBO

Hello all,

I am having trouble with trying to load a model and display it on the screen. I am wondering if there is anything wrong with the logic in the code below or if anyone has any pointers?

Currently this is my logic for initializing and drawing a model:

Struct for Vertex Data

[Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct VertexInterleaved
    {
        public Vector4 Position;
        public Vector3 Normal;
        public Vector2 TextureCoordinate;
 
        public static int VertexStride()
        {
            return (9 * sizeof(float));
        }
    }

Initialization Code

public void Initialize()
        {
            GL.GenBuffers(1, out mesh.vbo);
            GL.BindBuffer(BufferTarget.ArrayBuffer, mesh.vbo);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(mesh.vertices.Length * VertexInterleaved.VertexStride()),   mesh.vertices, BufferUsageHint.StaticDraw);
            initialized = true;
        }

Drawing Code

GL.Enable(EnableCap.Texture2D);
 
            GL.BindTexture(TextureTarget.Texture2D,texture.Vbo);
            GL.BindBuffer(BufferTarget.ArrayBuffer, mesh.vbo);
 
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);
            GL.EnableClientState(ArrayCap.TextureCoordArray);
 
            GL.VertexPointer(4, VertexPointerType.Float, VertexInterleaved.VertexStride(), (IntPtr)(0));
            GL.NormalPointer(NormalPointerType.Float, VertexInterleaved.VertexStride(), (IntPtr)(4 * sizeof(float)));
            GL.TexCoordPointer(2, TexCoordPointerType.Float, VertexInterleaved.VertexStride(), (IntPtr)(7 *    sizeof(float)));
 
            GL.DrawArrays(BeginMode.Triangles, 0, mesh.vertices.Length);
 
            GL.DisableClientState(ArrayCap.VertexArray);
            GL.DisableClientState(ArrayCap.NormalArray);
            GL.DisableClientState(ArrayCap.TextureCoordArray);
 
            GL.Disable(EnableCap.Texture2D);

Thanks in advance!


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
mOfl's picture

You are mixing up the deprecated Vertex Arrays with Vertex Buffer Objects. You set up your VBO correctly but then try to draw from Vertex Arrays. The correct way (without deprecated calls) to bind and draw the VBO(s) is something like:

uint vertexPositionLocation = glGetAttribLocation(shaderHandle, "inVertexPosition");
 
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);
glEnableVertexAttribArray(vertexPositionLocation);
glVertexAttribPointer(vertexPositionLocation , 4, GL_FLOAT, GL_FALSE, 0, 0);
 
// normals, texcoords etc. here
 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
 
glDrawElements(GL_TRIANGLES, numTriangles * 3, GL_UNSIGNED_INT, 0);

To work with VBOs the correct way, there are several things you have to change in your code. You need to drop the Vertex Array code, use a vertex shader and an index buffer from which you draw the triangles. If this whole restructuring is too much work for you, you might have a look at the static VBO demo that comes with OpenTK. They also use deprecated calls ("GL.VertexPointer", "GL.ColorPointer" - you don't do this nowadays, that's fixed-function pipeline), but this way the demo runs without using a shader and stays simple. If you are a beginner, I would, however, strongly encourage you to NOT get used to the gl*Pointer stuff but learn to use the state-of-the-art mechanisms.

Besides that,

GL.BindTexture(TextureTarget.Texture2D,texture.Vbo);

is there any good reason why you are binding a VBO handle (as the name suggests) to a texture target? What would you expect from that and how would you create a VBO from a texture?

raiderred's picture

Thanks for the help. I was getting confused with all the depreciated code examples out there. I went ahead and restructured my code as you described and now it is working.

As for the BindTexture part, that was just a naming mistake. That value is really the id that is called from GL.GenTexture().