初学Direct X(5)

初学Direct X(5)


前面学习了使用表面绘制屏幕,但这种方法与另一种比较起来,有着绘图速度颇慢以及缺乏对任何透明类型的支持,这就是前面的篮框以及炸弹会有黑色背景的原因,这种方法就是纹理。他可以绘制出有透明效果的物体,即只显示对象本身的像素而没有背景。

1. 加载带有位图的纹理

应该要让纹理像表面一样有该有的功能,比如将位图加载于纹理上。要做到这个,首先得创建纹理对象,它是LPDIRECT3DTEXTURE9类型:

LPDIRECT3DTEXTURE9 texture = NULL;

接着从位图中将位图加载到纹理中,其接口如下:

D3DXCreateTextureFromFileExA(
    LPDIRECT3DDEVICE9         pDevice,
    LPCSTR                    pSrcFile,
    UINT                      Width,
    UINT                      Height,
    UINT                      MipLevels,
    DWORD                     Usage,
    D3DFORMAT                 Format,
    D3DPOOL                   Pool,
    DWORD                     Filter,
    DWORD                     MipFilter,
    D3DCOLOR                  ColorKey,
    D3DXIMAGE_INFO*           pSrcInfo,
    PALETTEENTRY*             pPalette,
    LPDIRECT3DTEXTURE9*       ppTexture);

可见这里面需要知道位图的大小以及D3DXIMAGE_INFO,这个需要使用D3DXGetImageInfoFromFile提前获取:

D3DXIMAGE_INFO image_info;
HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(),&image_info);

下面是一个调用D3DXCreateTextureFromFileExA示例:

D3DXCreateTextureFromFileEx(
	d3ddev,
	filename.c_str(),
	image_info.Width,
	image_info.Height,
	1,
	D3DPOOL_DEFAULT,
	D3DFMT_UNKNOWN,
	D3DPOOL_DEFAULT,
	D3DX_DEFAULT,
	D3DX_DEFAULT,
	transcolor,
	&image_info,
	NULL,
	&texture
	);

2. 将纹理使用渲染器绘制到屏幕上

2.1 初始化

首先需要定义一个渲染器,其定义是:

LPD3DXSPRITE spriteobj;

接下来要将其初始化,作用是将纹理附着在Direct设备上,以便使得Direct设备知道如何在后台缓冲区绘制纹理,以下是接口的定义:

HRESULT D3DXCreateSprite( 
        LPDIRECT3DDEVICE9   pDevice, 
        LPD3DXSPRITE*       ppSprite);

2.2 绘制前后的操作

在主Direct设备调用BeginScene之后,就可以开始绘制纹理了,但是需要将表面锁住,这仅通过渲染器使用接口即可:

HRESULT Begin (DWORD Flags)

flags是必须的,通常是D3DXSPRITE_ALPHABLEND;当然在绘制完后需要对表面解锁,以便其他进程使用:

HRESULT End (VOID)

2.3 绘制

十分简单,渲染器,即LPD3DXSPRITE,仅需要使用单一的函数Draw来处理所有的变换,通过它可以执行透明,缩放,以及旋转,以下是这个函数的定义:

HRESULT Draw(
  [in]       LPDIRECT3DTEXTURE9 pTexture,
  [in] const RECT               *pSrcRect,
  [in] const D3DXVECTOR3        *pCenter, // 旋转发生的中间点
  [in] const D3DXVECTOR3        *pPosition, // 指定纹理的位置
  [in]       D3DCOLOR           Color 
  );

这里还有一个D3DXVECTOR3类型,它是:

typedef struct D3DXVECTOR3 {
  FLOAT x;
  FLOAT y;
  FLOAT z;
} D3DXVECTOR3, *LPD3DXVECTOR3;

color:可以是[0xFFFFFFFF - 0x00FFFFFF]:从不透明到透明,可以使用D3DCOLOR_RGBA来生成,一般设置为D3DCOLOR_XRGB(255, 255, 255),即为不透明

3. 运行一个例子看看

3.1 绘制无alpha通道位图,无选择ColorKey

生成图1之前,有几件事需要知道:

1)在加载位图到纹理时,将ColorKey设置为D3DCOLOR_XRGB(0, 0, 0),也就是黑色

2)背景色被清空为绿色

3)原始位图是24位图像,并不包含alpha通道

图1
图1

从结果可以看出,在对其进行绘制时,会对其ColorKey标定的颜色进行背景色填充,似乎也达到了透明的效果:)

3.2 绘制无alpha通道位图,有选择ColorKey

生成图2之前,也有几件事需要知道:

1)在加载位图到纹理时,将ColorKey设置为D3DCOLOR_XRGB(255,0,255),也就是粉色

2)背景色被清空为绿色

3)原始位图是24位图像,不包含alpha通道

图2
图2

从结果可以看出,这幅图似乎是我们想要的透明图(原图的背景色就是粉色,和图1处理的原图一样),这里可以看出ColorKey这个变量的意思了,它可以使其所在区域显示背景色,达到透明效果。

3.3 绘制alpha通道位图,有/无选择ColorKey

生成图3之前,也有几件事需要知道:

1)在加载位图到纹理时,将ColorKey设置为D3DCOLOR_XRGB(0,0,0),与图1一样的处理

2)背景色被清空为绿色

3)原始位图是32位图像,包含alpha通道

图3
图3

从结果可以看出,似乎绘制的效果不太好,但是它反应出了这几点信息,第一:如果在加载纹理时设置了有效的ColorKeyDraw将毫不留情的将其透明,这导致了显示结果中的飞机头部以及边缘部分是背景颜色;第二:由于飞机背景在alpha通道中被设置为了透明,故在Draw的绘制下,将其透明,这一点合情合理。综上分析,可以看出,在面对带有alpha通道的位图时,Draw在绘制原本就该透明的像素时,也不会忘记处理ColorKey的区域

原文地址:https://www.cnblogs.com/leihui/p/8922307.html