Sign in to follow this  

Terrain rendering and VBO

This topic is 1154 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am wondering, i am currently rendering a terrain. At first i did brute force rendering, then display lists, then vertex arrays, then now indexed vertex arrays :p! ( as i learn the new concepts i apply them ) and now VBOs with an indexed vertex array. I read that VBOs are better than displaylists so i used them even though i dont have any notable FPS gain they have the advantage of being flexible. So what i was wondering, is it better to use Indexed Vertex arrays or simple Vertex Arrays? Also is it good to render my terrain with a single vertex array? (its an rts like terrain). Also how would i apply several textures on my terrain using the texture array? ( each 'tile' of the terrain has a texture that can be different like sand grass etc... ). I didnt find any good tutorials on the subject since i probably dont even know the words to use for the search. Thanks in advance!

Share this post


Link to post
Share on other sites
If you can do indexing for vertices then do it. :)

Using one vertex array for the whole terrain probably isn't the best solution if you have loads of data in it. I suggest you split it in 'tiles' of some size.

Share this post


Link to post
Share on other sites
Quote:
Original post by Saya
I read that VBOs are better than displaylists so i used them even though i dont have any notable FPS gain they have the advantage of being flexible.
Uhm... sort of. Static VBOs are just as fast as DL (there may be sort of 2% difference but that's nothing).
Dynamic VBOs aren't directly comparable to DLs. Saying that they're faster is a gross simplification... but the result is that they're way better for dynamic data.
Dynamic data means the VBO data changes, not that the mesh itself changes.
Quote:
Original post by Saya
So what i was wondering, is it better to use Indexed Vertex arrays or simple Vertex Arrays?
Obviously indexed. I don't see the connection here. Why do you think this may be a problem?
Quote:
Original post by Saya
Also is it good to render my terrain with a single vertex array? (its an rts like terrain).
Yes, less VBOs/streams are better. Just make sure they don't grow too big. I am pretty happy at 4MB (my dataset is generally about tens of megs of geometry data) but I plan to move to higher numbers in the near future.

Do not try the impossible. Merging similar stuff in a single VBO is easy. Mixing two "very far" resources in the same VBO may be more difficult. Take it easy for now.

Using a VBO per tile (or a VBO per draw call in general) is likely to be far from optimal.
Quote:
Original post by Saya
Also how would i apply several textures on my terrain using the texture array? ( each 'tile' of the terrain has a texture that can be different like sand grass etc... ).
I'm unsure this makes sense. Supposing you want to tile them, then you'll have to place each tile in the right spot. Then, since you're already batching another call it just takes a simple Bind.
If you somehow manage to draw multiple tiles then using a support texcoord may help, but it's unclear if your "texture array" is the new fourth-gen shading pipe functionality.

Share this post


Link to post
Share on other sites
Well do i have to build a different vertex array for each texture type? I dont understand how to do it since my texture array only defines the texture position and not the texture itself.

Im having problems with using VBOs instead of simple vertex arrays. My indexed array code works but my VBO only displays like one fourth of the map and some rubbish.

Heres my code for the Vertex array and then the VBO (i use exactly the same arrays for both):

using an indexed vertex array:
	
void Map::renderTerrain(void)
{
/**vertex arrays*/
glEnable(GL_TEXTURE_2D);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white_color);
glBindTexture(GL_TEXTURE_2D, texture);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, vertexarray);
glNormalPointer(GL_FLOAT, 0, vnormalarray);
glTexCoordPointer(2, GL_FLOAT, 0, texarray);

glDrawElements(GL_TRIANGLES, 6*(size_x-1)*(size_y-1), GL_UNSIGNED_INT, indexarray);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glDisable(GL_TEXTURE_2D);
}






using VBO with an indexed vertex array:

void Map::constructVBO(void)
{
// Create the buffer objects
glGenBuffersARB(4, bufferObjects);

// Copy data to video memory
// Vertex data
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferObjects[VERTEX_DATA]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 3*4*(size_x-1)*(size_y-1)*sizeof(GLfloat), vertexarray, GL_STATIC_DRAW_ARB);
// Normal data
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferObjects[NORMAL_DATA]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 3*4*(size_x-1)*(size_y-1)*sizeof(GLfloat), vnormalarray, GL_STATIC_DRAW_ARB);
// Texture coordinates
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferObjects[TEXTURE_DATA]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 2*4*(size_x-1)*(size_y-1)*sizeof(GLfloat), texarray, GL_STATIC_DRAW_ARB);
// Indexes
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, 6*(size_x-1)*(size_y-1), indexarray, GL_STATIC_DRAW_ARB);
}

void Map::renderVBO(void)
{
glEnable(GL_TEXTURE_2D);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white_color);
glBindTexture(GL_TEXTURE_2D, texture_grass);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

// Here’s where the data is now
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferObjects[VERTEX_DATA]);
glVertexPointer(3, GL_FLOAT,0, 0);

// Normal data
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferObjects[NORMAL_DATA]);
glNormalPointer(GL_FLOAT, 0, 0);

// Texture coordinates
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferObjects[TEXTURE_DATA]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);

// Indexes
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]);
glDrawElements(GL_TRIANGLES, 6*(size_x-1)*(size_y-1), GL_UNSIGNED_INT, 0);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glDisable(GL_TEXTURE_2D);
}








[Edited by - Saya on January 10, 2008 10:02:41 AM]

Share this post


Link to post
Share on other sites

Nevermind, by looking at the source posted here i realised i had forgotten to multiply the size of the index array by the size of GLfloat...

However im having a slight compilation problem with VBOs i get these warnings (i use gcc on ubuntu linux):

g++ -Wall -g -lSDL -lSDL_image -lSDL_ttf -lGL -lGLU camera.cpp entity.cpp game.cpp main.cpp map.cpp sdlglutils.cpp vector3d.cpp -o test_opengl
/usr/bin/ld: Warning: type of symbol `glGenBuffersARB' changed from 2 to 1 in /tmp/cc5HsBFb.o
/usr/bin/ld: Warning: type of symbol `glBindBufferARB' changed from 2 to 1 in /tmp/cc5HsBFb.o
/usr/bin/ld: Warning: type of symbol `glBufferDataARB' changed from 2 to 1 in /tmp/cc5HsBFb.o
/usr/bin/ld: Warning: type of symbol `glDeleteBuffersARB' changed from 2 to 1 in /tmp/cc5HsBFb.o






Here is how i implement the extensions:

typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);

// VBO Extension Function Pointers
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL; // VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL; // VBO Bind Procedure
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL; // VBO Data Loading Procedure
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL; // VBO Deletion Procedure







std::cout<<"VBO supported..."<<std::endl;
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
glBufferDataARB = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");






Any ideas on what the problem could be?

Share this post


Link to post
Share on other sites

Nevermind, by looking at the source posted here i realised i had forgotten to multiply the size of the index array by the size of GLfloat...

However im having a slight compilation problem with VBOs i get these warnings (i use gcc on ubuntu linux):

g++ -Wall -g -lSDL -lSDL_image -lSDL_ttf -lGL -lGLU  camera.cpp entity.cpp game.cpp main.cpp map.cpp sdlglutils.cpp vector3d.cpp -o test_opengl
/usr/bin/ld: Warning: type of symbol `glGenBuffersARB' changed from 2 to 1 in /tmp/cc5HsBFb.o
/usr/bin/ld: Warning: type of symbol `glBindBufferARB' changed from 2 to 1 in /tmp/cc5HsBFb.o
/usr/bin/ld: Warning: type of symbol `glBufferDataARB' changed from 2 to 1 in /tmp/cc5HsBFb.o
/usr/bin/ld: Warning: type of symbol `glDeleteBuffersARB' changed from 2 to 1 in /tmp/cc5HsBFb.o






Here is how i implement the extensions:
typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);

// VBO Extension Function Pointers
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;					// VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;					// VBO Bind Procedure
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;					// VBO Data Loading Procedure
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;			// VBO Deletion Procedure






	std::cout<<"VBO supported..."<<std::endl;
	glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
	glBindBufferARB = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
	glBufferDataARB = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
	glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");






Any ideas on what the problem could be?

 

You have to link with

g++ -Wall -g -lSDL -lSDL_image -lSDL_ttf  camera.cpp entity.cpp game.cpp main.cpp map.cpp sdlglutils.cpp vector3d.cpp  -lGL -lGLU -o test_opengl

That is, put -lGL at the end AFTER your files. It's bullshit, but file order matters for linking.

The alternative is to not link with libGL at all and load everything dynamically - this is the preferred way if you need to support multiple OpenGL versions.

Share this post


Link to post
Share on other sites

This topic is 1154 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Guest
This topic is now closed to further replies.
Sign in to follow this