Sunday, June 28, 2009

Test3D


I took a break from programming City3D and played around with a program I have called Test3D today. It was one of my first 3D programming attempts and I have used it to test out new ideas and concepts I have learned. It actually looks pretty nice, I programmed it using the Glut library, something I avoid these days as it is a dated library and you can do everything it does on your own easily. My Test3D program has a nice rendered terrain with hills, trees, a detail texture so it looks better. It has real time lighting which I was proud to finally get working and a little idea I got I called "extended terrain" which basically allows you to walk on forever, the terrain just repeats itself as you go. Probably a useless feature, but it gets rid of those ugly borders where your 3D terrain suddenly comes to an end. I may do some more work on this just to practice my 3D programming more and come back to working on my City3D program later. City3D looks more primitive in comparison, but it is a "newer" project. It was created entirely without Glut and just with normal Windows + OpenGL programming, no extra libraries. I also want City3D to be a game, so I have tried to keep it simple. I may still need to start it over from scratch. I will probably work on a more detailed design document and try and get down on paper what I want it to do and how to do the 3D optimizations. The most important thing I need to redesign is the way the maps/levels are stored. The way the data is organized is THE most important part of creating a good 3D game. For example, you need to store your levels as a list of polygons for most of them. You can have some 3D objects loaded in separately, nothing too big, but the majority of your base level needs to be a list of polygons in something like a Quad Tree or something of that nature so that you can optimize rendering for things like Frustum Culling, Occlusion Culling as well as collision detection. Without your level data organized properly you can't do any of these very well. A lesson I have learned too late. Oh, you CAN do collision detection for example, but without frustum culling, or a quad tree (or similar data structure) you would need to test EVERY polygon in your level every time you moved for collision! As you can imagine, this would get very slow. With Quad Trees you can narrow down where you are, in a small section, then ONLY check the polygons in that section of your level. With frustum culling you can use math to figure out which sections of your level fall within your field of view, then ONLY render them. With Occlusion Culling you can check the polygons of the area you wish to render (within your frustum) and only render the polygons that actually face you. As you can see, with all these optimizations in place you can really cut down on the amount of polygons you will be sending to the video card to render and speeding things up. You can go further by using Level of Detail optimizations to lower the detail of objects that are further away from you, thus lowering the number of polygons sent to the video card. Video cards are fast, but the process of sending polygons TO the video card is the slow part (also called the "bottleneck"). Anyhow, I am experimenting with all this with my Test3D program, it's also fun to work with as it is starting to look really nice. If you're interested, you can download Test3D here: Test3D.zip

Monday, June 22, 2009

Skybox + enhanced text

I was bored with the way the game's sky looked. I wanted the buildings to appear out of a fog in the distance so you didn't just see them "pop" into existance as you moved. I was greatly influenced by the way Battlefield 1942 done their 3D. It looks very good, yet they used some simple techniques. They use coloured fog combined with a skybox that has the same colour as the fog near the horizon so that it blends in nicely and you see building, terrain etc... gradually appear in the distance, seeminly out of nowhere. I implemented the fog, just a normal grey fog, so my sky needed to be grey as well, either that or have a night time city so my fog colour could be black. Very boring. I finally decided to implement my skybox. I used Terragen to create the sky, this is a very nice program, it's also free and I am 99% certain this is what the people used in Battlefield 1942 to create their skies. For a skybox it's actually a very simple technique to give a realistic sky. You basically have a 3D Cube and you're point of view is in the center of this cube. The cube then rotates when you turn, but you always stay at the center of it. The terrain, buildings etc... are all then rendered inside this cube. To create textures for the cube so you don't look like you're inside a cube, but outdoors, you need to generate a view for each side of the cube that has a 90 degree field of view. Just do your math, you have 4 sides, 90 x 4 = 360... you end up with a panoramic 360 degree view. This is the same technique that was first used in games like Myst 3: Exile, it's also the reason why 3D acceleration actually improved the look of Exile. In exile the entire game you see is all just textures rendered on the inside of a cube! Really ingenious if you ask me, so simple, yet the effect was very nice, you could use your mouse to turn and look in all directions smoothly for the first time in a game ever. They took it a step further in Exile, they animated the textures on the cube's wall so you seen water shimmering, animals swim away when you got too close etc. I'm just going to have a normal texture with a nice blue sky with clouds. A simple idea, but very effective when you see the end result.

While working on my game I have text that is rendered on the screen displaying various variable values (say that 10 times fast! ;)). OpenGL has no option to display text (strange, but true) so text has to be rendered in special way. I won't go into details, but I got it done. I had it displaying red text, mainly because that colour seemed to stand out on the screen against the background but it was still not quite right so I made the game render black text behind it so it stands out better. The text looks a little aliased at the moment so I may look into other techniques to display text. At the moment you can choose from any font you wish, which is kind of nice, but it isn't really all that nessecary. I may look into rendering text from premade characters rendered on a bitmap. This way various colours and antialiasing can be added to them and whatever other effects you can add to an image. Will make for nice looking text for actual game text. Perhaps I can reserve the current method just for programming information.

I'm honestly not sure where I want to go next. I have the functions already created, in a seperate program, to import 3D models, which will make for some nice looking buildings, and even roads etc. But I don't know if I want to do that in game. I may save model importing for a level editor. This way models can be imported into a level, and then when the level is completed, the polygons can be all saved together for the level, allowing the entire level to be divided up in game, into a quad tree so I can use frustum culling and other speed optimizations as well as proper collision detection. I currently use 2D collision detection. I basically check your position on the 2D map and if you're inside a square that is supposed to be a building or other item, you stop. You can see how this is 2D by trying to fly over a building. It can't be done. Not that flying will be in the final version, this is meant to be a driving/tank game anyhow. I plan on working on a full 3D space game (already started!) seperately. You can download the current build here: City3D.zip (about 5.6megs).

Saturday, June 20, 2009

City3D




I started work on a small project to help me learn to program 3D using OpenGL. I am making a 3D map with a city style landscape, office buildings, roads and the like. I'm not sure if I want you driving around in a car for some reason or a tank. For now I have the movement set up so you move like you would in a tank. It's just easier this way and allows a little more freedom in movement. You can also fly up into the air to look down over the area but in the finished program there wouldn't be any flying as this is meant to be more of a land vehicle style game.

So far it is running rather well, but there was an unforeseen problem. I done a simple in game grid map with square spots like a 2D game, each being grass, road, building or whatever in a square grid. Then, the game creates a cube style building, textured etc, square flat piece for grass etc. This is temporary as I plan to load in 3D Models later on. I actually have a seperate program I worked on to learn to load in 3D Studio Max .ASC (text) models, and I have it working. Now my problem I have is when i started researching collision detection in 3D games. There's a lot more to it than one might think. In a 2D game, it is fairly straight forward, you check your position on the map and compare it to the location of buildings or other in game objects. In 3D it requires more preparation ahead of time. You want the program to test your position against ALL the polygons in the game... this would be time consuming, but... even in this simple case of checking all polygons, you need to have all polygons that will be used in the game in a list of some sort so you can check them. Creating on the fly objects in the game simply won't due. This means I have to design some sort of level editor and then a method to add polygons from any imported objects to the list as well... or just have the level editor import objects then merge them with the level I s'pose. So, I have to redesign the game, almost from scratch. Learning is a pain at times.

Once you get a level editor made and a level loaded into a game, you can then work on optimizing things for speed. You don't want to have to check every polgon in the game everytime you move after all! Well, with a list of polygons you can then use something called a Quad Tree... which basically sorts your polygon list into quadrants so you narrow down only a small number of polygons that are in the same quadrant as you are, then you search them for collision = faster. This also means you can speed things up when drawing your scene by only drawing polygons that fall within your field of view... also called a "frustum", which is just that area you see in a 3D game and excludes all polygons that fall outside that. This speeds things up a lot... you use your quad tree to discover which zones fall within your field of view then you only render the polygons in those quads. You can then take this a step further and only draw the polygons that actually face the viewer, no sense drawing polygons that aren't facing you after all right? This is called occlusion culling.

By now you might be thinking, "why should I go through all this trouble to speed things up, what's a couple extra polygons? My Video card is a super duper extra fast polgon rendering machine!", you've got some nerve asking such a question! :) You would be right though, IF all those polygons could be sent directly to the card without any problems I would agree, although there are still good reasons to speed things up. The faster it runs, the more detail you can add and the better looking your scene will be. There's another good reason. All those polygons need to be sent to the 3D Card, the slowdown comes when the data is actually sent to the card. This is a slow process, and the less data you send to the card, the faster it will all be rendered. You would be surprised at how much this improves things. I once created a 3D program that drew a simple landscape with trees, each tree consists of a simple 6 sided trunk with two polygons making up the branches, FAR LESS detailed than anything from modern games... when I ran the program with a higher detailed landscape and lots of trees I got 1 FPS!!! :) No optimizations.

Another optimization I want to do is called Level of Detail (LoD), this is where the farther an object is away from the viewer, the less detail (less polygons) are rendered. Some objects require a lower resolution version. Trees can be rendered as a single polgyon image at a far distance that always faces the viewer and is switched out for a higher and higher detailed model as it gets closer. This is done in most games that have lots of trees in them. You don't notice the difference, not at large distances, but you sure notice the speed.

Anyhow, this is a langthy description of what I wish to do. It's a long road but I really hope to get most of this done and have a good understanding of how to program a decent 3D game. I'll try to post my progress here, it may help someone else and will help keep me focused.