Need help on terrain engine issue

Discussion in 'Public Game Developers Forum' started by Ezak, Oct 9, 2010.

  1. Ezak

    Ezak Well-Known Member

    Sep 25, 2009
    148
    0
    0
    #1 Ezak, Oct 9, 2010
    Last edited: Oct 9, 2010
    Heya all,

    I'm having a pretty annoying issue on the terrain engine part of a project I'm working on.
    The coding was going fine, starting from brute force and optimizing the terrain rendering bits by bits.
    But now that I have added vertex buffers, I can't add any other draw calls (like a simple background sky, seen below screenshots)...

    No VBOs used:
    [​IMG]

    Using VBOs:
    [​IMG]

    Now I am pretty new to openGL, and I am most certainly doing something wrong with them, so please, if you can, help ! :D

    This is how I setup the VBOs:
    Code:
    glGenBuffers(1, &vertexBuffer);
    glGenBuffers(1, &indexBuffer);
    	
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VerticesData), VerticesData, GL_STATIC_DRAW);
    	
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    This is how I draw the sky:
    Code:
    glDisable(GL_DEPTH_TEST);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, BGVertices);
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, BGColors);
    	
    glDrawArrays(GL_TRIANGLES, 0, sizeof(BGVertices)/sizeof(float));
    	
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glEnable(GL_DEPTH_TEST);
    I then have terrain rendered as follows (note that VBOs are only used for the terrain):
    Code:
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    	
    // set the format and location for verticies
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_SHORT, sizeof(VertexData), (void*)offsetof(VertexData,Vertex));
    
    // set main texture
    glClientActiveTexture(GL_TEXTURE0);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, sizeof(VertexData), (void*)offsetof(VertexData,TextureCoords));
    	
    // set detail texture
    glClientActiveTexture(GL_TEXTURE1);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_SHORT, sizeof(VertexData), (void*)offsetof(VertexData,DetailTextureCoords));		
    
    // set shadowmap
    glClientActiveTexture(GL_TEXTURE2);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, sizeof(VertexData), (void*)offsetof(VertexData,ShadowTextureCoords));
    
    // activate textures
    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE1);
    glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE2);
    glEnable(GL_TEXTURE_2D);
    	
    glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)0);
    	
    glDisable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE1);
    glDisable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE0);
    glDisable(GL_TEXTURE_2D);
    	
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    The thing works fine when I don't use VBOs (first screenshot), but after implementing them, the background is just not rendered and all i can see is the clear color (see second screenshot)...
    The problem occurs on device too, not just on simulator...

    Now the engine is very simple atm, and I would really like to get back to working on it, but I'm stuck and frustrated...I've been googling for hours hoping for an answer, in vain :/

    Can anyone tell me what I'm doing wrong with the handling of the VBOs ?

    Best regards
     
  2. 99c_gamer

    99c_gamer Well-Known Member

    Mar 23, 2009
    659
    0
    0
    dont you need to enable depth test if you plan to draw in the background?
     
  3. Ezak

    Ezak Well-Known Member

    Sep 25, 2009
    148
    0
    0
    heya and ty for the reply !

    Well the background is in this case a flat quad, not a skybox.
    I disable depth testing so that it's always 'behind' the terrain, and draw it before rotations/translations so it stays still during movements.
    Depth testing is put back before drawing the terrain. It works fine when i don't use vertex buffers :/

    My problem is that nothing else can be drawn.. I picked the sky here because it was made of two simple triangles, but doodad models, decals, etc... Nothing shows.

    The VBuffer is only set for the terrain (as GL_STATIC_DRAW since it'll never change) and only the terrain can be shown. There has to be something there, like maybe i'm not "deactivating" the VBuffer setup phase properly, and it's causing it to "eat/glitch" my other models ?

    I'm still looking :/
     
  4. GlennX

    GlennX Well-Known Member

    May 10, 2009
    761
    0
    0
    UK
    Hmm, that's interesting. To be honest I don't have much experience of VBOs, they are next on my todo list since getting my 2.0 shader system up and running.

    A couple of things to try to home in on the answer:

    Have you tried changing the clear colour to bright purple or something?, that way you could see if the problem is polygons not being drawn or rendering wrong/

    Have you tried commenting out the entire terrain render (leaving the VBO setup in) and checking to see if your background appears?, if it does try with l commented out, if the background disappears without the DrawElements you'll know it's something in between and be able to home in further, trying more or less commented out lines.
     
  5. Ezak

    Ezak Well-Known Member

    Sep 25, 2009
    148
    0
    0
    Heya GlennX ! Wow this is great, been a huge fan of GroundEffect since the start (it's actually the game that made me realize the potential of the iphone concerning terrain rendering) and I was absolutely thrilled when i found out you had worked for Bullfrog :D (<--- Hi-Octane/Populous/Syndicate/Dungeon keeper huge fan here)

    Anyways...hrmm...sorry about that burst of "fanboyism" ^^

    I started with VBOs first for some reason, but I'm happy since they really helped the rendering speed on the ipad (got the 60fps cap thanks to them, so that gives me plenty of space). I hear they are only "effective" on 3GS and up though...

    I have tried rendering things in front of the camera, but they are just not being drawn when VBOs on terrain are active.
    Commenting out glDrawElements failed too, I just get a black screen :(
    So like you said, it really has to come from my use of the VBuffer during setup.

    Unfortunately, when I was messing around with the buffer thing earlier on, I completely crashed my ipad (stupid me was testing on actual device) and locked it in restore mode hehe ;)
    So well, after backing it up I somehow forgot to test more and that's when I came over here to ask for help :p
    I'll try to play around again with the VBuffers (on the simulator this time)

    Thanks for the heads up :)

    Cheers
     
  6. Ezak

    Ezak Well-Known Member

    Sep 25, 2009
    148
    0
    0
    Oooo I got it !!!

    Code:
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    Noticed it reading a guide on VBOs (http://www.songho.ca/opengl/gl_vbo.html).
    It seems that this must be used in order to switch back to normal.
    So don't forget to call this once you're done binding !

    I'm confused that the apple OpenGL ES best practice documentation, which insists on the use of VBOs, as well as describes their use, didn't even mention it :confused:

    Anyways, pfiueee... So happy, and now i'm going back to coding :D

    Take care
     
  7. GlennX

    GlennX Well-Known Member

    May 10, 2009
    761
    0
    0
    UK
    Hi Ezak, thanks for posting the solution. I suspect I would have run into the same problem and, knowing my haphazard approach to reading documentation, would probably have hit the same problem and taken a day or so to find the fix!

    Your screenshots look very cool. I'm looking forward to upgrading the landscape render in Ground Effect to use more than two textures and, even more importantly, upgrading the water render to have some sort of bump mapping and receive the landscape shadows, all stuff that wasn't really possible (at a decent frame rate) in GL1.1 .
     
  8. 99c_gamer

    99c_gamer Well-Known Member

    Mar 23, 2009
    659
    0
    0
    What do you guys use for collision detection. I'm doing a terrain engine for my game but it's much more basic than what you've got there. The hardest part for me was the collision detection.
     
  9. GlennX

    GlennX Well-Known Member

    May 10, 2009
    761
    0
    0
    UK
    #9 GlennX, Oct 10, 2010
    Last edited: Oct 10, 2010
    If you can get away with only colliding from above, Heightfields are very simple to handle. Ground Effect uses something like the following code.

    note that mMap is a 1D array representing a 2D map of [WORLD_X_CELLS*WORLD_Y_CELLS] structures with .mAlt being the height. Each cell is WORLD_CELL_SIZE across.

    Sorry about the lack of leading white space but the forum software removes it along with double slash comments!

    basex & basey are used to calculate which cell you're over
    partx & party are the coordinates within the cell

    tl, br, tr & bl are the altitudes at the top left, bottom right, top right and bottom left.

    top is the altitude of the point partx along the top edge of the cell
    bottom is the altitude of the point partx along the bottom edge of the cell
    collide is the altitude of the point party between top and bottom.

    This code considers the cell to be a sort of sheet stretched between the corner points which works better for Ground Effect than considering it as two triangles. I have code that does the same for two triangles if anyone is interested.

    float Collide(float x, float y)
    {
    x = x/WORLD_CELL_SIZE;
    y = y/WORLD_CELL_SIZE;
    float basex = floorf(x);
    float basey = floorf(y);
    float partx = x-basex;
    float party = y-basey;
    S32 xcell = (S32) basex;
    S32 ycell = (S32) basey;

    if((xcell<0) || (xcell>=WORLD_X_CELLS) || (ycell<0) || (ycell>=WORLD_Y_CELLS))
    {
    return DEFAULT_ALT_FOR_BEYOND_THE_MAP;​
    }
    S32 xc2 = (xcell+1)&(WORLD_X_CELLS-1);
    S32 yc2 = (ycell+1)&(WORLD_Y_CELLS-1);

    float tl = mMap[xcell+ycell*(WORLD_X_CELLS)].mAlt;
    float br = mMap[xc2+yc2*(WORLD_X_CELLS)].mAlt;
    float tr = mMap[xc2+ycell*(WORLD_X_CELLS)].mAlt;
    float bl = mMap[xcell+yc2*(WORLD_X_CELLS)].mAlt;

    float top = tl*(1.0f-partx)+tr*partx;
    float bottom = bl*(1.0f-partx)+br*partx;
    float collide = top*(1.0f-party)+bottom*party;

    return collide;​
    }
     

Share This Page