Colors and Computers

[ LiB ]

Colors and Computers

Throughout history, people have always tried to use physical media to express what they see and experience. It started with ancient humans drawing on walls, pyramids , and caves. It continued with hand drawings, paintings, pictures, projectors, televisions , and the VGA card. We have come a long way toward simulating what we see, and the creation of new 3D hardware will take us to new heights. Moving beyond older media, three-dimensional games take us away from our physical world, sucking us in as if we're the actors in these virtual stories. The VGA card and the computer monitor work hand in hand, whereby one sends data and the other receives the data and draws the image. This is how the computer monitor operates.

The visual image that appears on the monitor is broken down into pixels. The pixels change color based on the directive from the VGA card. A computer monitor is just a two-dimensional picture with many colors that can change images very fast. That's all it is; just think of it as a very fast-changing picture. The first monitors were black and white; then in a few years colors were incorporated. Today, most monitors refresh images at around 60 hertz, with high resolutions and millions of colors. Figure 2.3 shows one pixel of a monitor represented either as 32 bit or 24 bit. If you change enough pixels to specific colors, you can generate a very detailed image. It can be a picture of your loved one, your pet, your Mustang, or a beautiful landscape.

Figure 2.3. 32-bit mode includes an alpha channel.

graphic/02fig03.gif


NOTE

NOTE

The flickering image on a monitor is evidence of a low number of hertz.The illusion of real-time animation begins at 30 or more hertz.

What you want to do is to control what appears on the monitor by placing your own data on the video card's memory. In order to do this, you need to change each pixel in video memory to your own specified value.

Most video cards today run in 32-bit graphics mode. This is 32 bits, or 4 bytes, per pixel (8 bits for each color channel; red, green, and blue, and 8 bits for alpha or transparency). Why? Well, 24 bits of color can select one of 16.7 million colors, and this is more than enough to cover most of the color space range of any human being. Additionally, graphics cards and video monitors create the display using combinations of red, green, and blue phosphors (picture elements that give off light when excited), so there is a 1:1 correspondence between the pixel value and the image displayed on the screen. Finally, red, green, and blue can be used to create any color because they are the additive primary colors (recall that any color can be created as a sum of red, green, and blue).

Enter the Data Buffer

To create an image on the screen, you change specific pixel colors in the 2D matrix that represents the screen display (video buffer). The alpha portion of the 32-bit pixel is used to make the pixel transparent to some degree. For example, if you had two overlapped rectangles, the first rectangle pixels could be transparent so that the second rectangle is seen. With 32 bits per pixel, the computer has enough information to change a pixel's color to one of 16.7 million variations as mentioned. Figure 2.4 shows how this data is stored in the computer.

Figure 2.4. The data buffer stores the color information of an object in the computer.

graphic/02fig04.gif


During the course of this book, you'll develop a 3D rendering environment in order to incorporate your 3D algorithms. What you'll initially need is an image buffer so that when you create your 3D images they are projected on the 2D monitor. This means you need an image buffer to store your projected 3D images.

Projected image data can be stored as a file or in video memory directly, which causes it to appear on the computer monitor. If you save or output to a file, you can use some type of program to read and copy the RGB data buffer into video memory for viewing. The data buffer is just a two-dimensional array of bytes grouped together in red, green, and blue (RGB) data chunks .

You write to the RGB data buffer using this common algorithm:

 for(height=0; height< MY_OUTPUT_HEIGHT; height++)     for(width=0; width< MY_OUTPUT_WIDTH; width++)        pBuffer[MY_OUTPUT_WIDTH * height + width] = myColor; 

Copying chunks of data on the fly using this simple algorithm can be a slow process, especially when the image resolution is high. One method for optimizing the speed of copying data to an image buffer is to reduce the amount of memory that is copied . The best method is to reduce the memory for each pixel by converting the 32-bit pixel to 24 bits, 16 bits, or 15 bits.

NOTE

NOTE

Copying data into video memory and projecting a 3D image using software memory buffers is known as software rasterization.

Removing the Alpha Component

Today, most images that are rendered on the monitor are opaque without any transparency. The alpha component makes an image transparent to some degree as previously mentioned. Windows XP uses the alpha component in pixels for windows , controls, effects, and so on. But you really don't need it in this book. Today, programmers omit the alpha component and just use 24 bits for their image output. They do this because red (8 bits) plus green (8 bits) plus blue (8 bits) plus alpha (8 bits) combined is really a waste of memory.

With 24 bits (32 - 8 = 24) per pixel, you can create realistic images because of the large number of available colors. A range from 0 to 255 is set for each color component. That's 256 shades for each component, making 256 (red) times 256 (green) times 256 (blue), which equals 16.7 million colors.

Anything that falls outside the range of 0-255 is normally ignored. Table 2.1 shows an example of color mixing.

Table 2.1. RGB Color Mixing

Output Color

Input Color Mixtures

White

Red (255) + Green(255) + Blue(255)

Black

Red (0) + Green(0) + Blue(0)

Gray

Red (128) + Green(128) + Blue(128)

Red

Red (255) + Green(0) + Blue(0)

Green

Red (0) + Green(255) + Blue(0)

Blue

Red (0) + Green(0) + Blue(255)

Yellow

Red (255) + Green(255) + Blue(0)

Aqua

Red (0) + Green(255) + Blue(255)


The alpha component for pixels is natively used in a few file formats such as Truevision Targa TGA and Photoshop PSD but is nonexistent in popular formats such as BMP, TIF, and JPG. It can be used extensively utilized in 3D graphics. It also has some uses in 2D graphics and digital video editing. Many times you can use it in DirectX to create masks to filter out specific colors on surfaces. However, you won't use the alpha component of pixels in any of the applications in this book.

Converting Colors

Sometimes programmers don't want their output images to be 32-bit, so they down-sample them to a lower number of bits16-bit for example is common. 16-bit mode eliminates the highest bits of each 8-bit component and scales the component down to maybe 5 or 6 bits. Many programmers use red (5 bits), green (6 bits), and blue (5 bits) to fill up each 16-bit pixel. The good thing about this is that sometimes your application's performance will improve. The bad thing is that it only has 65,536 possible colors to choose from. It doesn't matter, because our eyes can't really differentiate that closely between colors anyway. The only time we find differences is when colors are clustered up next to each other.

Here are a few macros you can add to your application to build 15-bit, 16-bit, and 32-bit pixels from individual red, green, and blue values:

 // for r5.g5.b5 = 15 bit #define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10)) // for r5.g6.b5 = 16 bit #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11)) // for a8.r8.g8.b8 = 32 bit #define _RGB32BIT(a,r,g,b)  ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24)) 

NOTE

TIP

Some programmers add the extra bit for green in 16-bit modes because our eyes are more sensitive to green.This is because the cone cells responsible for color vision in the green range overlap the higher and lower frequency ranges.They are called M-class cones.

Unit Component

In most of the mathematical operations in this book, you'll be using vector mathematics (a vector in this case is a 2D or 3D quantity that represents a point in 2D or 3D space). In your work, for some equations to work properly, you must normalize any vector and color components before you perform operations with them. To normalize a vector, you must compute its length and then divide each component of the vector by this length value. This has the effect of forcing the length of the vector itself to 1.0.

For example, you'll need to scale your color components down to a range of 0.0 to 1.0 to perform calculations. Once you're done with your math, you'll convert the components back to their original values in a range of 0-255. It's not really a problem to convert numbers to a very small amount; just think of it as a different way of storing them.

The following code will help you understand how to normalize colors. It uses the float data type to hold the color components.

To normalize the color:

 float color, scale      // some data color = gray ;          // make it gray (128) scale = (color / 255);  // you get 0.50196078431372549019607843137255 

To return to the original:

 scale *= 255;          // 0.5 * 255 = 128; 

NOTE

NOTE

Although I'm doing the comparison with a floating-point number with only one number for gray,in a 24-bit color space,gray is actually composed of red,green,and blue components,all equaling 128.I con duct the test with only one component to simplify the process,but this is technically incorrect.To actually conduct color testing on each R,G,and B component,you must also test for the gray comparison.

Using an Epsilon

Integers are very simple when it comes to testing for one-to-one comparison. This is because integers are all whole numbers.

For example, look at the following:

 int White = 255; If (255  == White)     Get_My_Mojo(); // called!! 

But if you were to do this with floating-point numbers it wouldn't be so simple. For example:

 float Gray   = 0.500; If (0.501 == Gray)     Get_My_Mojo(); // not called!! 

This is because floating-point numbers must be exactly the same (whole number part and decimal part) when testing for equality. The difference past the precision to a certain degree can be filtered out in order to have a successful result.

You need to worry about this because your red, green, and blue components will be defined in a range of 0.0 to 1.0. If you want to test whether 0.500 (gray) is equal to 0.501 (mostly gray too), you must filter out certain numbers past the precision.

The problem with floating-point numbers is their imprecision, so you must create averages. This requires an epsilon, which is equal to 0.001. You'll use the epsilon to determine whether two floating-point numbers are close enough to be equal, for all practical purposes.

By performing a simple subtraction, finding the absolute value of the difference, and testing with an arithmetic comparison, you can determine whether two floating-point numbers are equal:

 (fabs(float2  float1) < EPSILON) is equal 

[ LiB ]


Focus On Photon Mapping
Focus On Photon Mapping (Premier Press Game Development)
ISBN: 1592000088
EAN: 2147483647
Year: 2005
Pages: 128
Authors: Marlon John

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net