LWJGL Forum

Programming => OpenGL => Topic started by: xman84 on September 26, 2010, 03:44:39

Title: drawelements for many identical objects
Post by: xman84 on September 26, 2010, 03:44:39
I would like to draw many cubes however when I get to around 1000 it starts to slow the frame rate down. Is there a way I can make a single draw call to open gl to draw them instead of making a drawelements call for every cube. The only difference between the cubes would be position and color.
Title: Re: drawelements for many identical objects
Post by: broumbroum on September 26, 2010, 15:06:29
This is a feature of gllist().  See opengl doc about it!  :D
Title: Re: drawelements for many identical objects
Post by: ParticleSwarm on October 22, 2010, 01:25:54
Can you expand on this a little bit? I'm using a display list to render but it doesn't seem to help much.

Here is where I make the list:

   static void buildLists() {
    float x = 1;
    float y = 1;
    float z = 1;
    float x2 = (float) (x + EdgeSize);
    float y2 = (float) (y + EdgeSize);
    float z2 = (float) (z + EdgeSize);
       box = GL11.glGenLists(1);                              
       GL11.glNewList(box,GL11.GL_COMPILE);              
           GL11.glBegin(GL11.GL_QUADS);

               GL11.glTexCoord2f(0.0f, 0.0f);GL11.glVertex3f( x2, y2,z);         // Top Right Of The Quad (Top)
               GL11.glTexCoord2f(1.0f, 0.0f);GL11.glVertex3f(x, y2,z);         // Top Left Of The Quad (Top)
               GL11.glTexCoord2f(1.0f, 1.0f);GL11.glVertex3f(x, y2, z2);         // Bottom Left Of The Quad (Top)
               GL11.glTexCoord2f(0.0f, 1.0f);GL11.glVertex3f( x2, y2, z2);         // Bottom Right Of The Quad (Top)
               
               GL11.glTexCoord2f(1.0f, 0.0f);GL11.glVertex3f( x2,y, z2);         // Top Right Of The Quad (Bottom)
               GL11.glTexCoord2f(1.0f, 1.0f);GL11.glVertex3f(x,y, z2);         // Top Left Of The Quad (Bottom)
               GL11.glTexCoord2f(0.0f, 1.0f);GL11.glVertex3f(x,y,z);         // Bottom Left Of The Quad (Bottom)
               GL11.glTexCoord2f(0.0f, 0.0f);GL11.glVertex3f( x2,y,z);         // Bottom Right Of The Quad (Bottom)
               
               GL11.glTexCoord2f(0.0f, 1.0f);GL11.glVertex3f( x2, y2, z2);         // Top Right Of The Quad (Front)
               GL11.glTexCoord2f(0.0f, 0.0f);GL11.glVertex3f(x, y2, z2);         // Top Left Of The Quad (Front)
               GL11.glTexCoord2f(1.0f, 0.0f);GL11.glVertex3f(x,y, z2);         // Bottom Left Of The Quad (Front)
               GL11.glTexCoord2f(1.0f, 1.0f);GL11.glVertex3f( x2,y, z2);         // Bottom Right Of The Quad (Front)
               
               GL11.glTexCoord2f(1.0f, 1.0f);GL11.glVertex3f( x2,y,z);         // Bottom Left Of The Quad (Back)
               GL11.glTexCoord2f(0.0f, 1.0f);GL11.glVertex3f(x,y,z);         // Bottom Right Of The Quad (Back)
               GL11.glTexCoord2f(0.0f, 0.0f);GL11.glVertex3f(x, y2,z);         // Top Right Of The Quad (Back)
               GL11.glTexCoord2f(1.0f, 0.0f);GL11.glVertex3f( x2, y2,z);         // Top Left Of The Quad (Back)
               
               GL11.glTexCoord2f(1.0f, 0.0f);GL11.glVertex3f(x, y2, z2);         // Top Right Of The Quad (Left)
               GL11.glTexCoord2f(1.0f, 1.0f);GL11.glVertex3f(x, y2,z);         // Top Left Of The Quad (Left)
               GL11.glTexCoord2f(0.0f, 1.0f);GL11.glVertex3f(x,y,z);         // Bottom Left Of The Quad (Left)
               GL11.glTexCoord2f(0.0f, 0.0f);GL11.glVertex3f(x,y, z2);         // Bottom Right Of The Quad (Left)
               
               GL11.glTexCoord2f(0.0f, 0.0f);GL11.glVertex3f( x2, y2,z);         // Top Right Of The Quad (Right)
               GL11.glTexCoord2f(1.0f, 0.0f);GL11.glVertex3f( x2, y2, z2);         // Top Left Of The Quad (Right)
               GL11.glTexCoord2f(1.0f, 1.0f);GL11.glVertex3f( x2,y, z2);         // Bottom Left Of The Quad (Right)
               GL11.glTexCoord2f(0.0f, 1.0f);GL11.glVertex3f( x2,y,z);         // Bottom Right Of The Quad (Right)
           GL11.glEnd();
       GL11.glEndList();


   }


Then, I call the cube with:

GL11.glCallList(MyGLFunctions.box);
Title: Re: drawelements for many identical objects
Post by: Fool Running on October 22, 2010, 12:33:34
Quote from: xman84 on September 26, 2010, 03:44:39
I would like to draw many cubes however when I get to around 1000 it starts to slow the frame rate down.
When you say that it starts to slow the frame rate down, how much slower are you talking about? A jump from 2000fps to 1000fps is nothing. A jump from 200 to 20 is a big jump.

Also, what graphics card are you using? That can have a big impact on the difference between being able to put 1,000 cubes and 1,000,000 cubes on screen.
Quote from: xman84 on September 26, 2010, 03:44:39
Is there a way I can make a single draw call to open gl to draw them instead of making a drawelements call for every cube. The only difference between the cubes would be position and color.
If the cubes don't move at all, you could put them all into one big display list. Otherwise, you have to draw them one at a time.

EDIT: Whoops, didn't realize that there were two different people responding. ParticleSwarm, the questions still apply, the quotes are just wrong. :P
Title: Re: drawelements for many identical objects
Post by: ParticleSwarm on October 23, 2010, 03:10:01
So at around 4000 cubes rendered, I'm getting 20fps. This is already low.

Each time I double the number of cubes, I cut the fps in half, so I'm getting a linear relationship with fps/cubes rendered. There has to be something seriously wrong with how I render.

I'm using a 945 intel chipset. I realize this doesn't help anything, but it doesn't account for such bad performance.

I've already posted my list code, so I'm going to post where I call it. Basically, it just renders a sector of 16x16x32 of blocks, and checks an array to see if a block exists at a particular spot. Maybe you can find something glaringly stupid?

   

   float x = 0;
   while (x <  16)
   {
    GL11.glTranslatef(1,0,0);
       float z = 0;
       while (z < 16)
       {
           GL11.glTranslatef(0,0,1);
           float y = 0;
           while (y < 32)
           {
            GL11.glTranslatef(0,1,0);
               //This checks an array to see if a block should be rendered at this spot
            if (Input.Blocks[(int) x][(int) z][(int) y] == 1)
            {          
         
            GL11.glCallList(MyGLFunctions.box);
           
            }
            y += 1;
           }

           GL11.glTranslatef(0,-y,0);
           z += MyGLFunctions.EdgeSize;
       }

    GL11.glTranslatef(0,0,-z);
       x += MyGLFunctions.EdgeSize;
   }
GL11.glTranslatef(-x, 0, 0);

   GL11.glEnd();
Title: Re: drawelements for many identical objects
Post by: broumbroum on October 23, 2010, 10:53:54
I've got the same problem with the Intel NM10 chipset (actually gma 13xx). I think the bus is overloaded with the growing fill rate (maybe increasing my ram to a dual-channel config can improve that).
E.g. I render about a 100 characters using tesselation and lists, that makes rendering sink to 5 fps. this is because Intel chipsets ain't too well designed for high def graphics.
I'm figuring out to buy a ION mainboard uses a dedicated graphics rendering pipeline.
Title: Re: drawelements for many identical objects
Post by: Fool Running on October 25, 2010, 18:01:10
Quote from: ParticleSwarm on October 23, 2010, 03:10:01
So at around 4000 cubes rendered, I'm getting 20fps. This is already low.

Each time I double the number of cubes, I cut the fps in half, so I'm getting a linear relationship with fps/cubes rendered. There has to be something seriously wrong with how I render.
I would assume that a linear relationship would be normal. Why wouldn't you expect to halve the framerate when doubling the items on screen?
Quote from: ParticleSwarm on October 23, 2010, 03:10:01
I'm using a 945 intel chipset. I realize this doesn't help anything, but it doesn't account for such bad performance.
Actually, this very well could explain your bad performance. Like broumbroum said, Intel chipsets don't make good graphics cards (I don't care what Intel says). :P

One thing you can try (if you aren't already doing it) is to make sure you are doing back face culling (keeps from drawing the backs of polygons you can't see):
glEnable(GL_CULL_FACE);
Aside from that, it looks like your cubes don't need to move, so you could combine many cubes into a display list to limit the number of calls to the OpengGL api, but you may not gain much with that approach.