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))

 2011052214314932.png

源代码下载

// ------------------------------------------------------------------------- 
// 文件名 : 7_1.cpp
// 创建者 : 方煜宽
// 邮箱 : fangyukuan@gmail.com
// 创建时间 : 2010-12-9 0:52
// 功能描述 : 16位模式,RGB565
// 对于像素位深度大于8的页面,不需要使用调色板
// -------------------------------------------------------------------------
#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))

 2011052214322772.png

源代码下载

// ------------------------------------------------------------------------- 
// 文件名 : 7_3.cpp
// 创建者 : 方煜宽
// 邮箱 : fangyukuan@gmail.com
// 创建时间 : 2010-12-11 22:05
// 功能描述 : 32位真彩模式
//
// -------------------------------------------------------------------------
#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
{

}
 
 

2011.05.22

转载请保留下面链接

标题 http://www.cnblogs.com/fangyukuan/archive/2011/05/22/2053556.html

转载于:https://www.cnblogs.com/fangyukuan/archive/2011/05/22/2053556.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值