About this blog
A first but serious attempt to create a game.
Entries in this blog
Finally, I'm ready to make another entry for this journal. I've been really looking forward to it. But I do not wish to add irrelevant progress updates or personal messages to this journal. Instead, I will set goals for each next entry. I believe this approach is to my advantage.
I've been working on my ideas for this game for quite some time already. Only after playing around with cartoon rendering techniques, and coming up with an elegant method for my game, I was willing to start my journal. The only thing missing from my (graphics) list were shadows. After doing some research I was sure I wanted to use stencil (or volumetric) shadows. They proved to be somewhat difficult to implement nicely though. Certainly, without the willingness to use OpenGL extensions (and sticking to OpenGL 1.1) this is a bit tricky. Furthermore, finding all light source facing triangles of each model (as well as creating a shadow volume for them) didn't sound like fun to me. I pretty much wanted to find a solution to this problem, since I knew that shadows would make my game look much better. Finally, I came up with a relatively nice and clean solution that involves only a few calculations for the CPU and a bit more on the GPU. I will explain this in the next section. Please note that I haven't tested it yet.
OBJECTS & MODELS
Some time ago, I made a list of requirements for the graphics in my game. Obviously, there will be static 3D models (I will call them 'objects') for all sorts of things. Additionally, some models will have parts (objects) that should rotate relative to each other. This can be said for about each game there is. Well, in addition, I want my game to be able to generate models for (human) characters itself, based on a few parameters. I want to have some gradations between normal, fat, and tall, as well as muscular men and voluptuous woman, with clothing to match. And of course, I will simply use matching vertices over a few models to do this.
The shadows that a model will cast on intself and it's environment will be encoded in the models too. To do this, I will first start to look at an object's complexity, then I will define some planes of vertices for the object (like cross-sections). These can be combined to cast a good shadow approximation of the object's shape. I will start drawing the object by putting vertices on these planes. Sometimes simply connecting vertices into triangles between different planes will suffice for an object. In other occaisions, extra vertices will be required. A bonus to this approach is that it resembles building a 3D-model from (more simple to draw) side-views. Simply drawing a line through all vertives on a single plane will give a strong visual hint of the object's appearance. This approach should work pretty well, especially on low polygon models where there are not too much 'floating' vertices required between the planes.
I will use indexed vertex-arrays for rendering. I will store vertex, normal and color information, and combine vertices where I can. The first vertex of an object's array is reserved for rendering shadows. Now when it's time to render shadows, this vertex has to be calculated. It's function is to provide a focal point for a triangle fan for all vertices of a particular (shadow) plane of the object. This fan, which is also rendered using (stored) indices will form a shadow volume for each of the planes. The information stored is simply all indices of the vertices on a plane, that combine together with the focal point to form a triangle fan shadow volume. If the focal point if far away enough, it'll make the volume appear 'straight'. Taking the relative orientation of an object's shadow volumes into account, they can be rendered in pretty much the same way as in the z-pass or z-fail algorithms, simply by adding or substracting the stencil values (if their orientation is not taken into account, different volumes will stencil each other out). Depending on a volume's orientation, values should be either added or substracted. Switching cull faces should also work.
So much for the theoretical work. Now on to some more practical issues.
THE FIRST STEPS
Creating a game involves lots of things. As with any program in any programming language, adopting a protocol for naming conventions is a good place to start I guess. I took quite some time setting up this protocol. I also wanted a very uniform structure and layout of my files, and will spend a considerable amount of time maintaining that. With only about 2000 lines of code, I can already clearly see the benefits of this. When you know where to go; the next things are functions and classes and such, and where to put them. It really pays off to think a lot about that sort of things.
My game will be window-based, and does not require split-second user interaction, so I will need to proces some Win32 API messages. I defined my own game events, enclosed them in a structure and put this and all window-related code in one file. I can now easily switch between different event handlers by changing a pointer. This was a very good first and nescesarry step. After this, I realized that I could speed up development time by writing some tools that can operate while I am testing my game. To make this possible I will need a user interface with controls, and an easy way of setting it up. I therefore added another project file that defines these controls, and handles all game events for them (I knew my events would come in handy). Here are the controls I have so far:
I've got simple labels, buttons, edit boxes (with different input filters for integers, floating point numbers and filenames), list boxes (that can additionally display colors), and some nice HSL color selection bars. The mouse pointer is changed appropriately over controls and the scroll wheel is used with list boxes. Relevant events are routed to event handlers for each control. Other controls can be implemented with a few lines of code, and an interface is set up very easily too. Of course, there is also a control that can be used for more serious rendering (that's the one with the diagonal line). Lots of tools can be created with these controls, but there are some limitations however. Controls cannot size dynamically; but hey, who cares?
My HSL color selection bars are the most elegant method of selecting a color I have seen. At all times, the color under the slide-button on all three bars is equal. Changing its position on one bar changes the colors on the other bars. This is very comfortable when trying to find 'matching' colors. The fixed-width font is based on the C64 font. :)
ps. Using the Win32 API: does anybody know how to change a window's caption, without changing the text in the associated button on the taskbar? -Thanks.>
AND SO IT BEGINS
-I just hope it'll go somewhere from here too-
Ever since the days of the good old C64 I've been thinking about creating my own computer games. So far nothing happened. Just thinking about it suited me better I guess. I started late too. When it was a good enough time to finally start writing in assembly the C64 had become too much of a museum-piece.
On the 64, writing a few k's in mnemonics sounded ok. But the age of PC-DOS had went unnoticed already, and mnemonics under a Windows environment just didn't seem like the right thing for me.
Finally I stumbled upon C++. During my study of environmental sciences I was able to spend some time learning C++, and actually earned bit of money in doing so too. I discovered OpenGL later on, and quickly bought the Redbook.
Well, that's enough about me for now, as I feel a bit uncomfortable writing about myself in this journal.
As I said, i've been thinking about creating games for a long time. Since some time, my often fuzzy ideas about 'my kind of game' evolved into more clearly defined shapes. At this moment, I feel confident enough to start working on some of the details. I will restrict my ideas for the game to short side notes. One piece of advise: It is a very good idea to start with writing a plan for your game, and as extensive as possible. GameDev has some great articles about this. Read them.
For now, I've set myself up comfortably with the (free) Borland compiler, and ConTEXT. Now this is quite some tool. While editing my code with syntax highlighting, I can compile and execute the whole lot, as well as display C++ help. It's almost like a IDE, I just love it.
TRADING ROUTE & GRAPHICS
My game will have a simple cartoon-style look to it. I want cell-shading, outlines and shadows. Furthermore I want semi-transparant water with waves. I also want atmospheric effects, with at least differences in day and night. At a later stage I might include weaher conditions too.
Now, I like things neat and efficient, I prefer nice short code over messy code (since I'll spend enough time going through it), and I prefer the GPU over CPU for graphics rendering (I need the CPU for AI too). Nothing new of course, but I am very willing to make compromises. I won't spend costly CPU time on some nice graphical feature, instead I'll look for an alternative or I won't implement it at all.
Another thing concerning graphics is the time it takes to design them. I like to design graphics, but only as long as it doesn't take too long. A cartoon-style therefore suits me; plain colors instead of textures -I love it.
For now, I prefer to use the core OpenGL 1.1. I have no idea how many people have GFX-cards that fully support OpenGL 2.0. As long as I do not, I will stick to 1.1. I want the audience for my game to be as large as possible. I do not aim for visual effects, which I guess is as humble as realistic in this one man's show.
TRADING ROUTE & CELL-SHADING
The one thing about cartoon style rendering (in OpenGL 1.1) that I did not like, is CPU calculations. In methods that I've read so far a 1D-texture is used, and texture coordinates for each vertex are CPU-calculated using the angle between normal and light source.
I've devised a method to do cartoon-style shading WITHOUT ANY calculations, while still being able to rotate the light source around my models, as well as controling the color of the light (day/night differences). The method implies drawing an invisible sphere, projecting a simple 1D-texture map as contours on it (while using some texture matrix adjustments), and loading the resulting image as a texture for an environment map. This all is done by OpenGL in a short display-list. I only set the angles of the light direction before executing the list. The fragment is color-modulated with the environment mapping texture, and alpha blending for semi-transparant fragments can be done too. I've also managed to avoid environment mapping 'polar' distortions by adjusting the texture matrix.
I like this method, it suits my needs and wishes. Here's a view of the approach. The hidden sphere, to be used as the environment map texture is shown. Using OpenGL, a simple 1D-texture is projected as a contour on the sphere's surface.
The results are surely adequate. You can run into a bit of trouble though, if the environment mapping texture's size is smaller than the curvature of the model on screen. For a scene like this, the texture could be larger. The polygon-offset (for rendering the model's outlines) could be better obviously, but this is not the intended scale of things in my game.>>