Subscribe to The Gamer's Algorithms to Goove By        RSS Feed

Maps: Using Image Files to Store Data

Icon Leave Comment
This is a 2D, I mean 3D, algorithm. Actually, it's both. I'll explain why.

I started to discuss Height Maps as they pertain to the terrain we discussed in the "Brute Force Terrain" algorithm and realized that maps are much more ubiquitous than just height maps.

As a programmer, I'm sure you're familiar with arrays. Arrays are used to control and store data all the time in game programs. One example of such an array is the height data array in the "Brute Force Terrain" algorithm. In that algorithm, the data in the array represents the altitude, or heights, of the corners of the grid squares (quads) that form the terrain grid. By putting data into that array, you specify the shape of the terrain with all of the corners regularly spaced and only the altitude of the quad corners changing.

Maps and arrays tend to go hand-in-hand. Imagine that we have our terrain with all of it's heights stored in an array. Now imagine we store those heights in an image file. Each value in the array becomes a texel (texture pixel) in the image. So, it must be converted to a "color".

There are many many different image file formats and ways of storing colors in images. One common method, and the one we will look closest at here, is 32 bit RGBA. That's 8 bits for Red, 8 bits for Green, 8 bits for Blue, and 8 bits for alpha. Keep in mind that this is just one of many ways to store color data. 8 bits holds 256 unique values and so each "color" in this format can be from 0 (black) to 255 (full color). Red, green, and blue can be combined to form all the colors humans can see. In fact, the 24 bits of those 3 colors can represent over 16.7 million unique colors. That's a broader range of color than humans can actually see. The fourth byte is what is known as the "alpha" channel.

Not all color formats even have an alpha channel. But the alpha channel represents transparency. If the alpha value of the color is 0, it is fully transparent. If the alpha value of the color is 255, it is fully opaque as if there were no alpha. What this actually does is determine how much of the color "behind" it to blend in with the RGB color. So, if it's fully transparent, with a value of 0 then you will see the background instead of the color of the texel.

One other fact I would like to throw out here is that when Red, Green, and Blue are equal the result is grey. The only exception of that is that when they are all 0 you have black and when they are all 255 you have white, everything in between is one of the remaining 254 shades of grey.

So, let's say we want to store the data in our height map array in a greyscale image. This is a common industry practice. What you would need to do is convert every value stored in the array to be between 0 and 255. One way to do this is to get the highest value and the lowest value and subtract the lowest value from all values to reposition everything to start at zero and then divide by the highest value (after it has the lowest value subtracted from it) for every value. This turns every value into a percentage. Once every altitude value is turned into a percentage, you can then multiply it by 255 to put it into the 0 to 255 range. The color values are integers and so you have to drop the remainder, or decimal values, or otherwise round the numbers to integers. At this point, you have a 1 byte color value. If you assign this value to red, green, and blue, you will be storing the greyscale value in the color image.

Every image file is written to disk differently, with different headers and formats and compression and such. But basically, this is how it's done. You take an array that matches the image size, such as 512 by 512 (it should always be a power of 2 which is 2 to the nth power in size on one side), and you assign the color value to every texel in the image that matches the positions in the array. In short, you convert the array data into colors and store those color values in the image.

One of the key things to understand about "maps" is that you are storing data in images rather than storing pictures in those images. You can open up a height map or other map file and see the image produced by the data, but that's not it's purpose. It's purpose is to store the data.

Once you have the data stored in your image, you can use it with other programs. Or you could create the original map data in another program and import it into your program. For example, there are terrain generating programs that you can get that will generate a height map for you to use with your terrain.

But to use this data, you will need to know how to put it to use. Basically, it's the same process in reverse. You don't have to look at all 3 color values when the image is greyscale. If it's grey, then all 3 colors will have the exact same value. So, you can simply read one color and know that it is the same as if you read all 3. Theoretically, we could store different data in all 3, but then it would not be a greyscale image and we would have to figure out what those color values "mean".

So, for the greyscale height map, you read the image file in and turn it into an array of colors or do the conversion as you read each texel in from the file. The conversion is to read one color, such as red, and get it's value which will be between 0 and 255. You "could" use this as the altitude directly. But you may want to convert those values into a percentage by dividing each of them by the maximum value of 255. Then you could apply that percentage to a specified maximum terrain height range and add a minimum terrain height value to all the values.

And that's pretty much all there is to using a greyscale image as a height map to set the shape of your terrain.

But the reason I did not want to make this specifically about terrain is that there is SO much more you will do with maps like this. In 3D, you can store normals in an image for bump mapping. Without going into this seperate algorithm too deeply, basically you convert the 3D vector normals to a range where X, Y, and Z are all between 0 and +1 (no negatives). Then you store those X, Y, and Z values into red, green, and blue. So Red represents the direction on the X axis (shifted into positive space), and the other colors represent Y and Z in the same way. This is what gives bump maps their distinctive color. The normals stored in the image, again, are not intended to be a picture to look at, but data. The data can be used to calculate lighting and such.

Also, this can apply to 2D programming as well. I've spent a lot of time outlining ways that mapping is commonly used in 3D. But you use arrays all the time in 2D for things like tile maps. So, you could store the values in your tile map array as greyscale values in an image file. Or, if you had arrays that overlay one another for storing background and monsters seperately for example, you could use one color channel to store 256 unique background tile values and another color to store 256 unique monster types, for example. You could load the values stored in the image, back into your game at runtime for different levels of the game and such.

You will see maps of all kinds used everywhere in 3D programming, but you may want to get creative and dream up new ways. And don't forget that they can be used in 2D as well to do things like store array values to a file.

0 Comments On This Entry


Trackbacks for this entry [ Trackback URL ]

There are no Trackbacks for this entry

June 2019

161718 19 202122


    Recent Entries

    Search My Blog

    0 user(s) viewing

    0 Guests
    0 member(s)
    0 anonymous member(s)