Game Development beginner's palette and pixel 1

Source: Internet
Author: User
Introduction

Today, we will use the color palette and RGB mode to familiarize ourselves with the basic graphics of DirectDraw. What are their differences? If you program in DOS, you may have used the color palette ing mode. The color palette is a color query table. To draw pixels, you write a single byte into the video memory. With this byte, You Can index A linked list with various colors, or query a table is called a palette. The RGB mode is different because it does not require color query tables. To create a pixel in RGB mode, you can directly write red, green, and Blue values into the video memory. Any color palette with a color depth higher than 8 digits can be replaced by the RGB mode.

When writing this article, I suppose you have read the previous chapters and learned how to set DirectDraw and create a surface. We will use directx7, which includes the latest DirectDraw interface. In fact, the DirectDraw interface in DirectX 7 may be the last upgraded version! Don't worry, the future version will be compatible with it, but it may be a comprehensive DirectDraw and direct3d product in the future. What we learn will not be useless.

Before you start, I have the last thing to remind you: in my subsequent articles, the section about the color palette may no longer be used, so if you are not very interested in the color palette mode, you can skip the first part of the article and start with the pixel format. The development and use of the color palette is the direct consequence of the memory limit of the original video system used in the PC. Currently, the color palette mode is almost obsolete due to ample memory. One reason it is worth retaining the palette mode is that performing the palette operation can achieve some interesting animation effects. No, let's get started!

  Create a DirectDraw palette

You must create a color palette, that is, a color query table, to display the image in 8-bit or below-8-bit color depth. More specifically, for DirectX, the color palette is the paletteentry structure. To create a palette, follow these three steps:

1. Create a color query linked list.

2. Get the pointer to the idirectdrawpalette interface.

3. link the palette to the DirectDraw surface.

I suppose we use 8-bit color depth. If you want to write a game in depth with 16-bit or higher colors, you don't have to watch the following crazy windows footage. In short, we can have a color palette of 256 entries for 8-bit color depth. Therefore, when you create a color query linked list, there are 256 entries in it:


Typedef struct tagpaletteentry {
// PE
Byte pered;
Byte pegreen;
Byte peblue;
Byte peflags;
} Paletteentry;

The first three parameters are obviously red, green, and blue. Each value ranges from 0 to 255, and the byte is an unsigned data type. The last parameter is the control flag and should be set to pc_nocollapse. I won't talk about the reason.

Now we need to arrange 256 entries in an orderly manner, that is, to find them, we can set an array for the linked list, as shown in the following figure:

Paletteentry palette [256];

OK, we have an array. you can load the color. When I work in the palette mode, I usually store colors in an external file and load colors with the following stuff:

File * file_ptr;
Int X;

If (file_ptr = fopen ("palette. dat", "rb "))! = NULL)
{
Fread (palette, sizeof (paletteentry), 256, file_ptr );
Fclose (file_ptr );
}

All right. The first step is complete. Now we need to get the palette interface. Just give it to the idirectdraw7: createpalette () function:

Hresult createpalette (
DWORD dwflags,
Lppaletteentry lpcolortable,
Lpdirectdrawpalette far * lplpddpalette,
Iunknown far * punkouter
);

The return type is hresult. You know it, so you can use the two macros failed () and succeeded () to check whether the function is successfully called. Parameters are described as follows:

※Dword dwflags: a constant that describes the identifier of a palette object. Of course, you can combine them with "|:

· Ddpcaps_1bit: one color, corresponding to the two-color palette.

· Ddpcaps_2bit: two colors, corresponding to the 4-color palette.

· Ddpcaps_4bit: 4-digit color, corresponding to the 16-color palette.

· Ddpcaps_8bit: 8 is the color, corresponding to the 256 color palette.

· Ddpcaps_8bitentries: indicates that an 8-bit color index is referenced. That is to say, each color entry is its own index to the 8-bit palette on the target surface. This is called the color palette of the address. It must be the same as ddpcaps_1bit, ddpcaps_2bit, or ddpcaps_4bit. A mess! Pai_^

· Ddpcaps_alpha: Each peflags Member of the paletteentry should be considered as an Alpha value. The color palette created with these labels can be pasted on the dierct3d texture surface, because DirectDraw itself does not support alpha mixing.

· Ddpcaps_allow256: Allow all 256 entries in the 8-bit color palette to be used. Generally, 0 points to black, and 255 points to white.

· Ddpcaps_initialize: specifies that the palette should be initialized using the array of paletteentry.

· Ddpcaps_primarysurface: The color palette is linked to the main surface to quickly change the display color.

· Ddpcaps_vsync: it is usually used when the circle is drawn.

In most cases, you will use ddpcaps_8bit | ddpcaps_initialize. If you just want to create an empty color palette and set it later, you can remove the latter, that is, ddpcaps_initialize. Of course, you can also use ddpcaps_allow256, if you really want to change these two commonly used entries.

※Lppaletteentry lpcolortable: This Pointer Points to the query table we created and passes the array name to it.

※Lpdirectdrawpalette far * lplpddpalette: this is the address pointing to the idirectdrawpalette interface pointer. If the function is called successfully, it will be initialized.

※Iunkown far * punkouter: as before, this is always prepared for the com advanced application. Set to null.

Not too bad! Now we can create our palette object. The last step is to link the palette to a surface, which requires only one function-idirectdrawsurface7: setpalette (). Its prototype is as follows:

Hresult setpalette (lpdirectdrawpalette lpddpalette );

It's easy, isn't it? You only need to pass the interface pointer obtained in the previous step to it. Well, Let's combine what we learned. Next I will give you a program framework. I suppose we have created an index linked list using the palette array, just like what we did in the previous step. This frame is used to create a DirectDraw palette to control the color and link it to the main surface (of course, the main surface is prepared in advance ):

Lpdirectdrawpalette lpddpal;
// Create the palette object
If (failed (lpdd7-> createpalette (ddpcaps_8bit | ddpcaps_initialize, palette, & lpddpal, null )))
{
// Error-handling code here
}

// Attach to primary surface
If (failed (lpddsprimary-> setpalette (lpddpal )))
{
// Error-handling code here
}

That's simple. Once your palette is created, it is no different to draw the pixel part in the RGB mode. From this point on, I will introduce both the RGB mode and the color palette mode. Before we actually display the image, I need to tell you what the RGB pixel format is.

  Pixel format

As I mentioned earlier, when you write a pixel in the color palette mode into the memory, you allocate a byte, each representing an index to the color query table. In RGB mode, you only need to write the color description value to the memory, but each color requires more than one byte. The number of bytes is related to the color depth. For a 16-bit color, you need to prepare two bytes (16 bits) for each pixel, and so on, you can guess what the 32-bit color is like, which is easy to understand. 32-bit color for a pixel, each character is as follows:

Aaaa AAAA RRRR GGGG BBBB

"A" indicates "Alpha" (alpha), indicating a transparent value, which is prepared for direct3d. As I have said before, DirectDraw does not support alpha mixing, so when you create a 32-bit color for DirectDraw, set the high position to 0. The next 8 bits represent the red intensity value, the next 8 bits represent the green color, and the last 8 bits represent the blue color.
A 32-bit Color Pixel requires 32 bits, So we generally use the uint type to define the corresponding variable type, which is an unsigned real number type. I usually use a macro to Convert RGB data into a correct pixel format. Let me show you how it looks. I hope this will help you better understand the pixel format:

# Define rgb_32bit (R, G, B) (r <16) | (G <8) | (B ))

As you can see, this macro writes red, green, and blue intensity values at the corresponding position through displacement, and fully complies with the correct pixel format. Is it a bit getting started? To create a 32-bit pixel, you can call this macro. The intensity values of red, green, and blue are 8 bits, and their values range from 0. For example, to create a white pixel, you can:

Uint white_pixel = rgb_32bit (255,255,255 );

The 24-bit color is basically the same, and the truth is actually the same, but the 24-bit does not have a description of α, that is, the 8-bit α is missing. The pixel format is as follows:

Rrrr RRRR GGGG BBBB

Therefore, red, green, and blue are still 8 bits, which means that the 24-bit color and 32-bit color actually have the same color depth, only 32-bit has a combination of α. Now, you must think that 24-bit is better than 32-bit. Is that true? No, because 24-bit has some trouble. In fact, there is no 24-bit data type. When you create a pixel, you have to write red, green, and blue intensity values in three steps, instead of a 32-bit statement. Although 32-bit colors require more memory, it is faster on most machines. In fact, many display cards do not support the 24-bit color mode, because each pixel occupies 3 bytes, which is inconvenient.

Now it's the turn of the 16-bit color. It's a little tricky because for 16-bit colors, not every display card uses the same pixel format! There are two formats. One of them is also quite popular. Red occupies 5 places, green occupies 6 places, and blue occupies the remaining 5 places. The other format occupies five digits, and the remaining one is not used for high positions. Some old display cards use this format. So the two formats look like this:

565 format: RRRR rggg gggb BBBB
555 format: 0rrr rrgg gggb BBBB

When you work in a 16-bit color depth, you must first check whether the display card supports the 565 format or the 555 format, and then use the appropriate method. This is annoying, but you stick to the 16-bit color, which cannot be avoided. Because there are two formats, you need two macros:

# Define rgb_16bit565 (R, G, B) (r <11) | (G <5) | (B ))
# Define rgb_16bit555 (R, G, B) (r <10) | (G <5) | (B ))

For the 565 format, the value range of red and blue is 0--31, and the value range of green is 0--63; For the 555 format, the value range is 0--31. Therefore, when creating a white pixel, it will be different:

Ushort white_pixel_565 = rgb_16bit565 (31, 63, 31 );
Ushort white_pixel_555 = rgb_15bit555 (31, 31, 31 );

This ushort is of the unsigned short real number type, and the corresponding variable is only 16 bits. There are two formats that make things a little complicated, but in actual game programming, you will feel that this is not as annoying as you think. By the way, sometimes the 555 format is called the 15-bit color depth, so if I talk about it like this in the future, you must be considerate!

Now, I may tell you how to check which format the display card supports in the 16-bit color depth mode. Is it 555 or 565? The simplest method is to call the getpixelformat () function under the idirectdrawsurface7 interface. Its prototype is as follows:

Hresult getpixelformat (lpddpixelformat );

The parameter is a pointer to the ddpixelformat structure. You just need to declare it, initialize it, and pass its address. Everything is OK. This structure is huge, so I will not list it, but I have to tell you that all three of its members are of the DWORD type. They are dwrbitmask, dwgbitmask, and dwbbitmask. You can obtain the mask value from dwrbitmask, dwgbitmask, and dwbbitmask ). You can also use them to detect formats supported by the display card. If the display card supports 565, dwgbitmask is 0x07e0. In the 555 format, dwgbitmask is 0x03e0.

Now we have learned all the pixel formats we may use and can enter the actual stage of displaying images under DirectX. You have been waiting for a long time, haven't you? Before placing pixels on the surface, we need to lock the surface, at least part of the locked surface. The lock surface returns a pointer pointing to the surface in the memory, and then we can do whatever we want.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.