landscape optimisation....

I’m doing some tests about how many tris/quads a card can display.

my geforce II mx currently display only 9000 quads (18000 tris), multitextured (2 TMUs), at nearly 40 FPS.
40 FPS for both immediate mode and vertex array, no improvement, strange.

those 9000 quads and 40 FPS are bad, very bad values : i’m sure that even a geforce II mx can do better.
go and see the nvidia Vertex Buffer Performance Statistics , you’ll understand what i mean :slight_smile:

So, except T&L, is there a way to actually push a lot of quads ??

your code might not be well optimized, or maybe the bottelkneck is not the geometry stage.

Maybe you’re right but i’ve done some time profiling tests and here are some results :
each engine loop take approx. 35 millisec. to be executed and the display func takes 28 ms within these 35 ms.

When i say display func i mean it : it only send the visible quads to opengl. The my basic visibility algo. takes 4 ms !! :slight_smile:

0.8 M triangles per second? It is very bad
for GF class cards. Try display lists.

display lists ??
i don’t know if multitextures are supported and i don’t think that 512x512 display lists (1 quad = 1 dl) will please the beast :wink:

BTW, can you give me benchmark about how many multitextured quads your code/engine can push and how ??

>>maybe the bottelkneck is not the geometry stage<<

ild say this is true

I think that set of 64x64 display lists is a good solution.

What’s the average size of your triangles ( if they’re all big, maybe your application is fillrate limited ? ). How many textures are you using ? Are you sure you minimize texture switching, if you use many textures ?


for the quads size it’s 20x20 on the XZ plane.
for the textures i use 6 rgb textures and 21 luminance textures because i want the landscape to be as cool as possible :slight_smile:
I diplay the visible quads sorted by (rgb, luminance). This way i hope to minimize tex binding.
But tex binding is not the problem, i’ve done a one tex bind only test, it gave me 1 or 2 frames more :frowning:

still tracking ****ing bug :slight_smile:

The “physical” size doesn’t matter, the relative size does. How large is 20x20 in your world? If your viewpoint is located 0.1 units above the terrain, then the quads are quite huge. If you are located 1000 units above, they are quite small. See what I mean?

Are you drawing lots of things outside the frustum maybe? Try split your terrain in smaller patches, and when rendering, you determing if it’s inside the frustum or not. If not, then don’t draw it.

Dunno where I read it, but I think on a GeForce you should not use vertex arrays larger than 1-2k vertices. Do you upoload the entire terrain at once?

I tried the method I mentioned above, and I’m getting between 10 Mtris/sec (wireframe and non-textures triangles) and 6 Mtris/sec (dual passes with two textures in each pass). I do not use any fancy extensions as compiled vertex arrays or the GL_fence-thingie, only multitexturing.

Another common problem is the texture size when mapped onto the primitive. If you squeeze a high-resolution texture on a small (relative the texutresize) triangle, the performance can drop quite alot.

And yeah, I got a GeForce2 MX aswell.

I’m interested in such benchmarks, but one thing is missing in your description I think it’s important, at what resolution are your rendering ?

Did u use glDrawElements or glArrayElements or directly glVertex ?

How much memory takes your whole geometry/texturecoord/normals data ? (I’ve heard about problems with lists bigger than XXX)

bye bye,

Each patch is fixed 16x16 squares and contains its own small heightmap. The main heightmap’s size is irrelevant, since I always get the same triangle throughput, the only thing that changes is the number of patches. And in a larger terrain, less patches are visible because of frustum culling. I also got two global arrays that are shared among all patches, one for indices and one for texture coords.

If I use the same set of texturecoordinates for each patch, I can use a tiled texture that streches over the entire patch, and with a 256x256 texture, I get OK detail level, and with a 512x512 texture, I get pretty good detail level.

Indices are also shared, since each patch is drawn in the same way: a row from east to west, and each row from north to south. I use GL_TRIANGLES with glDrawArrays() to draw the whole patch in one single command.

The shared indices-story works for LOD aswell. You can build, say six sets of shared indices. One for high level of detail, and one for low level of detail. Then four sets for the patches between two detal levels. One for when LOD goes from high->low from north->south, one for south->north, and same for east/west. This way, you don’t have to recalculate indices when LOD changes, since they are precalculated.

6 Mtris/sec (dual passes with two textures in each pass).

Do i understand that you the polycount of your scene is 100000 triangles @ 60 FPS ??

Are you drawing lots of things outside the frustum maybe

No, as i said before i have a basic algo that retreive the quads to display (without scaning the whole landscape) : ONLY visible quads are displayed.

Another common problem is the texture size when mapped onto the primitive

My rgb textures are 256x256/128x128 and luminance texture are 64x64.

Well it seems that vertex array are the way to go.

Yepp, about 100k triangles at 60 fps. And of course, I’m not talking about a view from above, where you see the entire terrain as a small square, but when you are actually standing in it, as you would in a game.

One of the reasons why it’s fast, is that literraly everything is precalculated. And as a bonus, it’s also stored in a way that when you want to alter the landscape (for example when a bomb explodes and creates a hole), all you have to do is poke in heightmap a little, and you don’t have to recalculate anything else.

I really recomend this way, or something similar. It wasn’t difficult at all to code.

Bob, are you using quadtree to render the terrain? If not what is the structure that you’re using? I’m kinda interested in what you said, can you give me more info?

Bob, how do you change texture for to continous quad/triangle ??
You would need to be able to specify a different uv for each triangle for the same shared vertex, am i wrong ??
And if i use many textures how can the vertex array technique actually be usable ??

sooooo many questions in my mind :wink:

I have also been able to push scenes with 140K triangles per frame, at 58fps with display lists, in a GeForce2 GTS and a P3 600 @ 672, with a lot of different materials and textures, with 4 lights on. Without display lists I get 25 fps, using glDrawEllements with strips and EXT_compiled_vertex_arrays.
What CPU do you have? CPU and bus are very important even if you have T&L. Remember that the CPU sends the vertices through the system bus. If you have a P2 266 and a PCI bus, well.

Wolf: I just loop through each patch in my terrain, test if they are inside the viewfrustum, and draw them if they are inside. Each patch got a vertex array which contains X, Y and Z value for each vertex. This is the array I upload when I draw the patch.
And as I said, I also got a global index array. This index array tells OpenGL how to draw the data in the vertex array. The data is stored in the same way in all patches, and will be drawn in the same way, so this array can be global.
Same goes for base texture coordinates. I strech my textures over the entire patch, and with a bit of thought, you will realise that each pathc can have the same texture coordinates aswell. If one vertex got texture coordinates (0.5, 0.5), the same vertex in the neighbour patch will have (0.5, 1.5), and using GL_REPEAT it will automatically become (0.5, 0.5), i.e. the same texture coordinate.

holocaust: Each vertex needs one set of coordinates for the basetexture. This is the global one I’m talking about. But if you want to do multitexturing with a second greyscale mask that got different texture coordinates, you must create this array per patch, and keep it in the patch structure.

coco : i have a OC celeron @ 416 Mhz with 256 Mb RAM.
About textures : i’m currently using 6 rgb textures and 20 luminance textures !! Quads are displayed by [rgb/luminance] pair lists. To give you an idea about the mutlitexturing binds : in one frame, the app can do 200 [rgb/luminance] binds (200 TMU0, 200 TMU1) !!

But, as i said before, textures binds are not the problem : i’ve done a one bind pair only test and it gave me 1 or 2 frames more :frowning:

Well i know that i should/could use CVA/VAR/DL and such, but i hoped that, without these techs, even a geforce 2 mx could push more than 24000 tris @ 30 FPS (0.72 Mtris/sec) :frowning: I was waiting for something like 60000 tris @ 60 FPS (3.6 Mtris/sec) :wink: