★ TouchArcade needs your help. Click here to support us on Patreon.

Need help on terrain engine issue

10-09-2010, 01:48 PM
#1
Joined: Sep 2009
Posts: 148
Need help on terrain engine issue

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:


Using VBOs:


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

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

Last edited by Ezak; 10-09-2010 at 03:43 PM. Reason: clarified
10-09-2010, 02:31 PM
#2
Joined: Mar 2009
Posts: 659
dont you need to enable depth test if you plan to draw in the background?

10-09-2010, 03:37 PM
#3
Joined: Sep 2009
Posts: 148
Quote:
Originally Posted by 99c_gamer View Post
dont you need to enable depth test if you plan to draw in the background?
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 :/
10-09-2010, 04:03 PM
#4
Joined: May 2009
Location: UK
Posts: 741
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.

-=< Fat Owl With A Jetpack >=-
-=< Topia World Builder >=-
-=< Twitter >=-
-=< Blog >=-
10-09-2010, 04:38 PM
#5
Joined: Sep 2009
Posts: 148
Quote:
Originally Posted by GlennX View Post
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.
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 (<--- 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
10-09-2010, 05:08 PM
#6
Joined: Sep 2009
Posts: 148
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

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

Take care
10-09-2010, 06:58 PM
#7
Joined: May 2009
Location: UK
Posts: 741
Quote:
Originally Posted by Ezak View Post
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

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

Take care
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 .

-=< Fat Owl With A Jetpack >=-
-=< Topia World Builder >=-
-=< Twitter >=-
-=< Blog >=-
10-09-2010, 08:16 PM
#8
Joined: Mar 2009
Posts: 659
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.
10-09-2010, 10:22 PM
#9
Joined: May 2009
Location: UK
Posts: 741
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;
}

-=< Fat Owl With A Jetpack >=-
-=< Topia World Builder >=-
-=< Twitter >=-
-=< Blog >=-

Last edited by GlennX; 10-09-2010 at 10:27 PM.