Sign in to follow this  
snowfell

[c++] Effective Rendering

Recommended Posts

Hey, guys. I could use a little help with making a program render more effectively, if you don't mind lending me a few minutes of your time. I have been working on this small project for a little while now and I thought it was about time to try and improve my method of rendering. My goal of the project is to have a simple 3d fps-style game (not really caring about game aspects like AI or lighting at the moment, just trying to get the 3d environment and stuff up and running smoothly), as my final project in my high school C++ class. Basically I have multiple functions (cube, wall, .ect) for rendering, and the program has to call these functions every time the loop goes through. Then I use these functions to draw the world and everything in it. I believe that this method is very ineffective but I don't know of any other way. Would this be a good time to look into display lists, or would that help at all? Any other tips on making a better rendering engine? Thanks for your time and help! ->basic program model Main() { Window_Setup() Import_Textures() Init() Game_Loop() { Rendering() Input() Physics() } Destroy() } ->function for rendering cubes
void BuildCube(float x1, float y1, float z1, float x2, float y2, float z2, int tex_l, int tex_x, int tex_y)
{
    glBindTexture(GL_TEXTURE_2D, tex_l);
    glBegin(GL_QUADS);
    //bottom
    glTexCoord2f(0.0, 0.0); glVertex3f(x1, y1, z1); glTexCoord2f(tex_x, 0.0); glVertex3f(x2, y1, z1); glTexCoord2f(tex_x, tex_y); glVertex3f(x2, y2, z1); glTexCoord2f(0.0, tex_y); glVertex3f(x1, y2, z1);
    //top
    glTexCoord2f(0.0, 0.0); glVertex3f(x1, y1, z2); glTexCoord2f(tex_x, 0.0); glVertex3f(x2, y1, z2); glTexCoord2f(tex_x, tex_y); glVertex3f(x2, y2, z2); glTexCoord2f(0.0, tex_y); glVertex3f(x1, y2, z2);
    //sides
    glTexCoord2f(0.0, 0.0); glVertex3f(x1, y1, z1); glTexCoord2f(0.0, tex_y); glVertex3f(x1, y1, z2); glTexCoord2f(tex_x, tex_y); glVertex3f(x2, y1, z2); glTexCoord2f(tex_x, 0.0); glVertex3f(x2, y1, z1);
    glTexCoord2f(0.0, 0.0); glVertex3f(x2, y1, z1); glTexCoord2f(tex_x, 0.0); glVertex3f(x2, y2, z1); glTexCoord2f(tex_x, tex_y); glVertex3f(x2, y2, z2); glTexCoord2f(0.0, tex_y); glVertex3f(x2, y1, z2);
    glTexCoord2f(0.0, 0.0); glVertex3f(x2, y2, z1); glTexCoord2f(tex_x, 0.0); glVertex3f(x1, y2, z1); glTexCoord2f(tex_x, tex_y); glVertex3f(x1, y2, z2); glTexCoord2f(0.0, tex_y); glVertex3f(x2, y2, z2);
    glTexCoord2f(0.0, 0.0); glVertex3f(x1, y2, z1); glTexCoord2f(0.0, tex_y); glVertex3f(x1, y2, z2); glTexCoord2f(tex_x, tex_y); glVertex3f(x1, y1, z2); glTexCoord2f(tex_x, 0.0); glVertex3f(x1, y1, z1);
    glEnd();
}

Share this post


Link to post
Share on other sites
First, an implementation note: ditch immediate mode (glBegin, glEnd, etc.) and learn to use Vertex Buffer Objects (VBO), or at least Vertex Arrays. Immediate mode is an archaic holdover, and you will benefit from moving on.

Next, don't hardcode your level design like this. Design your level in a 3D modelling application (Blender is free, if you don't have one already), and load it into your game from a model file. Again, you will thank yourself later, whether or not you see the point right now.

Share this post


Link to post
Share on other sites
I think I am going to give vertex arrays a try. So far I have been able to setup a vertex array that renders all my code as before. But I am having trouble understanding how I can have the type of texture support that I did before. I already know how to setup the texture coordinates, but I don't see how I can have different textures assigned to different shapes without having a new array for each shape of one texture.

Is there a way to give multitexture support for these arrays?

Share this post


Link to post
Share on other sites
You could indeed have multiple arrays, e.g. one per texture.

Another approach would be texture atlasses where all texture images are packed into a huge texture and texture coordinates are adjusted. However, if you're using fixed function (I assume you do), tiling will be very hard to achieve, if not impossible. Using shader's it's quite easy, but I assume they're out of scope right now.

Share this post


Link to post
Share on other sites
Well I already have bitmaps assigned to an array. It would help the most if I could put all the vertexs in one array regardless of the texture its using. It would grow a little confusing having a different vertex array for each texture to be used. If its an option to do this, what might I want to look into?

What method is used in most modern or older games? In a game like Quake what method of rendering would you expect they used?

Share this post


Link to post
Share on other sites
A few more things you need to consider are using a scene graph, using some pre-calculated visibility data, and using frustum culling.

Scene graphs:
BSP Trees (Binary Space Partition Trees) are very good for
enclosed spaces such as large buldings. They can be used for outside
environments too but are not as well suited as other techniques.
These come in two flavours...
Solid Node and Leafy. I'm not going to go into detail about the differences
but Leafy BSP trees are more common and are the type that i use in my engine.

Oct Trees / Quads Trees are another option.
These are good if alot of your environment is outside.
I dont know much about Oct Trees and Quad trees tho.

Pre-calculated visibility data:
This is something that is more commonly known as a PVS (Potentially Visible Sets) It's a set of data that describes what areas of your 3D world are visible
to other areas. For instance if one room in a building is visble to another
through a door way or whole in a wall.

Frustum culling:
This is a farily simple technique to avoid trying to render objects that are
outside of the camera's FOV (Field Of View). Again, im not going to go into
too much detail but there is so much info out there on the net that I'm sure
you'll find what you need.

These technique combined will dramatically bump up your frame rate, even with very large maps. They are standard techniques used in the game industry.

Both the BSP Tree and PVS need to pre-compiled. You cannot build a BSP tree
and calulate visibility data at render time as this process is VERY cpu intensive and takes a loooong time to assemble the data.
Frustrum culling however needs to be done at run time but is not particually
heavy on the CPU if done in an intellegent way.

So anyway, have a look around for some tutorials on BSP trees, PVS and Frustum culling. And good luck! keep coding.

Share this post


Link to post
Share on other sites
After spending some time looking into these methods I feel a bit overwhelmed. What can I do to prepare myself for this more advanced style of 3d programming? I have basically worked my way through Beginning Opengl Game Programming by Dave Astle, Kevin Hawkins. But when I try to take the next step into more advanced methods it just seems too much. Know of any good books that make a good transformation from beginner to intermediate. Also where can I go to learn about the structure of a real time 3d program?

Thanks for all the great incite so far, you all have been a great help!

Share this post


Link to post
Share on other sites
I dont blame you for feeling overwelmed by these techniques.
I know i certainly felt the same way when i first looked at them.
Especially the BSP trees, those really confused me at first but stick at it
because they do make sense in the end.
These can be tricky techniques to learn but are very rewarding when you grasp
how they work.

Unfortunetly i dont really know of any good books on these subjects as i learnt almost everything i know from online resources.
however, this was a number of years ago so i cannot for the life of me remember
what these websites are. Or even if they still exist for that matter!

What i will say tho is, as this is a high school project you are working on then
perhaps it might be more prudent for you to build a VERY simple first person
shooter. IE have it consist of only a few basic rooms without too much detail
in the map, that way you can for now at least just about get away without using
BSP trees, PVS and frustum culling. Although it would still require a resonable
spec PC to run because of the extra strain you'll be putting on both the CPU
and GPU.

But please, dont let the complexity of these techniques put you off the subject.
Game development is full of many joys (as well as many headaches haha) and is
very satisfying when you get things running just the way you want.
I certainly felt very pleased with myself when i got my last engine to run at
an exsessively high frame rate.

A final note on BSP trees tho... (im a big fan of these as you maight have guessed)
BSP trees not only lend them selves very well to helping you with rendering
your map very quickly, they are also very good for helping with very efficient collision detection, lighting and shadow casting.

Anyway, good luck with your project. And please keep researching these subjects,
they will benefit you more than i can say!

By the way, sorry if this post is slightly chaotic, I just got in from the pub ;)

Share this post


Link to post
Share on other sites
See I love programming also, that's why I plan going to college for computer engineering. This project that I am currently working is also meant to be the beginning to a long term game project. I just was hoping the get the game to be as impressive as possible (haha, only one using something besides iostream), but I do believe that these concepts are a bit difficult for me right now. When I feel more comfortable I will take time to try these later (probably over summer break).

Thanks a lot zombiebasher and everyone else for you guidance and time.

Share this post


Link to post
Share on other sites
Just a quick comment: please note that most of the Quake techniques that zombiebasher mentioned have become largely obsolete on modern 3D hardware. Specifically PVS and BSP trees. The former are entirely obsolete, and have no use anymore in a modern engine. The latter can be replaced with other spatial structures that are much better suited to the demands of todays GPUs (simple kd-trees, (loose) octrees, ABTs, etc). It is also not true anymore that spatial structures take a long time to precompute. On modern CPUs, spatial partitioning trees for even huge scenes (hundreds of times larger than your typical Quake level) can be computed in seconds. It is also becoming common to rebuild parts of the tree (or the entire tree !) in realtime, so to accommodate moving objects.

That said, this is still a bit too specific for you right now. However, spatial partitioning structures are a very important element of a 3D engine, and you will soon make contact with them. Until then, implementing VBOs and a generic 3D model loader would be your next steps.

Quote:

What method is used in most modern or older games?

Older games are not really relevant, because modern 3D hardware is quite different from older one, and expects different access patterns from your game.

Modern games use a combination of two approaches. The first one is to use a separate array per "shader state". Such a shader state encapsulates, amongst many other things, the texture used by the mesh. This is commonly used for large scene textures, such as building textures, floors, walls, grass, etc.

The other approach is a texture atlas, as Lord_Evil mentioned. They are often used to store a collection of many small textures (like lightmaps or textures for characters), because such textures would otherwise create too many separate vertex arrays, which is detrimental to performance. However, going overboard with texture atlases will also negatively affect performance. Different types of texture atlases exist (2D packing, 3D texture slices, texture arrays, etc). All have their respective pros and cons.

So it's usually a combination between both. Right now, you should start by just using a separate VBO per texture.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this