DDraw笔记-高彩模式

 

高彩模式

除了8位的,还有16位、24位、32位等。高于8位的模式都不再采用调色板模式。下面介绍几种编码模式。

16位模式下有几种编码方案

Alpha.5.5.5:这种模式用D15位存储一个Alpha(透明度),其余15位均匀分配给红色5位,绿色5位,蓝色5位。

X5.5.5:与Alpha.5.5.5类似,只是最高位没有使用。

5.6.5这个是16色彩最常用的模式。5位分配给红,6位分配给绿,5位分配给蓝

下面是构造他们的宏:

// this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)

#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))

 

// this builds a 16 bit color value in 5.6.5 format (green dominate mode)

#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))

 

源代码下载

#define INITGUID#include<windows.h>
#include <ddraw.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HWND main_window_handle = NULL;                  // 全局的windows窗口句柄
LPDIRECTDRAW7 lpdd        = NULL;                // ddraw 接口指针
DDSURFACEDESC2 ddsd;                             // ddraw 显示表面 描述结构
LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;       // ddraw 主显示表面
LPDIRECTDRAWSURFACE7  lpddsback    = NULL;       // ddraw 从显示表面

#define SCREEN_WIDTH    640                      // 屏幕宽
#define SCREEN_HEIGHT   480                      // 屏幕高
#define SCREEN_BPP      16                       // 深度

 

#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct, 0, sizeof(ddstruct)); ddstruct.dwSize = sizeof(ddstruct); }
 // this builds a 16 bit color value in 5.6.5 format (green dominate mode)
#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
 // this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
 #define KEYDOWN(vk_code) ((::GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((::GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

 
/*
    每个像素16位,用此函数前先锁住表面。
*/
inline void Plot_Pixel_Faster16(int x, int y, 
                                int red, int green, int blue, 
                                USHORT *video_buffer, int lpitch16)
{
    USHORT pixel = _RGB16BIT565(red,green,blue);
    video_buffer[x + y*lpitch16] = pixel;
}
int Game_Init(void *parms = NULL, int num_parms = 0)
{
    if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
        return 0;

    if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, 
        DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
        return 0;

    if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0, 0)))
        return 0;

    memset(&ddsd,0,sizeof(ddsd)); 
    ddsd.dwSize = sizeof(ddsd);

    ddsd.dwFlags = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

    if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
        return 0;

    // 不需要调色板了
    // 对于像素位深度大于8的页面,不需要使用调色板

    return 1;
}
int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
    if (lpddsprimary)
    {
        lpddsprimary->Release();
        lpddsprimary = NULL;
    }

    if (lpdd)
    {
        lpdd->Release();
        lpdd = NULL;
    }
    return 1;
}
int Game_Main(void *parms = NULL, int num_parms = 0)
{
    if (KEYDOWN(VK_ESCAPE))
        SendMessage(main_window_handle, WM_CLOSE, 0, 0);

    DDRAW_INIT_STRUCT(ddsd); 

    if (FAILED(lpddsprimary->Lock(NULL, &ddsd,
        DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
        NULL)))
        return 0;

    int lpitch16 = (int)(ddsd.lPitch >> 1);
    USHORT *video_buffer = (USHORT *)ddsd.lpSurface;

    for (int index=0; index < 1000; index++)
    {
        int red   = rand() % 256;
        int green = rand() % 256;
        int blue  = rand() % 256;
        int x = rand() % 640;
        int y = rand() % 480;

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

    if (FAILED(lpddsprimary->Unlock(NULL)))
        return 0;

    return 1;
}
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nShowCmd)
{
    HWND hwnd;
    MSG msg;
    TCHAR lpszClassName[] = TEXT("kuan");

    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = ::LoadIcon(NULL,IDI_APPLICATION);
    wc.hCursor = ::LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = lpszClassName;

    RegisterClass(&wc);

    hwnd = CreateWindow(lpszClassName,
        TEXT("fangyukuan"),
        WS_POPUP | WS_VISIBLE,
        0,0,SCREEN_WIDTH,SCREEN_HEIGHT,
        NULL,
        NULL,
        hInstance,
        NULL);
    main_window_handle = hwnd;

    Game_Init();
    while(TRUE)
    {
        if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        { 
            if (msg.message == WM_QUIT)
                break;

            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        Game_Main();

    }
    Game_Shutdown();

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam)
{
    switch(message)
    {
    case WM_LBUTTONDOWN:
        {
            ::MessageBeep(0); 
        }
        break;
    case WM_DESTROY:
        ::PostQuitMessage(0);
        break;
    default:
        return ::DefWindowProc(hwnd,message,wParam,lParam);
    }
    return 0;
}

32位模式下有几种编码方案

Alpha(8).8.8.8:用8位表示透明信息。红色、绿色、蓝色,各有用8位。每个像素都用32位来表示,这是奔腾处理器最快的内存寻址方式。

X(8).8.8:最高8位没有使用。其它的跟Alpha(8).8.8.8一样。

  

下面是构造他们的宏:

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

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

 

源代码下载

#define INITGUID

#include<windows.h>
#include <ddraw.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HWND main_window_handle = NULL;                  // 全局的windows窗口句柄
LPDIRECTDRAW7 lpdd        = NULL;                // ddraw 接口指针
DDSURFACEDESC2 ddsd;                             // ddraw 显示表面 描述结构
LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;       // ddraw 主显示表面
LPDIRECTDRAWSURFACE7  lpddsback    = NULL;       // ddraw 从显示表面

#define SCREEN_WIDTH    640                      // 屏幕宽
#define SCREEN_HEIGHT   480                      // 屏幕高
#define SCREEN_BPP      32                       // 深度
  
  

#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
 // this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
inline void Plot_Pixel_32(int x, int y, 
                          int alpha,int red, int green, int blue, 
                          UINT *video_buffer, int lpitch32)
{
    UINT pixel = _RGB32BIT(alpha,red,green,blue);
    video_buffer[x + y*lpitch32] = pixel;
}
int Game_Init(void *parms = NULL, int num_parms = 0)
{
    if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
        return 0;

    if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, 
        DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
        return 0;

    // set display mode to 640x480x16
    if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0, 0)))
        return 0;

    memset(&ddsd,0,sizeof(ddsd)); 
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

    if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
        return 0;

    // 不需要调色板了
    // 对于像素位深度大于8的页面,不需要使用调色板

    return 1;

}
int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
    // now the primary surface
    if (lpddsprimary)
    {
        lpddsprimary->Release();
        lpddsprimary = NULL;
    }

    // now blow away the IDirectDraw4 interface
    if (lpdd)
    {
        lpdd->Release();
        lpdd = NULL;
    }
    return 1;
}
int Game_Main(void *parms = NULL, int num_parms = 0)
{
    if (KEYDOWN(VK_ESCAPE))
        SendMessage(main_window_handle, WM_CLOSE, 0, 0);

    DDRAW_INIT_STRUCT(ddsd); 

    if (FAILED(lpddsprimary->Lock(NULL, &ddsd,
        DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
        NULL)))
        return 0;

    int lpitch32 = (int)(ddsd.lPitch >> 2);
    UINT *video_buffer = (UINT *)ddsd.lpSurface;

    for (int index=0; index < 1000; index++)
    {
        int red   = rand() % 256;
        int green = rand() % 256;
        int blue  = rand() % 256;
        int x = rand() % 640;
        int y = rand() % 480;

        Plot_Pixel_32(x, y, 0, red, green, blue, video_buffer, lpitch32);       
    }

    if (FAILED(lpddsprimary->Unlock(NULL)))
        return 0;

    return 1;
}
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nShowCmd)
{
    HWND hwnd;
    MSG msg;
    TCHAR lpszClassName[] = TEXT("kuan");

    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = ::LoadIcon(NULL,IDI_APPLICATION);
    wc.hCursor = ::LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = lpszClassName;

    RegisterClass(&wc);

    hwnd = CreateWindow(lpszClassName,
        TEXT("fangyukuan"),
        WS_POPUP | WS_VISIBLE,
        0,0,SCREEN_WIDTH,SCREEN_HEIGHT,
        NULL,
        NULL,
        hInstance,
        NULL);
    main_window_handle = hwnd;

    Game_Init();
    while(TRUE)
    {
        if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        { 
            if (msg.message == WM_QUIT)
                break;

            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        Game_Main();

    }
    Game_Shutdown();

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam)
{
    switch(message)
    {
    case WM_LBUTTONDOWN:
        {
            ::MessageBeep(0); 
        }
        break;
    case WM_DESTROY:
        ::PostQuitMessage(0);
        break;
    default:
        return ::DefWindowProc(hwnd,message,wParam,lParam);
    }
    return 0;
}

获取像素格式

想知道任意表面的像素格式,可以用下面函数获取
IDIRECTDRAWSURFACE7::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat);

对DDPIXELFORMAT结构我们感兴趣的有以下三个:

DWORD dwSize;          // 结构大小
DWORD dwFlags;         // 描述表面的标志,见下表
DWORD dwRGBBitCount;   // RGB的位数

DDPIXELFORMAT. dwFlags的有效标志 

描述

DDPF_ALPHA

像素格式描述一个只有alpha的表面

DDPF_ALPHAPIXELS

画面有alpha信息的像素格式

DDPF_LUMINANCE

像素格式中有单一透明或者透明alpha分量的画面

DDPF_PALETTEINDEXED1

画面是1位色彩索引

DDPF_PALETTEINDEXED2

画面是2位色彩索引

DDPF_PALETTEINDEXED4

画面是4位色彩索引

DDPF_PALETTEINDEXED8

画面是8位色彩索引

DDPF_PALETTEINDEXEDTO8

画面是1位、2位、4位色彩索引到8位调色板

DDPF_RGB

像素格式中的RGB数据有效

DDPF_ZBUFFER

像素格式 描述 一个Z缓冲画面

DDPF_ZPIXELS

画面在像素中含有Z信息

比较重要标志是:

DDPF_PALETTEINDEXED8:说明表面租用 8位调色板模式。

DDPF_RGB:说明表面采用RGB模式,其格式可以通过测试dwRGBBitCount值获得。

DDPIXELFORMAT ddpixel;
LPDIRECTDRAWSURFACE7 lpdds_primary;
memset(&ddpixel, 0, sizeof(ddpixel));
ddpixel.dwSize = sizeof(ddpixel);
lpdds_primary->GetPixelFormat(&ddpixel);
if (ddpixel.dwFlags & DDPF_RGB) 
{   
    switch(ddpixel.dwRGBBitCount)
    {          
    case 15: // must be 5.5.5 mode                  
        break;         
    case 16: // must be 5.6.5 mode          
        break;       
    case 24: // must be 8.8.8 mode     
        break; 
    case 32: // must be alpha(8).8.8.8 mode   
        break;    
    default:
        break;          
    }
}
else if (ddpixel.dwFlags & DDPF_PALETTEINDEXED8)
{    
    // 256 color palettized mode
}
else
{

} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值