
Simple VBO Troubles
Posted Monday, 13 July, 2009 - 22:29 by avic inHi,
I'm new to opengl and opentk and I'm trying to write a program which takes in data from a device that does a scan of a sample and dynamically renders the data the device collects as a 3d image as the data is collected. To do this I figured I need to use vertex buffer objects so I'm trying to write a little test program hacked together from all the tutorials I can find online. I'm writing in vb .net.
So the test program draws a pyramid on the screen and using the method of rotation from the opentk tutorial (rotate on application.idle) it's supposed to rotate the pyramid. I had this working all right when I used just vertex arrays. But when I switched over to using a vertex buffer object, the rotation speed slowed down drastically, to the point where you can barely see the pyramid moving. Does anyone know what I've done wrong?
Here is how I define my pyramid (it's in form load):
vertexArray = New Double() {0, 1, 0, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1}
Note: I haven't done anything with color at all...there's just one vbo and that's for the vertices...so it's just a white pyramid.
Here is my render function:
Private Sub GlControl1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles GlControl1.Paint If Not loaded Then Return End If GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) GL.MatrixMode(MatrixMode.Modelview) GL.LoadIdentity() GL.Translate(x, 0, -0.5) GL.Rotate(rotation, 1, 1, 0) GL.GenBuffers(1, buffer) GL.BindBuffer(BufferTarget.ArrayBuffer, buffer(0)) GL.BufferData(BufferTarget.ArrayBuffer, vertexArray.Length * 8, vertexArray, BufferUsageHint.StreamDraw) 'size of double = 8 GL.VertexPointer(3, VertexPointerType.Double, 0, IntPtr.Zero) GL.EnableClientState(EnableCap.VertexArray) GL.DrawArrays(BeginMode.TriangleFan, 0, 6) GL.DisableClientState(EnableCap.VertexArray) GL.BindBuffer(BufferTarget.ArrayBuffer, 0) GlControl1.SwapBuffers() End Sub
This is the rotate event handler. It's pretty much copy pasted from the opentk tutorial:
Private Sub rotate() sw.Stop() Dim milliseconds = sw.Elapsed.Milliseconds sw.Reset() sw.Start() Dim deltaRotation = milliseconds / 20.0 rotation += deltaRotation GlControl1.Invalidate() End Sub
And I also have the translate keypress event handler from the tutorial:
Private Sub GlControl1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles GlControl1.KeyDown If e.KeyCode = Keys.Space Then x += 0.01 GlControl1.Invalidate() End If End Sub
Thanks for your help!


Comments
Re: Simple VBO Troubles
You seem like creating the buffer and filling it with data each frame. This causes huge slowdown. And you don't need to enable/disable of VertexArray anymore. Just move the init functionality (GenBuffers & BufferData) out of the paint event handler.
Re: Simple VBO Troubles
What kvark said. Additionaly, if you want to repeatedly update an existing VBO at runtime, either use:
null or IntPtr.Zeroas parameters (tells the driver to invalidate the buffer once it's not used for drawing anymore) and a second call to send the new data (driver will allocate the new storage regardless whether the old data is still in use).Re: Simple VBO Troubles
Thank you very much!
I moved as much of the init code out of the paint subroutine but this didn't seem to help at all. The paint subroutine now only contains these lines:
And these lines are called once at initialization:
I got the same results as before though. I put in a timer control that would update the
rotationvalue and invalidate the glcontrol just to see if that would work and it actually did. Also, it worked equally well regardless of whether the unnecessary initialization code was in the paint subroutine or not and that seemed weird to me. What am I missing? When you use vertex buffers, does something change with when the application deems itself to be idle? Did I not move the right code out of the paint routine? At this point I'm just curious.Also thanks a lot for the information about updating a VBO. That will be very helpful for when I'm writing my real program.
Re: Simple VBO Troubles
This line of code:
is framerate dependent. In other words, the more times you call Paint(), the faster your pyramid will rotate.
To maintain a stable rotation speed, multiply rotation with the elapsed time between two consecutive Paint events. For best results, calculate the elapsed time using a System.Diagnostics.Stopwatch and make sure to reset the Stopwatch every frame:
Re: Simple VBO Troubles
That didn't seem to fix the problem either. Isn't that kind of what I was doing anyway earlier in the Application.Idle event handler? (The rotate() sub from my first post...I guess I forgot to say that
swwas my stopwatch.) Like I said, that was pretty much lifted from the openTK introduction tutorial.Basically my question comes down to this: Am I using the vertex buffer object correctly in my current code? The program worked just fine when I used immediate mode and nothing bad happened when I switched over to using vertex arrays. The fact that the animation speed slowed to a halt when I switched over to VBOs (which as I understand are the preferred method) tells me that I'm doing something wrong. Am I? Or is this some weirdness with the application.idle event? So to reiterate, is this the correct way to use a vertex buffer object? Or am I not including something that I should be? Thanks again for all your help.
Re: Simple VBO Troubles
As long as you update the position according to the frame time, it should work.
What *is* your frametime? Could it be that you are getting so high framerates (low frametimes) that you are hitting into a precision limit? I encountered that on Linux with Ati GL3 drivers. Try adding a call to
System.Threading.Thread.CurrentThread.Sleep(1)into your paint event and see if that helps.Re: Simple VBO Troubles
Whoa. The Thread.Sleep worked like magic. What happened there? Why did I need to put in a sleep when using a VBO and not when I was using vertex arrays or immediate mode? Was it because using a vbo was so fast that the application idle times became too small for the application to handle? If that's the case then all I can say is, sweeeeeeeeeeeet.
Re: Simple VBO Troubles
It's one of two things:
Best solution: enable vsync for fluid-smooth animation (GraphicsContext.VSync = true).
Re: Simple VBO Troubles
Cool. Solved. I enabled vsync for the glcontrol rather than with GraphicsContext. Is there a difference?
Re: Simple VBO Troubles
No, GLControl.VSync is there for convenience (it calls GraphicsContext.VSync internally).