Archive for March 2008

Multi-Threading

C# makes it easy to do multi-threading but I havn’t been able to make it speed up Bunnies any yet. The issue I found was that I had to pass in an object to the render function which contained the parameters of the function. And then, if more than one thread wanted to render a portion of the screen I had to have local copies of all the variables that the render function needed to work.

So, any advantage to using more than one thread was lost on initializing and cleaning up local variables.

Before I try again I think I’ll need to do more code cleanup to organize variables better. I may be able to allow a fixed number of rendering threads and avoid some overhead.

Bilinear Filtering

One of the lingering issues with Bunnies was pixelated graphics. While I was poking around looking at various Ray Tracing information on the web I stumbled across a method for doing bilinear filtering.

My version follows the same basic principles but modified to work with my existing code. Of course when the source texture is really low resolution it’s going to still look like trash but this allows you to see what’s going on. Bilinear filtering is best suited for textures that are slightly stretched such as the walls.

Full Screen Z-Buffer

One of the issues with having bouncing bunnies is that they sometimes jump higher than the walls. Now I could just make sure objects can’t go higher than the walls but that would be silly. The whole point of Bunnies is to get rid of restrictions that were imposed by Wolf3D.

One of the advances in 2.0.4 is the full screen z-buffer. Now bunnies can be behind a wall and jump higher than it. Previously if a bunny was half behind a wall and they jumped higher than the wall, the part behind the wall wouldn’t render so you’d see half a bunny in mid-air.

This will lead to issues with jumping through ceilings but I’ll deal with that later. For now any level with bunnies should keep them outdoors to avoid the issue.

Another issue that’s coming up is the framerate. All these added features are starting to eat up processing power.

If a sprite isn’t on screen then it isn’t rendered. If bump maps or lighting aren’t on then the normals aren’t calculated for objects.

But, collision detection now has 8 checks per move instead of one. This keeps bunnies from going through walls but slows down things a notch.

As I move along with this project I’ll keep looking for bottlenecks and try to remove them.

MOD for Floats

The mod operator basically gives you the whole number remainder when you divide two numbers. That works great for integers.

But let’s say you have a variable that is a radian and you want to keep it between 0 and 2*PI. You could do something like


if(v > 2 * PI)
v = v - 2*PI

But now what if v is negative or v is greater than 4*PI?


public static double fmod(double v, double m)
{
if (v * m == 0) return 0;
double d;
if (v < 0)
{
v = -v;
d = v / m;
v = 1.0 - d + Math.Floor(d);
if(v == 1.0) return 0;
}
else
{
d = v / m;
v = d - Math.Floor(d);
}
return v * m;
}

Let’s say v is 5 and m is 3.

d = 5/3 = 1.6667

Floor(d) = 1 so 1.6667 - 1 = 0.6667

0.6667 * 3 = 2

Which is correct. It’s all very clever. When v is negative we just take the inverse result. So let’s imagine that v was -5 then the fmod(-5,3) would be 1 which is correct. If you don’t believe me, draw a circle with three numbered points, start at 0 and go backwards 5 spaces and see where you end up.

So now we can wrap any number around any limit. The difference between mod and fmod is that mod limits the result between 0 and m-1 where fmod limits the results between 0 and m minus an infintesmally amount.

This method has always been used in Bunnies to allow for textures of any size. It’s just a lot more subtle.


uh = ray_x - (int)ray_x;

and

uv = ray_y - (int)ray_y;
if (ray_cos < 0)
uv = 1.0 - uv;

All we’re doing is getting rid of the whole value and the fractional part is the value between 0 and 0.999999 which gets us the pixel that we want from our texture when we multiply it by the size of our texture.

Bump Mapping for Objects

Walls, floors and ceilings are easy. The bump map always faces the same direction.

The bump map for an object rotates depending on the viewing angle of the camera. So first you have to calculate the angle between the camera and the object. Then you have to rotate the bump map as though it were a wall to get it vertical. And finally you have to rotate the bump map around the vertical axis to face the camera.

It’s not the cheapest operation but it makes everything look more realistic. I still need to update the Bunnies web-site to allow for users to define the bump/depth maps for tiles.

I’ll also be creating new object textures to replace the Wolf3D ones.

Random Stuff

The Bunnies web-site has been updated. There were two key issues slowing the site down. One was that everything, including images, was going through index.php and the second was that index.php was logging every request. Index.php includes every supporting script needed to run the site. This meant a lot of unneccessary compiling just to load an image. So now there’s a second script, image.php, which only loads what is needed to render an image. This is way much faster. Also, not logging sped things up quite a bit as well since the site is no longer writing to a file on every page load.

Also, I learned that in C# you can have real multiline strings.

http://msdn2.microsoft.com/en-us/library/aa287596(VS.71).aspx


string myString1 = "This is the first line of my string.\n" +
"This is the second line of my string.\n" +
"This is the third line of the string.\n";

string myString2 = @"This is the first line of my string.
This is the second line of my string.
This is the third line of the string.";

The first way is the standard string concat method which is incredibly horrible to work with. Especially when you’re trying to create dynamic web-sites. The second method is what every real scripting language supports. And thank goodness C# does as well.

The “@” symbol in front of a string tells the compile to interpret the text literally. Without the “@” you would have to use “\n” to create a linebreak. With it, you just hit enter and start your new line. It’s not exactly the same as how languages like PHP and Perl work but it’s good enough.

There is nothing worse than trying to put together a block of HTML without multiline and then trying to edit it later. It’s a complete mess.

Bump Map Demonstration


No lighting effects


Basic lighting


Lighting with bump/depth maps applied

You can easily see what a huge difference it makes. I did find a small bug however, if you minimize the window it tries to set the resolution to 0,0 which crashes the program. Once that is fixed the game code for 2.0.3 will be finished. The final step is some updates to the Bunnies web-site so you can easily apply bump/depth maps to tiles.

Bunnies 2.0.3 is Almost Ready

Version 2.0.3 is adding bump maps and depth maps to tiles. Technically the objects could take advantage of these features as well but that’s a client side issue since sprite textures are not handled by the Bunnies web-site fully. That’s something that needs a lot of work.

A bump map defines the angle of the points on the surface; the normals that determine the angle at which a light source hits the surface. It’s called a “bump map” because they’re used to create bumpy surfaces. But bump maps are not sufficient. Imagine a pure white bump map with a black square somewhere on it. A bump map will not show a dark hole on the surface. It will show a very thin ridge on the surface around the square.

That’s where the depth map comes in. The depth map is used to create indents on a surface based on the gray scale value. Black is zero depth and white is maximum depth. So now we take the same white tile with a black square and use it as a depth map. Because black is zero depth we will see a very dark area around a light colored square.

By combining a bump map with a depth map you can turn any simple looking surface into a very complexly lit surface with all sorts of ridges and bumps.

Surprisingly the bump map doesn’t affect the frame rate significantly. It’s actually a pretty simple operation.

The game server and the database support depth and bump maps but the Bunnies web-site does not. Meaning you can’t set the bump or depth map through the web-site. For testing I manually update the tile in the database. So it’ll still be a day or two before this version is released. I’d also like to come up with some textures for the sample level that make the level look cartoony with simple lighting or no lighting at all and look very realistic with bump and depth maps on.

On the web-site I also finally added support for directories. You can now stuff your source image files into directories to help sort them out. I have hundreds of images in my account and it was getting ridiculous.

Bump Mapping

That wall actually has a pure white texture. A bump map is applied and two lights are in the map. One is colored and the other is a white light.

The bump map is pre-calculated for the texture using a grayscale image. There is still some tweaking and testing to do before a release but Bunnies 2.0.3 should be out this weekend or early next week.

One of the obvious issues is defining bump maps. Currently the Bunnies web-site doesn’t support that sort of thing nor does the game server.

Lighting with Normals

The left side is lighting without normals. You can see that the light wraps around the corner. That’s because lighting is based only on distance and visibility. Since the check for visibility is not exact the light shows up where it shouldn’t. Now, I could do more precise visibility calculations or I could do it the easy way; with normals.

A normal is a direction vector. Since the light is coming towards the camera and that wall is facing towards the camera, the light hits the back of the wall which is not visible to the player so the wall is not affected by that particular light. This gets rid of the light that wraps around the corner as you can see on the right side image.

You can also see that the light renders more realistically. Real light is not just affected by the distance from the light source to the point but also by the angle that the light hits the point.

This is all in preparation for bump mapping. Currently a wall/floor faces a single direction. A bump map is used to change the normal of a point on a surface to adjust the light creating bumps. Right now the surfaces look curved because they’re painted with premade shadows. With a bump map you can have the texture be solid colors and create the shadows on the surface dynamically which is much more realistic.

That triangle is actually white. All the shadows and colors are created with colored lights and a bump map.

ss_blog_claim=70b9168863fc97c91e6d88b40542a327 ss_blog_claim=70b9168863fc97c91e6d88b40542a327