yuriks's picture

VBO problems: nothing gets drawn

Hey. I'm having some issues using VBOs. This is the code I have right now:

        public void Draw(Point position)
        {
            int[] vertexData = {
                                                     position.X, position.Y,
                                                     position.X + Image.Width, position.Y,
                                                     position.X, position.Y + Image.Height,
                                                     position.X + Image.Width, position.Y + Image.Height
                                               };
 
            uint glVertexBuffer;
 
            GL.GenBuffers(1, out glVertexBuffer);
            GL.BindBuffer(BufferTarget.ArrayBuffer, glVertexBuffer);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexData.Length * sizeof(int)), vertexData, BufferUsageHint.StreamDraw);
 
            int size; // This is 32, like it should be so I assumed the buffer got uploaded correctly.
            GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferMapped, out size);
 
            GL.EnableClientState(EnableCap.VertexArray);
 
            GL.BindBuffer(BufferTarget.ArrayBuffer, glVertexBuffer);
            GL.VertexPointer(2, VertexPointerType.Int, 0, 0);
 
            //GL.BindTexture(TextureTarget.Texture2D, glTexture);
            GL.Disable(EnableCap.Texture2D);
 
            GL.Color3(1.0f, 1.0f, 1.0f);
 
            GL.BindBuffer(BufferTarget.ArrayBuffer, glVertexBuffer);
            GL.DrawArrays(BeginMode.TriangleStrip, 0, vertexData.Length);
 
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
            GL.DisableClientState(EnableCap.VertexArray);
 
            GL.DeleteBuffers(1, ref glVertexBuffer);
 
            /*GL.Begin(BeginMode.TriangleStrip);
            GL.TexCoord2(0, 0);
            GL.Vertex2(position.X, position.Y);
 
            GL.TexCoord2(1, 0);
            GL.Vertex2(position.X + Image.Width, position.Y);
 
            GL.TexCoord2(0, 1);
            GL.Vertex2(position.X, position.Y + Image.Height);
 
            GL.TexCoord2(1, 1);
            GL.Vertex2(position.X + Image.Width, position.Y + Image.Height);
            GL.End();*/
        }

I call SwapBuffer later on in another function. The commented out immediate mode section is what I want to replace, and that works fine, but using VBOs, nothing get's drawn. I've checked using GL.GetError after every function call and no errors are reported. Anyone got a clue on what I'm doing wrong?


Comments

Comment viewing options

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

As he said, he fixed the problem in his code (not the sample posted here) :-)

objarni's picture

So why is there any problem with the VertexPointer method? I cannot see a problem if there is an error message from the compiler .. just add an IntelliSense comment "Use IntPtr.Zero instead of 0"

the Fiddler's picture

There is no error message: "0 isn't converted to an IntPtr, it's taken as an object of type Int32, that's why I explicitly need to cast it. When you pass 0, the object overload is used (which passes a reference to the local variable that contains 0, instead of 0 itself).

In other words: the compiler does what it's told, which is not what you expect.

I've spoken with the guy behind PyOpenGL, who explained how they build the PyOpenGL docs. I hope to add these docs to intellisense, along with custom annotations, which will hopefully help avoid such issues in the future.

objarni's picture

When you pass 0, the object overload is used (which passes a reference to the local variable that contains 0, instead of 0 itself).

I guess the natural question then is: why do we need an object overload for VertexPointer?

the Fiddler's picture

Let me twist your question around: do you know, off-hand, how to obtain a void* to a managed object? :-)

That's the main reason. The other is backwards compatibility between Tao 2.0 and Tao 1.3.

Another question that gets asked from time to time is why not use a generic method. The main reason is that DllImports can't be generics and, besides, generics would needlessly increase memory requirements and complicate pinning.

objarni's picture

Let me twist your question around: do you know, off-hand, how to obtain a void* to a managed object? :-)

Nope :)

But then again: the IntPtr in VertexPointer is supposed to be targeted at an unmanaged resource, right? Pointing it towards a managed object wouldn't be correct.

the Fiddler's picture

But then again: the IntPtr in VertexPointer is supposed to be targeted at an unmanaged resource, right? Pointing it towards a managed object wouldn't be correct.
Not necesserily. As long as the managed resource has the correct format and you know it won't move, you are perfectly free to pass a pointer to that.

Of course, this only holds true for functions that don't retain the resource after the function returns. Fortunately for us, almost everything in OpenGL works like this - and everything that doesn't, has been deprecated in GL3.0. This means, you are free to create VBOs, textures, shaders from managed objects (say, an array of floats or Vector3 structs).

The only thing you need to avoid are legacy, client-side vertex arrays (VAs).

objarni's picture

But isn't VertexPointer the API to specify data for a VA?

And therefore the object-overload should be unnecessary?

Why not put in an overload for VertexPointer for the specific case of a managed float-array? Having a parameter of type "object" is less-than-elegant in C#, and as we have seen in this thread confusing..

the Fiddler's picture

The answer is simple actually: the last parameter is not constrained to float arrays.

Why don't you check yourself, if you don't believe me? :-)

objarni's picture

Well yeah, it is a void* in c. So what? :)

If we can make it better, why should we not? OpenTK is not a 1-1 mapping of the OpenGL API.