pooya's picture

Slow rendering

Hi all
I used VBO to accelerate rendering process because my vertices matrix is updated per frame. The problem is, when I run my application it works properly JUST FOR ONE MIN and then it stops rendering for couple of seconds and then it comes back again but very (very) slowly.
Any idea to solve my problem?
Thanks in advance :D

.
.
.
 
GL.PushMatrix();
            {
            for (int i = 0; i < 370000; i++)
            {
                vertices[i] = new Vector3(i,i,i); //just as an example
            }
            vbo_size = vertices.Length; 
            GL.GenBuffers(1, out vbo_id);
            GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_id);
            GL.BufferData(BufferTarget.ArrayBuffer,
                          new IntPtr(vertices.Length * BlittableValueType.StrideOf(vertices)),
                          vertices, BufferUsageHint.DynamicDraw);
 
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_id);
            GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
            GL.DrawArrays(BeginMode.Points, 0, vbo_size);
            }
            GL.PopMatrix();
            SwapBuffers();

Comments

Comment viewing options

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

Well your creating a new vbo every frame and never deleting it.
If the geometry is dynamic, you should still create it once and just update the contents.

Robmaister's picture

Basically what ERP said, you're assigning some memory in VRAM (the graphics card's RAM) every single frame and never deleting it. After about a minute you run out of VRAM, after that I'm not sure what it's doing, but whatever it does it'll be really slow.

What you want to do is create the VBO once at the beginning of the program and store vbo_id somewhere. Instead of calling GenBuffers, BindBuffer, BufferData, BindBuffer to draw, only call the last BindBuffer, as you have already generated the buffer and stored your data there at the beginning of the program. If the vertex data is dynamic (changing every frame), avoid the GenBuffers call, only bind it once, then call BufferData and then draw.

Note that you can call BufferSubData if the data you're planning on passing in is of equal or smaller size to what you originally assigned.

Oh yeah, and if you are updating vertices each frame because the object is moving, rotating, or scaling, consider using a Matrix4 for those transformations and then call LoadMatrix inside the draw loop. You'll want to PushMatrix before each object and PopMatrix afterwards. Not doing so will accumulate all the object's transformation matrices.

Also, you can change "new IntPtr(0)" to "IntPtr.Zero", I think even just "0" works...