Jump to content

My Slow OpenGL World vs. Minecrafts Fast Massive 3d World [Download and Link]

- - - - -

  • Please log in to reply
9 replies to this topic

#1
coderwalker

coderwalker

    Newbie

  • Members
  • Pip
  • 8 posts
I am making a game that is like a virtual world made of legos. A game where the user can just walk around and place blocks and destroy blocks and make things. I was researching if anyone had done anything similar, and someone has. The game is called Minecraft. It has a 3d world made of blocks similar to what I was thinking of making, but the other aspects, such as crafting, will not be in my game.

I split my map into chunks and am only going to draw the visible ones. Minecraft I learned takes the same approach.

The problem I am having is speed. My game runs majorly slow for some reason.
I am drawing only 3*3 = 9 chunks
Minecraft draws 9*9 = 81 chunks and still gets a higher framerate.
My game barely gets 30fps and Minecraft gets 210-450fps!

I dont understand why its so slow.

I have included links to both, so that you can see what I am talking about as well as my Chunk drawing code.

Someone please make a great observation, this is really killing me. I have no idea why it's so slow and can not work on other componets until the framerate problem is fixed.
Thanks a TON in Advance.
Coder Walker

Happy early Christmas :c-penguin:

Project Block: (2mb includes SDL and OpenGL dll's)
ProjectBlock.zip
PASSWORD FOR THE ZIP IS "block"
Minecraft Alpha (In Browser Java):
Minecraft

Chunk Drawing Code:
position is the number of blocks in that chunk
grid is an array that holds the x,y and z of each block
void chunk::draw(float x, float y, float z)

{

    glPushMatrix();

    glColor4f( 1.0, 1.0, 1.0, 1.0 );

    glTranslatef(x,y,z);

    glEnable( GL_TEXTURE_2D );

    for(int a=0;a<position;a++)

    {

        glPushMatrix();

            glTranslatef(grid[a].x,grid[a].y,grid[a].z);

            glBindTexture( GL_TEXTURE_2D,grid[a].tex );

            //Front

            glBegin( GL_QUADS );

                glNormal3f(0.0f, 0.0f, -1.0f);

                glTexCoord2d(1.0,1.0);glVertex3f(1, 1, 0 );

                glTexCoord2d(1.0,0.0);glVertex3f(1, 0, 0 );

                glTexCoord2d(0.0,0.0);glVertex3f(0, 0, 0 );

                glTexCoord2d(0.0,1.0);glVertex3f(0, 1, 0 );

            //Back

                glNormal3f(0.0f, 0.0f, 1.0f);

                glTexCoord2d(1.0,1.0);glVertex3f(1, 1, 1 );

                glTexCoord2d(1.0,0.0);glVertex3f(1, 0, 1 );

                glTexCoord2d(0.0,0.0);glVertex3f(0, 0, 1 );

                glTexCoord2d(0.0,1.0);glVertex3f(0, 1, 1 );

            //Top

                glNormal3f(0.0f, 1.0f, 0.0f);

                glTexCoord2d(1.0,1.0);glVertex3f(1, 1, 1 );

                glTexCoord2d(1.0,0.0);glVertex3f(1, 1, 0 );

                glTexCoord2d(0.0,0.0);glVertex3f(0, 1, 0 );

                glTexCoord2d(0.0,1.0);glVertex3f(0, 1, 1 );

            //Bottom

                glNormal3f(0.0f, -1.0f, 0.0f);

                glTexCoord2d(1.0,1.0);glVertex3f(1, 0, 1 );

                glTexCoord2d(1.0,0.0);glVertex3f(1, 0, 0 );

                glTexCoord2d(0.0,0.0);glVertex3f(0, 0, 0 );

                glTexCoord2d(0.0,1.0);glVertex3f(0, 0, 1 );

            //Left

                glNormal3f(-1.0f, 0.0f, 0.0f);

                glTexCoord2d(1.0,1.0);glVertex3f(0, 1, 1 );

                glTexCoord2d(1.0,0.0);glVertex3f(0, 1, 0 );

                glTexCoord2d(0.0,0.0);glVertex3f(0, 0, 0 );

                glTexCoord2d(0.0,1.0);glVertex3f(0, 0, 1 );

            //Right

                glNormal3f(1.0f, 0.0f, 0.0f);

                glTexCoord2d(1.0,1.0);glVertex3f(1, 1, 1 );

                glTexCoord2d(1.0,0.0);glVertex3f(1, 1, 0 );

                glTexCoord2d(0.0,0.0);glVertex3f(1, 0, 0 );

                glTexCoord2d(0.0,1.0);glVertex3f(1, 0, 1 );

            glEnd();

        glPopMatrix();

        //printf("%d\n",a);

        }

    glPopMatrix();
Every object in the game will be the block or Cube. So there has got to be a further optimization to this. Please help me find it.

#2
elasto

elasto

    Newbie

  • Members
  • Pip
  • 1 posts
Hi. Came across this post while Googling. Don't know if you are still looking for comments on this but I'll share them anyway! (I started a Minecraft clone myself in XNA last week just for fun and so have been thinking about such things.)

Firstly, you say you are only drawing visible chunks, and that's obviously a good optimisation. If that's the only one you are doing, though, there is plenty more that can be done. Here is three that have occurred to me to date:

1) Cull all cubes that have no exposed face. ie if a block is cubic and has 6 immediate neighbours, its vertices need not be added to your drawlist at all (it can't be seen). It's possible to go further and cull all cubes that only surround a closed cave that the player is not inside (assuming you even have caves). Basically you just render surface cubes.

2) As well as not adding any face that has an immediate neighbour, don't add any face to your drawlist if it's facing away from the player. ie the player can never see more than 3 faces of a cube from a single vantage point: If he can see the front he can't see the back; if he can see the left side he can't see the right side. Notch blogged he does this at a chunk level - and although he might have refined that since that seems to make a lot of sense to me as is: Cull at the chunk level and you only need to resend vertex data to the graphics card when the player changes chunks - when the vertex data needs to be updated anyway (and that can be prepared ahead of time and drip-fed to the card using multiple vertex buffer objects - it all depends where the bottlenecks end up being). (And, yes, the graphics card can do this face culling very efficiently, but assuming your blocks are all x-y-z axis aligned and all angles 90 degrees you can do this in code at more or less zero cost. If they aren't then ignore this one).

3) Strip the internal vertices from cubes that are touching and have the same texture. ie if you have two 1x1 grass cubes touching, convert them into a single 2x1 cuboid, halving the vertex count (you'll obviously need to texture wrap). Notch blogged about doing this saying it halved the number of vertexes rendered on the average newly formed map (surprises me it isn't more).

If you aren't using index buffers I imagine that would help too. I haven't bothered doing that yet because I am getting >60fps for >100blocks viewdistance with just doing optimisations (1) and (2), so my attention has moved on to other things for now.

I have a hunch Notch culls cubes/chunks based on lighting too: I think this because I have dug through the middle of a mountain without bothering to light any torches, and when I did light one deep inside I got the familiar chunk-loading type stutter. If I were to hazard a guess I'd think this is how Notch is culling the closed caves I mentioned in (1) - although I'm not sure whether he does something further clever with undiscovered cubes with their own lighting (lava etc).

Note, some optimisations don't play especially nice with each other - eg Texture atlas'ing & vertex stripping, but there are ways around that (eg Notch converts his 16x16 textures to 1x256 so he can do both).

Anyhow, have fun with the project. I certainly am!

#3
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
wow I'm really glad I came across this post. I was having a similar problem a while back when i was creating a 3D world except my frame rate was absolutely horrific. That and I hadn't came up with an idea yet, just was making a world. I was doing the openGL backface culling, but never thought of culling before the vertices hit the pipeline. Thanks for the response elasto

#4
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
How do you perform those optimizations though? How do you make them fast enough so that the optimizations themselves don't slow down the program? Or will that most likely not happen? I'm curious because I'm introducing myself to graphics.

EDIT: I get a framerate of 45 flat when running your program (game?). Also, all the console output might be slowing it down a little.
Latinamne loqueris?

#5
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
I didnt get a chance to test it cause I'm on linux and I didnt really want to install wine just to try it out.
But since you tested it out, that's interesting to know that he put console output in the game, I hope that is just a debug build and not the distribution build.

I put all my debug printing in debug blocks:
#ifdef DEBUG

   printf(...);

#endif

Anyways, about the optimizations, I think that's whatever way the programmer sees fit ya know? If the programmer is really good I bet he/she could write some great optimizations, if not they might not be that great.

From what I see, I think the camera's location & direction needs to be compared to the grid blocks from this function:
glTranslatef(grid[a].x,grid[a].y,grid[a].z);

If I remember correctly, Open GL does not spend time drawing polygons that are out of view of the camera.
And I think it has a pretty good function for determining what is in and out of the camera,
but as far as preventing objects within the camera's range but not visible from being drawn....

That would be basically not drawing anything behind the closest face right?
Doesn't openGL do that too?

I don't know it's been a while since i've done GL.

What do you think mebob? have you studied openGL yet?

#6
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
Well, the console output was in a text file named stdout.txt, so I figure it is console output redirected to a file. I have began learning OpenGL, but I am still in the very early stages. All I've created so far is a program that has a cube, each face a different color, and you can rotate it and move it using the keyboard.
Latinamne loqueris?

#7
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
Ahh i see. Yeah I didnt get too far either. made a block that had collision detection against other blocks and you could move them. that's about it lol. I took a break for winter when everyone was back. I dunno, I think that it will be in the material you read though, i remember seeing a lot of culling type stuff when reading on openGL and DirectX

#8
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
Actually, I've been mostly just looking at the documentation and Googling stuff here in there when I need to. I want to start putting shaders in, but I really don't feel like it. I also really want to know how to do collision detection, but I also don't feel like doing that. I'm just lazy.
Latinamne loqueris?

#9
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
Have you done a 2D game first? 3D can get quite discouraging sometimes, I was rather quite successful in 2D and it helped me get collision detection and other fundamental game ideas down first. for a good 2d graphics library (and great for other media like music too) check out SDL.

#10
mebob

mebob

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 490 posts
I haven't tried making any actual games yet. I did try a few things with 2D using SFML, but I really wanted to do 3D so I got into that. Also, I've tried SDL, but I prefer SFML.
Latinamne loqueris?




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users