Tricks of the Windows Game Programming Gurus:Advanced DirectDraw and Bitmapped Graphics

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

For an example of using the 16-bit modes to write pixels to the screen, take a look at `DEMO7_1.CPP|EXE` on the CD. The program basically implements what you’ve done here and blasts random pixels to the screen. Take a look at the code and note that you don’t need a palette anymore, which is kind of nice <BG>. By the way, the code is in the standard T3D Game Engine template, so the only things you need to really look at are `Game_Init()` and `Game_Main()`. The contents of `Game_Main()` are shown here:

    int Game_Main(void *parms = NULL, int num_parms = 0)

    {

    // this is the main loop of the game, do all your processing

    // here

    // for now test if user is hitting ESC and send WM_CLOSE

    if (KEYDOWN(VK_ESCAPE))

       SendMessage(main_window_handle,WM_CLOSE,0,0);

    // plot 1000 random pixels to the primary surface and return

    // clear ddsd and set size, never assume it’s clean

    DDRAW_INIT_STRUCT(ddsd);

    // lock the primary surface

    if (FAILED(lpddsprimary->Lock(NULL, &ddsd,

                       DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,

                       NULL)))

       return(0);

    // now ddsd.lPitch is valid and so is ddsd.lpSurface

    // make a couple aliases to make code cleaner, so we don’t

    // have to cast

    int lpitch16 = (int)(ddsd.lPitch >> 1);

    USHORT *video_buffer = (USHORT *)ddsd.lpSurface;

    // plot 1000 random pixels with random colors on the

    // primary surface, they will be instantly visible

    for (int index=0; index < 1000; index++)

        {

        // select random position and color for 640x480x16

        int red   = rand()%256;

        int green = rand()%256;

        int blue  = rand()%256;

        int x = rand()%640;

        int y = rand()%480;

        // plot the pixel

        Plot_Pixel_Faster16(x,y,red,green,blue,video_buffer,lpitch16);

        } // end for index

    // now unlock the primary surface

    if (FAILED(lpddsprimary->Unlock(NULL)))

       return(0);

    // return success or failure or your own return code here

    return(1);

    } // end Game_Main

#### 24/32-Bit High-Color Mode

Once you’ve mastered 16-bit mode, 24-bit and 32-bit modes are trivial. I’ll begin with 24-bit mode because it’s simpler than 32-bit mode—which is not a surprise! 24-bit mode uses exactly one byte per channel of RGB blue. Thus, there’s no loss and a total of 256 shades per channel, giving a total possible number of colors of 256×256×256 = 16.7 million. The bits for red, green, and blue are encoded just as they were in 16-bit mode, except that you don’t have to worry about one channel using more bits than another.

Because there’s one byte per channel and three channels, there are three bytes per pixel. This makes for really ugly addressing, as shown in Figure 7.5. Alas, writing pixels in pure 24-bit mode is rather contrived, as shown in the following 24-bit version of the pixel-writing function:

    inline void Plot_Pixel_24(int x, int y,

                              int red, int green, int blue,

                              UCHAR *video_buffer, int lpitch)

    {

    // this function plots a pixel in 24-bit color mode

    // assuming that the caller already locked the surface

    // and is sending a pointer and byte pitch to it

    // in byte or 8-bit math the proper address is: 3*x + y*lpitch

    // this is the address of the low order byte which is the Blue channel

    // since the data is in RGB order

    DWORD pixel_addr = (x+x+x) + y*lpitch;

    // write the data, first blue

    video_buffer[pixel_addr]   = blue;

    // now red

    video_buffer[pixel_addr+1] = green;

    // finally green

    video_buffer[pixel_addr+2] = red;

    } // end Plot_Pixel_24

Figure 7.5 Three-byte RGB addressing is ugly.

The function takes as parameters the x,y, along with the RGB color, and finally the video buffer starting address and the memory pitch in bytes. There’s no point in sending the memory pitch or the video buffer in some `WORD` length because there isn’t any data type that’s three bytes long. Hence, the function basically starts addressing the video buffer at the requested pixel location and then writes the blue, green, and red bits for the pixel.

For an example of 24-bit mode, take a look at `DEMO7_2.CPP|EXE` on the CD. It basically mimics the functionality of `DEMO7_1.CPP`, but in 24-bit mode.

> Warning: Many video cards don’t support 24-bit color mode. They support only 32-bit color, which is usually 8 bits of alpha transparency and then 24 bits of color. This is due to addressing constraints. So `DEMO7_2.EXE` may not work on your system.

Moving on to 32-bit color, the pixel setup is a little different, as shown in Figure 7.6. In 32-bit mode, the pixel data is arranged in the following two formats:

Alpha(8).8.8.8—This format uses eight bits for alpha or transparency information (or sometimes other information) and then eight bits for each channel: red, green, and blue. However, where simple bitmapping is concerned, you can usually disregard the alpha information and simply write eights to it. The nice thing about this mode is that it’s 32 bits per pixel, which is the fastest possible memory addressing mode for a Pentium.

X(8).8.8.8—Similar to the preceding mode, except in this mode the upper eight bits of the color `WORD` are “don’t care’s” or irrelevant. However, I still suggest setting them to zeroes to be safe. You may say, “This mode seems like a 24-bit mode, so why have it?” The answer is that many video cards can’t address on three-byte boundaries, so the fourth byte is just for alignment.

Figure 7.6 32-bit RGB pixel encodings.

Now, take a look at a macro to create a 32-bit color `WORD`:

    // this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)

    #define _RGB32BIT(a,r,g,b) ( + ((g) << 8) + ((r) << 16) + ( << 24))

Then all you need to do is change your pixel-plotting function to use the new macro and take advantage of the four-byte-per-pixel data size. Here it is:

    inline void Plot_Pixel_32(int x, int y,

                              int alpha,int red, int green, int blue,

                              UINT *video_buffer, int lpitch32)

    {

    // this function plots a pixel in 32-bit color mode

    // assuming that the caller already locked the surface

    // and is sending a pointer and DWORD aligned pitch to it

    // first build up color WORD

    UINT pixel = _RGB32BIT(alpha,red,green,blue);

    // write the data

    video_buffer[x + y*lpitch32] = pixel;

    } // end Plot_Pixel_32

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.