PDA

View Full Version : OpenGL best way to render terrain?



jdarling
03-08-2010, 03:32 PM
I've made more progress on my learning of OpenGL and can now render objects, a HUD, and etc. I can move through the "world" successfully, and in general can do most of the basics.

Now, I'm to the point I think optimization is necessary. Right now if I create a large space (well, not so large, but big enough to get the idea) of 100x100 and render it my FPS drops to 16.

Here is what I'm doing (and I know its the wrong way of doing it):


Camera.Apply;
// render the ground "tiles"
glPushMatrix();
j := 20;
glTranslatef(-20, 0, -20);
while(j>0)do
begin
i := 20;
while(i>0)do
begin
glTranslatef(2, 0, 0);
fGround.Render;
dec(i);
end;
glTranslatef(-40, 0, 2);
dec(j);
end;
glPopMatrix();

// render a rotating box
glPushMatrix();
glTranslatef(-1.5, 2, 0);
glRotatef(yrot,1.0,0.0,0.0);
glRotatef(xrot,0.0,1.0,0.0);
fBox.Render;
glPopMatrix();

// render a rotating graphic (right now a star)
glPushMatrix();
glTranslatef(1.5, 2, 0.0);
glRotatef(-rotation,0.0,1.0,0.0);
fObj2.Render;
glPopMatrix();

// update the FBO that contains my model to be rendered into my HUD
fbo.Render;
// Render the HUD
GLHUD.Render;


I'm guessing that I should be using some type of wrapping (triangle strips?) when I draw the ground and shouldn't be iterating the squares directly. I've search all over for "Ground Plan OpenGL Tutorial" and got back little to nothing :(.

I'm also curious, should I be doing object culling inside my code and if so can someone point me to the "Idiots guide to object culling". I'm can use Matrix Manipulations instead of directly calling the opengl methods, but the opengl methods seem like an easy place to start and then I move final stuff into my base classes.

Any help greatly appreciated as usual.

- Jeremy

tpascal
03-08-2010, 07:38 PM
Hello,


Now, I'm to the point I think optimization is necessary. Right now if I create a large space (well, not so large, but big enough to get the idea) of 100x100 and render it my FPS drops to 16.



Well, currently you still drawing dinamicly, mean you add code (using loops) for draw a 100x100 grid. But when you REALLY GET in the point that you need to render big scenes with good FPS then you need to draw stuff less dinamicly like that.

Your videocard BOX package maybe advertice that your videocard can render several millions triangles per secs, maybe it is but it mean you have to feed the videocard with several millions triangles as soon as you can, but if you do a loop like




for k:=0 to 2000000 do
begin
glbegin...
.
.
.
glend...
end;



Then the FPS will drop drastically, becouse you are involving your CPU to do a big part of the work, instead giving your GPU the most hard work.

Check others Opengl ways to render stuff, like DrawElements or Vertex Buffers, where you basically tell your videocard "here is a pointer to a block memory with the scene data, please draw 20000 triangles from that block".

Yes, the faster way to render big scenes is storing several thousands of triangles data in chunk memory and passing a pointer to opengl for that chunk and saying how much triangles it have to draw from that chunk.

The chunk data can be already pre-procesed, sorted, optimized and loaded in memory from file disk for example, so you dont have to built that dinamically every time, (here is when you need to start coding file format readers to load scenes built in a CAD program)


I'm also curious, should I be doing object culling inside my code and if so can someone point me to the "Idiots guide to object culling".

In these days where we have moderns GPU videocards, somtimes is better to draw everithing that spend some time in the CPU figuring out what is visible and what is not, remember, the videocard box advertice it can render severals millions triangles per secs, so chances are that you will spend more time doing culling in Cpu than what will take to the videocard to draw everithing, depending on how big is your scene.

For culling objects you will need:

- Usign your camera AT, Eye, and your viewport data calc the FRUSTRUM (<-google this)
you need to calc the FRUSTUM, which is a group a planes data that basically describe the cone view dimension of your current view.

- Search code/algorith in pascal for doing an AABB versus frustum test.
AABB stand for Axis aligned bounding box, which is a imaginary box in the world, if for exampel you have a 4000 triangle object, instead asking if every triangle is visible, you calc a AABB for your object (it can be pre-calculated) and just test if your AABB is visible with your current frustum, if not then dont bother rendering any of those 4000 triangle object.

Also somtimes you wil want more acuracy using a OOBB (object Oriented bounding box) instead AABB.

good luck.

tp.

User137
03-08-2010, 07:55 PM
I'm guessing biggest slowdown is here: fGround.Render;
If you have tiles they have to be in same texture. If you use glBindTexture for every tile it'll be a huge fps drop. Also, commands like glBegin-glEnd loops are slowest possible way to render. Displaylists can improve it close to vertex arrays performance.

jdarling
04-08-2010, 01:38 AM
How do these changes affect dynamic worlds and running on limited hardware?

My two final targets are running on Android platforms (OpenGL ES limited graphics card) and educational software. So both require limited hardware specs.

Right now I create a display list for each object and render it to the screen. If I need to rotate/translate the object they each have a local matrix that is * by the camera display matrix. This works, and once I pushed all of the "terrain" into a display list it did increase the rendering speed. But, it also seems to have locked me to static textures.

So, what is the proper way to do animation and animated textures in this situation?

I can post some code if it helps, but I think the questions are generic enough. I'd love to see GL code for animated textures and dynamic (just basic rotation and translation) related to display lists, etc...

Thanks again,
- Jeremy

User137
04-08-2010, 09:43 AM
How do these changes affect dynamic worlds and running on limited hardware?
Vertex array should work on limited hardware, not so sure about VBO. There's many ways and i probably don't know the fastest, but what you can do is create a vertex+textureCoord arrays which you can update on the fly. My rts demo used 3D-textures where texture x,y were always 0 or 1 but z-coordinate was the tile at location, or a half-mix of 2 tiles (smooth blending). I used triangle-strips and rendered each row at the time with 1 call to glDrawArrays, as sort of slices. Only thing i changed realtime was texture coordinates because vertices don't move, you can move map with glTranslate, by fraction of the camera position.


So, what is the proper way to do animation and animated textures in this situation?

I can post some code if it helps, but I think the questions are generic enough. I'd love to see GL code for animated textures and dynamic (just basic rotation and translation) related to display lists, etc...
I am not sure i understand the situation properly. A screenshot would help most, but code aswell if you would like optimization hints.

jdarling
04-08-2010, 12:37 PM
Best example I can come up with is that of a solar system. There are basically 11 planets (or dwarf planets) that we would render: Mercury, Venus, Earth, Mars, Ceres, Jupiter, Saturn, Uranus, Neptune, Pluto, and 2003 UB313. Each planet has a very specific path that it follows and has a fairly basic initial texture that is applied. Then overlays for clouds/movement go on top of that.

I know that isn't landscape, but its the easiest thing I could think of.

The end goal is to build something that is simple to use for my son and I to model School assignments in. We plan on building out a "amusement park" where you walk around and play games/learn about different aspects. As he advances in school we will add to the "game" and expand its content. There are a few others in our home schooling group that would also like to have something like this, so we plan on sharing, otherwise I'd target his system and upgrade where needed :)

The other project I'm working on (the one for the Android) is migrating my Pentominoes game over to OpenGL and the Android platform. This of course is primarily 2D, but I'm thinking I might want to show the shapes in more of 3D.

- Jeremy

tpascal
04-08-2010, 06:45 PM
My two final targets are running on Android platforms (OpenGL ES limited graphics card) and educational software. So both require limited hardware specs.


oh, sorry about that, i did not realize we where talking about openglES, which i understand glbegin...glend is not even supported so you are already using vertex arrays.

Still your botleneck is filling the vertex array, displaylist helps a lot becouse you draw and compile your 100x100 grid into a displaylist once and then you use use the same displaylist every frame; but then you wonder how you "update" your displaylist, well you cant, you have to build the displaylist again if somthing change.

I have not idea if you have access to data resources, like i said, the key is to have the hard work already pre-proccesed and then load the data into chunks memory; Drawelements for example allow you to use different chunks of memory for store diffrents components like vertices, UVmaps, normals, colors, etc, so when you need to do dynamics changes you can access just the needed component accesing the chunk memory.


So, what is the proper way to do animation and animated textures in this situation?


if for animation you just mean changing from position an objects then you just translate the matrix as required and then draw the object with no need to change the vertices data array;

Animated texture as far i know is done cycling UVs, so you have to update the UVs data every needed time, like about 24 frames per secs is enough.