Latest Diary Entry:
| Wednesday, September 13, 2000 6:40 PM |
| I'm working on another research paper
right now. I'm not saying anything at the moment. It should be done in a
few weeks. However, the reason I'm posting is just to say that I've moved
the site to a new location. The last research article on advanced per
pixel lights and shadowing techniques actually generated so much interest,
I surpassed my monthly bandwidth quota and my site was cut off until the
first of next month. I got more than 1800 hits in approximately the first
36 to 48 hours after posting the article. It was at this point that I got
cut off. I temporarily relocated the site, but I know the same problem
would just crop up again with the next article (more likely that not). So,
I finally set up an account with a new web host to avoid future problems.
All in all, as of this moment, I have received about 3700 hits for the new
article. I'm actually quite impressed, so thanks to those who came and
saw. And thanks to those who emailed kind comments and questions about the
article. I've actually made a few good connections and it looks like some
good things may come out of this before its all through. More on this
later.
Again, thanks for visiting and emailing. Check back soon. My new research project should be done before October.
|
| Thursday, September 7, 2000 4:25 PM |
| Hello again. I got back a little quicker than last
time. Only one month since my last update. In that time I completed another research
project. Actually, it's kinda like part 2 of my previous research project. This time I
took the per-pixel point lights and spot lights and expanded them. The last version only
supported distance attenuation and spotlight filtering. The new demo does a lot more.
First it does self-shadowing, which means that it automatically shadows the polygon if it
is facing away from the light (don't get this confused with a non-convex object casting a
shadow onto itself, that's something a bit different). This is advantageous because before
you had to check each triangle and see if it faces towards or away from a light before
rendering, and then only render those that faced towards it. Now you can just throw
triangles at the card and let it handle the shadowing properly. The next feature added was
diffuse bump mapping. I'm sure most people know what this is by now. Third was specular
bump mapping, which means it makes the surface look shiny when you look at it from certain
angles. The last lighting effect added was gloss mapping, which allows you to specify
which parts of a triangle are glossy/shiny and which are dull. In addition, I also added shadowing to the project. Actually, two types of shadowing. The first is stencil shadow, which isn't really that big of a deal compared to other stuff. The other type of shadowing is depth cube map shadowing. Depth cube shadowing is a variation of depth map shadowing that I came up with. Basically, it allows you to generate the same effect as depth map shadows, but when used on a 360° spherical light (like a point light) it requires less passes to render. Standard depth maps would take up to 6 passes to build the depth maps, and then another 6 passes to apply shadows to the scene. My depth cube maps take up to 6 passes to build (just like the standard depth maps), but only 1 pass to apply shadows to the scene. Its something that I think will be quite useful on upcoming graphics cards. Granted it is a bit slow right now, but I think it could be reasonably fast on one of the nVidia processors that comes out next year. So take a look and tell me what you think. To get to it, click on "Research Projects" on the left nav bar and select "Advanced Per-Pixel Lighting and Shadowing" on the screen that comes up. So what's next? Perhaps another research project, perhaps I'll even rewrite my rendering engine to support all this fun new stuff I've been researching. I've been thinking about rewriting for a while (even before I began any of these research projects). I got to thinking about things and experimenting, and I think I've convinced myself that my 100% true portal, no overdraw method is not the proper technique to be using. On modern processor and graphics cards, I think the time I spend clipping each triangle and processing sectors multiple times (such as when you can see into the same room through 3 different windows) actually end up costing more than it would to render each sector once in its entirety and letting the graphics card just accept the overdraw (and use the z-buffer to deal with it). I'm not sure what to do, but I was thinking about combining the portal system with an octree. I was thinking maybe I could use an octree to store all the polygons. Then, I could also have a set of sectors that encompass all of the geometry. It would be kind of like it is now, in that the portals help define visibility and each sector is convex. Except that right now, a sector is made of visible walls and portals, whereas in the new design, the non-portal sides of the sectors wouldn't be visible (they would just be to help break things up). This would allow a lot of flexibility. In areas where you want to do special effect you could still make the sectors correspond to convex portions of the room and such. I think it would also help tremendously with collision detection. Not to mention it would make the editor a hell of a lot easier. I don't know exactly, its just something I've had in the back of my mind. Ill figure it all out a little better later. Until next time...
|
| Monday, July 31, 2000 2:20 PM |
| I'm getting bad at this. Its been almost 2 months since
the last update. Probably makes it seem like I'm not doing much but in that time I
actually got quite a few things done. First and foremost, I actually got the base networking code in place. It had quite a few bugs from it kinda being hacked together. It could stand to be rewritten from scratch but I'm more concerned with other things right now. What I have so far is a client application and a server application. The server currently has no knowledge of the game environment. All it does is manage connections, receive status updates from players, and periodically update all clients of the state of all players. This allows multiple users to connect to the server from the client, walk around the level, and see the positions and movements of all other players. There's no type of collision detection or other interaction yet. Its just like seeing a bunch of ghosts walking around. However, that is at least as much as I was aiming for right off the bat. The next thing I did was to perform some research on procedurally generated textures. Its an interesting topic that seems to be getting more popular, so I started looking into it. There is a book I want to pick up on the topic that is supposed to be good (Textures and Modeling: A Procedural Approach). However, for the time being, I just worked based off of some info on the web. I came to the conclusion that procedurally generated cloud textures would be an interesting addition to the game, so I focused my research in on that topic. I managed to come up with a sample app demonstrating this capability. The clouds move and change shape over time, and are completely unique...never repeating, never tiling. You can also adjust the cloud cover from thin to thick. I then went and integrated these procedural clouds into the rendering engine. Right now its a little hacked in, but I will clean it up eventually. I have some new images on the screen shots page that show the clouds. You cant see them move obviously, but you can get a good look at them at least. In the near future, hopefully I will have an article and sample app available on the new research projects page that I just created so that you can download and take a look at it in real time. Speaking of the new research projects page, the reason I created it is because I just completed a brand new research project on the topic of real time per-pixel point lights and spot lights. Some of the stuff in it I think is quite unique. You can adjust the light's colors, intensity, and position in real time and the lighting is updated dynamically. The most interesting feature is the spot light. Its something that I think is quite unique. I haven't seen anyone do anything of the sort yet, so hopefully I'm the first. Anyway, the spotlights can do a lot of cool dynamic lighting ranging from flashlights to a disco light. There really isn't room here to say everything I can about it. I really recommend that you go to the research projects page and look at it. I think you will be impressed. And as a bonus, if you happen to have a graphics card with a nVidia GeForce or GeForce 2 chip, you can also download the demo application and experience the benefits of per-pixel lighting for yourself. For those of you with other cards, sorry, but the demo relies upon some of the newest technology only available on GeForce cards. The new ATI Radeon looks like it has similar features, but I don't know for sure all it has yet, as I don't have one. If someone would like to give me a free Radeon card, Id be more that happy to work with it a little bit. But even if the Radeon has all the necessary functionality, I can say without a doubt that it wont be accessed in exactly the same way as the GeForce, so the demo app wont run on it without a reasonable amount of modification. As for that other brand, 3DFX, well what can I say. When it comes to the latest technology, they are seriously falling behind in the game. Their cards don't seem to support any of what I would personally consider advanced technology. The only thing they have going for them is some good anti-aliasing. To tell you the truth, the whole world seems crazy about anti-aliasing, but not me. I tried it and I just think it makes everything blurry. You lose the fine details. I would much rather run all my games at 1600x1200 resolution at 32-bit color (which I must say I am doing on my new 64MB GeForce 2 GTS card from Hercules, and its running great) than run at 1024x768 anti-aliased. The experience just seems nicer. What will I do now and when will I write next? That's probably like trying to figure out how many licks it takes to get to the center of a tootsie roll tootsie pop (no, despite what Mr. Owl says, the answer isn't 3). I guess Ill just see what I come up with next and let you know about it when it happens. Remember to go check out the new screen shots. Until next time....
|
| Wednesday, June 7, 2000 5:57 PM |
| Been a few weeks again. First off, Im a little
embarrassed. I just finally noticed that all the dates appearing in the diary were 1999
instead of 2000. Every week I just do a copy and paste, then change the date and delete
the old entry. Apparently I never even noticed the old date and I just kept copying it
over every time. Oops. Well, that aside, I kinda took a little bit of a break (or maybe you can say I got side-tracked). About 2 weeks ago I got a GeForce 2 GTS. Since then I've been playing around with it quite a bit. I played a lot of Unreal Tournament at first. But then I spent about a week and a half doing some experiments with environment mapping, bump mapping, etc. just to see how it works and to consider how I might implement these features into the game in the future. So while I havent touched the game itself, I dont consider it wasted time. More like research. But now Im ready to get back into the swing of things. Pick up on the networking will be my first priority. I want to get the networked sample goint where 2 games can connect to a server and the 2 people could see each other walking around. So far, the server accepts multiple connections, but it isnt managing the updates and sending them back and forth.
|
| Monday, May 15, 2000 5:57 PM |
| Well, its been a few weeks.
Although I got some stuff done, not as much as I like. I had a bit of stuff to do at work
(including an out of town trip), and I ended up working a lot of overtime. However, I did
get at least a few things done. Adjustable detail levels never got touched. Stencil support is partially implemented. It works fine except when you get right up on a portal, then you get some errors on the other side of it. Ill have to work on that still, as it was just a quick throw in. I also got the game logic separated up a bit more. Loading levels is pretty much dynamic now (though I don't have any type of level select menu yet). I also got the file management utility completed. It allows you to combine multiple files into a single archive (no compression), including nested archives and subfolders. The latest thing Is getting the network code up and running. I have developed a CWinsockSocket class for handling socket functions and communication. It works as either TCP or UDP. It only requires 1 line of code for a UDP socket (plus an extra line if you want to "connect" the socket to a specific remote socket), 2 lines for a TCP client socket, and 3 lines for a TCP sever (plus 2 lines every time you accept a connection). Then just a single line of code to read or write a block of data. In addition, the class also supports both synchronous and asynchronous communication. The next thing was to create a CPlayerConnection class. This class contains a few enhancements over the standard socket. First, it has functions for sending and receiving a complete packet of data (this is a trivial task for UDP, since it works in packets anyway, but for TCP this actually performs a useful service). It also takes care of all the work of establishing a connection between client and server along with validating the connection. The way it works is a follows.
If all went well, at this point, the client and server will share both a TCP connection and a UDP connection. Note that with UDP it isn't strictly necessary for the sockets to be explicitly connected. This was done however in order to filter out any spurious data from other IP addresses as well as to help logically isolate communication with each client. Next steps are to further integrate the CPlayerConnection class and to enhance the server to support loading level, receiving player update packets, and to send out game state packets to the clients. Not too terribly complex, just a lot of work and integration and testing. One of the biggest things with any networked game is to reduce the amount of data sent between client and server. I've been thinking about this quite a bit over the last 3 weeks or so, and I think I've come up with a reasonable solution. I can get the data for a single player down to about 12-13 bytes per update(including 3-D coordinates, view direction, velocity, current weapon, sector, up/down view angle, and playerID. This isn't too bad. My goal is to support up to 64 players on a server, so this comes to 768 to 832 bytes per update for a fully populated game. Not that bad at all. That comes to just about 7-8KB per second if I update at 10 Hz. Granted that's a bit more than a standard 28.8 modem can handle. However, this is just a worse case scenario. There is quite a bit of optimization that can be done. For instance, some things don't change very often, such as the player's weapon or their sector. So by eliminating this data from every packet where it doesn't change, I can cut off about 1KB per second. Other things, such as velocity and rotation and view angle don't change very often either, and could possibly save up to another 1KB/sec. So that could bring packet size down to about 5-6KB/sec. I could also save almost an additional 0.5KB/sec by not sending the player ID with the packet. Instead I would just have to ensure that I send data about every player with each update and provide a single bit at the appropriate position to indicate if a player's data is or isn't included (a player's data isn't included if there are less than 64 players in a game). I figure this would make the break even point to be 10 players. So as long as there are at least 11 players in a game, it would be quicker to not send the player ID. If there are less than 10 players, a little wasted bandwidth isn't as important since even a full update (without the above optimizations) would be less than 1.5KB/sec. Another thing: Since these packets will be sent via UDP, there is the possibility that by not sending unchanged data, a client could lose something such as a weapon change on a player. To solve this, we can just send a complete update once every second or two, and then partial updates per frame. With the above optimizations, I think I can get the packet size down to about 8 bytes per player on average. For a 64 player game at 10Hz updates, this brings the bandwidth down to about 5KB/sec bandwidth. However, a few consideration here. First, a 64 player game will be rather uncommon in all but the most extreme circumstances. On average, a game should be 32 players or less, this cuts the effective bandwidth down to about 2.5KB/s. This in itself is possible on a standard 28.8 modem. In addition, we can make a few considerations. First is that bandwidth is growing all the time, and by game release, 56K may be the low end while DSL and cable modems might be very popular or even the standard. So we can make the assumption that the average player will have a large bandwidth or else they just cant play in 64 player games. Another optimization we can make is to just "punish" players with a slow connection by only sending them an update 2 or 3 times a second. Even at 4 updates/sec, with the above optimization, this could get the bandwidth requirements down to 2KB/sec for a 64 player game. In conclusion, I think there is plenty of room for scalability here... we can eliminate redundant data, we can reduce update frequency for slow connections, and we can assume not all games will be the worst-case 64 player scenarios. Now the above figures don't include overhead for other game data, but as a whole, I think I have a solution that is very capable for a 28.8 modem. This is what the next few weeks (at least) will be spent implementing.
|
| Monday, May 1, 2000 9:30 AM |
| Over the last week, I finished up
the conversion of the menu system. Nothing really important to say about that. I also picked up a trial copy of Intel VTune. Quite an impressive analysis tool. It actually helped me pinpoint a few performance bottlenecks in my code and helped me to fix them up some. It helped performance a little bit. It also helped me see that a few of thoses bottlenecks were bigger than I originally anticipated. One of those bottlenecks is the clipping code, and another is the vector operations. Clipping, vector addition and subtraction, and dot products are accouting for 55-60 percent of execution time. The vector operations are (for the most part) as optimized as I can get with one exception: SSE. I could easily convert the vector operations over to use SSE SIMD instructions. This might just about double the performance (I would expect). Only problem is that I dont own a copy of the Intel compiler and Visual C++ isnt supposed to support SSE code generation until MS releases an update sometime this summer. I could always use assembler, but I havent resorted to that in years, and I dont intend to now either. Its not a really pressing issue, so I'll just put it on the shelf and pick it up later when the SSE support has been added to Visual C++. During the week I also manager to implement a player model. I exported a simple Poser model to a DXF file and wrote a quick DXF loader. When you walk around, the model follows along with the camera, and you can see your reflection in mirrors and stuff. This is really just a primitive model at this time. No real work was put into it. It is just flat shaded, unlit polygons...about 5500 of them. Thats a bit more complex then I care to include. However, being that I am even less interested in spending the time to custom develop a low-poly texture-mapped model, I'll just live with this model for now. The next step is to get networking code started. Just today I got a simple UDP communication app built that allows you to send text messages between 2 computers. Next I intend to expand this into a full comm class that uses UDP for non-critical message (like game state updates and such, which arent critical since, if you miss one, you can always pick up the next one), and TCP for critical messages (such as chat messages, and for client-server connection management). Once that is done I will begin integration of that with the existing game in order to build a simple client-server setup that will allow 2 people to walk through the same world and actually see each other. Other things on the immediate horizon are adjustable detail levels. Right now, if a computer doesnt have hardware OpenGL support (or if it doesnt seem to work right, as I have seen happen on several systems, including some Geforce cards), the game just crawls becuase of the performance impact of bilinear and trilinear filtering, 32-bit color depth, and a few other things. Therefore, I would like to create a detail settings menu that would allow you to turn such features on/off. Another thing sitting on the horizon is implementing stencil buffer support for clipping to portals. Clipping polygons is quite slow. On my system (P3-450), at 30 frames per second, the clipping algorithm can handle about 1300 polygons per frame (4 sided polygon clipped against 4 sided clip volume). It will not be acceptable to clip a whole scene brute force like this. I need to perform some combination of regular clipping along with stencil buffer "clipping". Maybe use the regular clipping for world polygons, and the stencil for objects, players, projectiles and particles, etc. Also on the horizon is a better separation of game logic and level logic. Right now the game is hard coded to load a particular level. What I need is to make loading levels dynamic at runtime. Along with this will be a file management utility. All of the above should be more than enough to keep me busy for at least a few weeks.
|
| Sunday, April 23, 2000 9:30 AM |
| Yesterday I manager to redesing
the menu system to be very flexible. Now creating a menu screen is as easy as defining
menu items, and providing an event handler to react to input for the selected menu item.
To create a menu item, you just call a function which returns a menu item structur, fill
in info like size (all size info is scaled 0 to 1, so it is resolution independant) and
the event handler function. You can create 2 types of menu items: text and image. For a
text menu item, you specify the text and its color for each of 3 states (normal, selected,
and highlighted), alignment (left, center, or right alignment with respect to the
specified x,y coord), and stuff like that. For images, you specify a texture and the
texcoords for each of the 3 states. Somewhat of a lot of initialization code, like maybe
10-14 lines per menu item, however its mostly very similar so you can copy and paste and
change like 4 values to create additional items. All in all not to bad. Then in the event
handler all you have to do is have a switch statement to take appropriate action for
whatever menu item is acted upon. Then you can check the event to see if its a mouse click
or an enter key or whatever, and take appropriate action. Kinda sounds like a lot, but its
actually quite simple. The basic menu class takes care of default keyboard and mouse
handling, so if you dont want to override the default actions of the up and down arrows,
you can just ignore them and the default menu handler will automatically make the down
arrow select the next menu item and so on. Mouse cursor display and handling is also built
in. Today is Easter so not much is gonna get done. Maybe a little tonight. So far I have my main menu converted to the new system. So tonight if I get the chance I want to convert the resolution switching menu over to the new system also. Besides that, nothing else on my list to do right now. Once I get this done (probably tomorrow), Ill regroup and decide which of the 1,000,000 left to do will get done next.
|
| Friday, April 21, 2000 10:24 AM |
| Today was a pretty decent day. I
completed the reorganization of the code. Things are a lot more modular than before. A lot
of after-the-fact cleanup work that stems from this being my first big game project. All
in all, not to bad though. I also got started on my menuing system. I have a basic menuing
system in place that allows you to start a walkthrough of the game or change resolutions.
The simple menu system allows for fullscreen window menus with mouse support halfway
integrated. Mouse cursor control is fully encapsulated, however, mouse click control is
manually coded into each menu page. I would like to implement a slightly better system
that allows you to define "hotspots" and will automatically track the mouse
movement and clicking on these "hotspots". As far as the improvements on the font engine, that is semi-implemented. I have a way to create larger and smaller fonts now, though it is somewhat of a hack. I would like to implement a much better system. Right now I have the font renderer using a virtual coord system, and by telling it that a 800x600 window is actually 400x300, you can make the fonts 2x as big. It works for a hacked implementation. It allows me to get enough done. Ive been thinking how I actually want to implement a cleaner version of the system. I think possibly a textout function that takes a scale (x,y) from 0 to 1, and a font size from 0 to 1 (0 = invisible, 1 = full height of the screen). Still have to think about this a bit. Also, Ive noticed something odd about my resolution switching code. When changing resolutions, I dont specify a refresh rate (I figure this would be a bad thing to do in case the monitor doesnt like the refresh, and I heard under 95 or 98, you actually can't pick the refresh yourself anyway). Im developing under 2000 right now, and I noticed that when my display modes are enumerated, I get multiple modes with the same res but differnet refresh rates. I was always told before that if you dont specify a refresh when changing display modes, win will pick the default refresh rate for you. However, that is not the case (at least on my Win2K dev machine). My desktop res is 1152x864 32-bit 75Hz. Yet when I set the mode to 1152x864 32-bit without specifying a refresh, I am getting something that is not 75Hz (its either 60Hz or 70Hz I think...I would guess 60Hz). I need to figure out how to get this going better. Maybe a dig through MSDN or some mailing lists will turn up an answer. Someone else has had to have faced this.
|
| Friday, April 21, 2000 7:16 AM |
| I have now added objects to the
sectors. This means you can have things like crates and barrels in the middle of a room. I
have some rough collision detection code running on that right now. It definitely detects
the collision just fine and prevents it. However, I doesnt work as good as I want it. With
my world collision detection, it works like in most games, so when you walk into a wall
dead on, you stop. However if you walk into it at a slight angle, you slide a little, and
a steeper angle will make you slide more. Thats the way things should work, and its how my
walls works, but I dont have the objects in sectors woking that well. Ill come back to
that a little bit later. The next thing to work on is reorganizing the game slightly. While I have been building the engine very modularly, In order to get things up and running quickly and painlessly, a lot of the classes are tied together sloppily...a carryover from some of the older code. Basicly, I didnt want to waste the time to divide everything up completely when I wasn't really sure how it was going to work. But now that things are up and going good, I feel its time to make those changes now, before everything gets more integrated and starts getting really sloppy. I started this cleanup process yesterday. At the same time, Im modifying my game to have a configuration menu. Last night, I got a simple resolution config menu going, where you can actually set the display resolution & bit depth. And while I was developing that, I had to clean up my resolution switching code to support this. My original implementation of the res switching code was enough to start the game, switch to any res, do whatever, switch back, and end the game. Changing the resolution more than once at runtime was not supported. So obviously I got that all fixed. I also have a logo on that menu screen (the logo you see at the top of this site). This menu system was a thrown in as a replacement for the "game" engine. Basically, my design includes an base CInterfaceObject class, which provides the mechanism for interfacing with the user. You can then derive any class from this base class, and use an instance of the new class as your current user interface. My "game" engine is derived from this class, as is my menu system. Right now, I just create an instance of my menu rather than the game engine. So I still need to make it so that, from the menu, you can invoke the game, and then return from the game to the menu, and so on. Hence on my list for today (and this weekend):
|
| Sunday, April 16, 2000 9:27 PM |
| Well again, its been a while
since I wrote in here. A lot has happened since my last update. Basically, I havent
touched this since last July. I know, thats almost 9 months. But a lot has happened, so I
have an excuse. I got completely tied up with my last semester of college, and literally
had no time at all to work on Apparition from mid August to mid September (except maybe 3
or 4 hours spread out over that time period). But now I finally graduated from the
University of Michigan - Dearborn. After 10 semesters of full time classes, I graduated
with a 4.0 GPA. Five years of perfect grades. Having so much riding on my last semester
(even one A- could ruin the whole 4.0 thing). That just got so stressful, but now Im done
with all of that for good. Now I have a full time job, but when I comehome, its my time,
so I dont have to worry about homework slowing things down. Anyway, those of you that visited here before may remember that Apparition used to be a Real Time Strategy game. Well, a couple of things happened. After developing my experimental / proof of concept engine about half way through, I realized a few things. First, I realized I didnt like Direct 3D. The API is just straight out cumbersome. I think I spent more time working around the API than I did actually develop anything. I was using DirectX 6. I hear DirectX 7 is better, and the upcomming DirectX 8 is supposed to be great. However, I learned OpenGL and realized how much better and simple it was to work with. I found myself actually getting work done. So I trashed my proof of concept engine and started over with a new OpenGL version of the proof of concept engine. However, at the same time, I decided that a lot more of my interest lies in graphics and 3D mathematics than it does in artificial intelligence algorithms. Because of this, and because I have always favored FPS games since Wolfenstein 3D (not to mention that my original game development experiments we also FPS), I decided to start completely from scratch and design a FPS. That was mid December. By January 1, 2000, I had a decent, simple demo of and FPS going (or at least the renderer), and Ive been improving and adding features since then. I am loving OpenGL. I have modularized my game quite well, so when I get closer to completion, it will be relatively trivial to add Direct3D support for whatever version of DirectX is current. However, DirectX changes so often, I decided it isnt really worth worrying about for the time being. As of now, I have the following features in my engine:
I have a parital level editor in the works. It has some of the logic for dealing with the portal system, but is so far completely incapable of generating any type of level. Thus, the 2 existing test levels are 100% hand coded. I manually specified hundreds of verticies, and texture coordinates to create those levels. A lot of work, but it allowed me to get some things off the ground a lot quicker than waiting for a complete level editor to be finished. I have a series of features that are close on the horizon. As mentioned above, Volumetric Fog has currently been removed until I can find a more optimized way of dealing with it. The previous demo used a somewhat brute-force attack at generating the fog. I did some a quick and dirty attempt at drawing the fog, and my algorithms for subdividing trianges was nowhere near optimized. At some points, drawing the fog consumed 5000 or more triangles, only about 10% or less of which were actually important and necessary. I've been thinking of taking another stab at it, since I have some new ideas in my head, but Im hesitant about wasting time on it until I think it through further. Other features that I may tackle soon are
|