Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (495)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Why are display lists running faster than VBOs in my game?  (Read 1322 times)
0 Members and 1 Guest are viewing this topic.
Offline thunderfist123

Senior Newbie





« Posted 2013-11-27 02:15:49 »

I created two simple voxel engines, literally just chunks that hold cubes. For the first one, I use display lists and can render hundreds of chunks at 60 FPS no problem, despite the fact that the technology behind it is years old and deprecated by now. With my VBO version, I try to render 27 chunks and I suddenly drop to less than 50 FPS. What gives? I use shaders for my VBO version, but not for display list one. Without shaders for the VBO version, I still get the same FPS rate. I'll post some relevant code:

VBO
-----
Initialization of chunk:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
    public void initGL() {
      rand = new Random();
     
      sizeX = (int) pos.getX() + CHUNKSIZE;
      sizeY = (int) pos.getY() + CHUNKSIZE;
      sizeZ = (int) pos.getZ() + CHUNKSIZE;

      tiles = new byte[sizeX][sizeY][sizeZ];

      vCoords = BufferUtils.createFloatBuffer(CHUNKSIZE * CHUNKSIZE * CHUNKSIZE * (3 * 4 * 6));
      cCoords = BufferUtils.createFloatBuffer(CHUNKSIZE * CHUNKSIZE * CHUNKSIZE * (4 * 4 * 6));

      createChunk();

      verticeCount = CHUNKSIZE * CHUNKSIZE * CHUNKSIZE * (4 * 4 * 6);

      vCoords.flip();
      cCoords.flip();

      vID = glGenBuffers();
      glBindBuffer(GL_ARRAY_BUFFER, vID);
      glBufferData(GL_ARRAY_BUFFER, vCoords, GL_STATIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER, 0);

      cID = glGenBuffers();
      glBindBuffer(GL_ARRAY_BUFFER, cID);
      glBufferData(GL_ARRAY_BUFFER, cCoords, GL_STATIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
   }
    private void createChunk() {
      for (int x = (int) pos.getX(); x < sizeX; x++) {
         for (int y = (int) pos.getY(); y < sizeY; y++) {
            for (int z = (int) pos.getZ(); z < sizeZ; z++) {
               if (rand.nextBoolean() == true) {
                  tiles[x][y][z] = Tile.Grass.getId();
               } else {
                  tiles[x][y][z] = Tile.Void.getId();
               }
               vCoords.put(Shape.createCubeVertices(x, y, z, 1));
               cCoords.put(Shape.getCubeColors(tiles[x][y][z]));
            }
         }
      }
   }

And then rendering:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
    public void render() {
      glBindBuffer(GL_ARRAY_BUFFER, vID);
      glVertexPointer(3, GL_FLOAT, 0, 0L);

      glBindBuffer(GL_ARRAY_BUFFER, cID);
      glColorPointer(4, GL_FLOAT, 0, 0L);

      glEnableClientState(GL_VERTEX_ARRAY);
      glEnableClientState(GL_COLOR_ARRAY);

      shader.use();
      glDrawArrays(GL_QUADS, 0, verticeCount);
      shader.release();

      glDisableClientState(GL_COLOR_ARRAY);
      glDisableClientState(GL_VERTEX_ARRAY);
   }

I know I use quads, and that's bad, but I'm also using quads for my display list engine. The shaders are very simple, all they do is take a color and apply it to the vertices, I won't even post them they are that simple.

Display List
------------
Initialization:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
    public void init() {
      rand = new Random();

      opaqueID = glGenLists(1);

      tiles = new byte[(int) lPosition.x][(int) lPosition.y][(int) lPosition.z];

      genRandomWorld();
      rebuild();
   }
    public void rebuild() {
      glNewList(opaqueID, GL_COMPILE);
      glBegin(GL_QUADS);
      for (int x = (int) sPosition.x; x < (int) lPosition.x; x++) {
         for (int y = (int) sPosition.y; y < (int) lPosition.y; y++) {
            for (int z = (int) sPosition.z; z < (int) lPosition.z; z++) {
               if (checkCubeHidden(x, y, z)) {
                  // check if tiles hidden. if not, add vertices to
                 // display list
                 if (type != 0) {
                     Tile.getTile(tiles[x][y][z]).getVertices(x, y, z, 1, spritesheet.getTextureCoordsX(tiles[x][y][z]), spritesheet.getTextureCoordsY(tiles[x][y][z]));
                  } else {
                     Tile.getTile(tiles[x][y][z]).getVertices(x, y, z, 1);
                  }
               }
            }
         }
      }
      glEnd();
      glEndList();
      spritesheet.bind();
   }

I should note that in my display list version, I only add in the visible cubes. So, that may be an unfair advantage, but it should not bring the VBO version down to that FPS with just 27 chunks versus 500 chunks for the display list version.
I render like this:

1  
2  
3  
4  
5  
6  
7  
    public void render() {
      if (tiles.length != -1) {
         glEnable(GL_BLEND);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         glCallList(opaqueID);
      }
   }

So, after all of that code, I really still wonder why my VBO version is just so darn slow? I do have a one dimensional list of chunks in my display list version for when I'm calling them to render, and a 3 dimensional one in my VBO version, but I think the JVM pretty much eliminates any lag with the extra dimensions. So, what am I doing wrong?

Edit: I just turned off individual block culling in my display list version and it still ran just as fast, albeit the start up time was slower, as expected.
Offline theagentd
« Reply #1 - Posted 2013-11-27 08:08:36 »

I should note that in my display list version, I only add in the visible cubes. So, that may be an unfair advantage, but it should not bring the VBO version down to that FPS with just 27 chunks versus 500 chunks for the display list version.
That would be my first guess. The whole point of voxel engines is that 99% of all blocks are either air or covered by other solid blocks. There are over 2 million blocks in a 128x128x128 voxel world.


Edit: I just turned off individual block culling in my display list version and it still ran just as fast, albeit the start up time was slower, as expected.

I find that hard to believe, but let's assume that what you're saying is indeed what happens. I can see quite a few optimization possibilities.
 - Store vertex colors as 4 unsigned bytes, not floats.
 - Store both positions and colors interleaved in the same VBO.
 - When rendering, bind the shader and enable the vertex attributes once. When rendering a chunk you should only bind your VBO, update the two attribute pointers and call glDrawArrays().

Myomyomyo.
Offline StumpyStrust
« Reply #2 - Posted 2013-11-27 10:16:51 »

One thing that you have to understand is that display lists can be heavily optimized by drivers to the point that for static geometry they will out perform VBOs. The driver could pack data to be as optimized as possible, It could literally be tossing out non-visible geometry its self. (OK maybe not that but still) However, because it is driver based they are not reliable. I have found that display lists are many times slower then static VBO for my graphics card. VBOs are reliable and generally faster. The speed difference you say as me thinking something is amiss.

Interleave the data. That can have a substantial impacted. Do similar things that the all knowing agent above said.

In my ventures on minecraft like voxels I was able to do many thousands of chunks with static VBOs and maintain 30-60 fps. Turning off face culling (what the display list is doing) cuts performance down hugely.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline theagentd
« Reply #3 - Posted 2013-11-27 10:42:19 »

How big are your chunks? If they're too small, you get CPU performance problems since the geometry is so fine-grained that the cost of binding buffers and attributes is too high (probably not your case), and if they're too big you get problems with GPU performance instead since your frustum culling isn't culling as precisely anymore.

Myomyomyo.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Dwinin (28 views)
2014-09-12 09:08:26

Norakomi (57 views)
2014-09-10 13:57:51

TehJavaDev (72 views)
2014-09-10 06:39:09

Tekkerue (37 views)
2014-09-09 02:24:56

mitcheeb (57 views)
2014-09-08 06:06:29

BurntPizza (43 views)
2014-09-07 01:13:42

Longarmx (27 views)
2014-09-07 01:12:14

Longarmx (34 views)
2014-09-07 01:11:22

Longarmx (34 views)
2014-09-07 01:10:19

mitcheeb (40 views)
2014-09-04 23:08:59
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!