本篇是
创建游戏内核(8)的续篇,其中涉及到的纹理知识请参阅
D3D
中的纹理贴图(1)。
图像和TEXTURE
纹理使3D看起来更货真价实,使用全彩色成像可以使简单的多边形显得逼真,尝试保存一个纹理列表是一个不错的选择,但有了TEXTURE的帮助,就能使问题变得更容易。
来看看TEXTURE的定义:
class TEXTURE
{
protected:
GRAPHICS* _graphics; // pointer to GRAPHICS object
IDirect3DTexture9* _texture; // pointer to texture object
unsigned long _width, _height; // dimensions of texture image
public:
TEXTURE();
~TEXTURE();
IDirect3DTexture9* Get_Texture_COM();
BOOL Load(GRAPHICS* graphics, char* filename, DWORD transparent = 0, D3DFORMAT format = D3DFMT_UNKNOWN);
BOOL Create(GRAPHICS* graphics, DWORD width, DWORD height, D3DFORMAT format);
BOOL Create(GRAPHICS* graphics, IDirect3DTexture9* texture);
void Free();
BOOL Is_Loaded();
long Get_Width();
long Get_Height();
D3DFORMAT Get_Format();
BOOL Blit(long dest_x, long dest_y,
long src_x = 0, long src_y = 0,
long width = 0, long height = 0,
float x_scale = 1.0f, float y_scale = 1.0f,
D3DCOLOR color = 0xFFFFFFFF);
};
接着来看看TEXTURE类的实现:
//---------------------------------------------------------------------------
// Constructor, initialize data member.
//---------------------------------------------------------------------------
TEXTURE::TEXTURE()
{
_graphics = NULL;
_texture = NULL;
_width = _height = 0;
}
//-------------------------------------------------------------------
// Destructor, free Direct3D COM object.
//-------------------------------------------------------------------
TEXTURE::~TEXTURE()
{
Free();
}
//-------------------------------------------------------------------
// Create texture object from specified file, you can specify transparent
// value and pixel format of the texture.
//-------------------------------------------------------------------
BOOL TEXTURE::Load(GRAPHICS* graphics, char* filename, DWORD transparent, D3DFORMAT format)
{
// Free Direct3D COM object
Free();
// Check if condition is sufficient.
if((_graphics = graphics) == NULL)
return FALSE;
if(graphics->Get_Device_COM() == NULL)
return FALSE;
if(filename == NULL)
return FALSE;
// Creates a texture from a file
if(FAILED(D3DXCreateTextureFromFileEx(graphics->Get_Device_COM(), filename, D3DX_DEFAULT, D3DX_DEFAULT,
D3DX_DEFAULT, 0, format, D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE, D3DX_FILTER_TRIANGLE,
transparent, NULL, NULL, &_texture)))
{
return FALSE;
}
_width = Get_Width();
_height = Get_Height();
return TRUE;
}
//-------------------------------------------------------------------
// Creates a texture resource.
//-------------------------------------------------------------------
BOOL TEXTURE::Create(GRAPHICS* graphics, DWORD width, DWORD height, D3DFORMAT format)
{
Free();
if((_graphics = graphics) == NULL)
return FALSE;
if(FAILED(_graphics->Get_Device_COM()->CreateTexture(width, height, 0, 0, format, D3DPOOL_MANAGED, &_texture, NULL)))
return FALSE;
return TRUE;
}
//-------------------------------------------------------------------
// Configure a TEXTURE class from an existing IDirect3DTexture9 object
// instance.
//-------------------------------------------------------------------
BOOL TEXTURE::Create(GRAPHICS* graphics, IDirect3DTexture9* texture)
{
D3DLOCKED_RECT src_rect, dest_rect;
D3DSURFACE_DESC surface_desc;
Free();
_graphics = graphics;
// check condition
if(_graphics == NULL || texture == NULL)
return FALSE;
// copy texture over, from source to dest.
texture->GetLevelDesc(0, &surface_desc);
_width = surface_desc.Width;
_height = surface_desc.Height;
_graphics->Get_Device_COM()->CreateTexture(_width, _height, 0, 0, surface_desc.Format, D3DPOOL_MANAGED,
&_texture, NULL);
// Locks a rectangle on a texture resource.
texture->LockRect(0, &src_rect, NULL, D3DLOCK_READONLY);
_texture->LockRect(0, &dest_rect, NULL, 0);
memcpy(dest_rect.pBits, src_rect.pBits, src_rect.Pitch * _height);
// unlocks a rectangle on a texture resource
_texture->UnlockRect(0);
texture->UnlockRect(0);
return TRUE;
}
//-------------------------------------------------------------------
// Free Direct3D COM object.
//-------------------------------------------------------------------
void TEXTURE::Free()
{
Release_COM(_texture);
_graphics = NULL;
_width = _height = 0;
}
//-------------------------------------------------------------------
// Check if loaded texture successfully.
//-------------------------------------------------------------------
BOOL TEXTURE::Is_Loaded()
{
return (_texture != NULL);
}
//-------------------------------------------------------------------
// Get texture component.
//-------------------------------------------------------------------
IDirect3DTexture9* TEXTURE::Get_Texture_COM()
{
return _texture;
}
//-------------------------------------------------------------------
// Get width of the texture.
//-------------------------------------------------------------------
long TEXTURE::Get_Width()
{
D3DSURFACE_DESC surface_desc;
if(_texture == NULL)
return 0;
if(FAILED(_texture->GetLevelDesc(0, &surface_desc)))
return 0;
return surface_desc.Width;
}
//-------------------------------------------------------------------
// Get height of the texture.
//-------------------------------------------------------------------
long TEXTURE::Get_Height()
{
D3DSURFACE_DESC surface_desc;
if(_texture == NULL)
return 0;
if(FAILED(_texture->GetLevelDesc(0, &surface_desc)))
return 0;
return surface_desc.Height;
}
//-------------------------------------------------------------------
// Get texture storage format.
//-------------------------------------------------------------------
D3DFORMAT TEXTURE::Get_Format()
{
D3DSURFACE_DESC surface_desc;
if(_texture == NULL)
return D3DFMT_UNKNOWN;
if(FAILED(_texture->GetLevelDesc(0, &surface_desc)))
return D3DFMT_UNKNOWN;
return surface_desc.Format;
}
//-------------------------------------------------------------------
// Draw a 2-D portion of texture to device.
//-------------------------------------------------------------------
BOOL TEXTURE::Blit(long dest_x, long dest_y,
long src_x, long src_y,
long width, long height,
float x_scale, float y_scale,
D3DCOLOR color)
{
RECT rect;
ID3DXSprite* sprite;
// check condition
if(_texture == NULL || _graphics == NULL)
return FALSE;
if((sprite = _graphics->Get_Sprite_COM()) == NULL)
return FALSE;
// If no specify width and height, set with member width and height.
if(width == 0)
width = _width;
if(height == 0)
height = _height;
// set the portion of the source texture to use for the sprite will to be drawed
rect.left = src_x;
rect.top = src_y;
rect.right = rect.left + width;
rect.bottom = rect.top + height;
D3DXMATRIX transform_matrix(x_scale, 0, 0, 0,
0, y_scale, 0, 0,
0, 0, 0, 0,
(float)dest_x, (float)dest_y, 0, 0);
// Sets the sprite transform
sprite->SetTransform(&transform_matrix);
// Adds a sprite to the list of batched sprites.
if(FAILED(sprite->Draw(_texture, &rect, NULL, NULL, color)))
return FALSE;
return TRUE;
}
TEXTURE类能够从磁盘上的一幅图像文件或一个现有的IDirect3DTexture9对象加载纹理。从磁盘加载一幅图像,需要调用
TEXTURE::Load函数。此函数需要几个参数才能起作用,第一个参数是预初始化的GRAPHICS对象,第二个参数是要加载的图像的文件名。
TEXTURE::
Load还带有两个可选参数,分别是透明关键色(如果使用带有透明像素的纹理,就要使用此参数)和存储格式。transparent参数的缺省值为0,意味着Load函数不使用透明像素,如果要使用透明像素,可以给这个参数指定一个
D3DCOLOR_RGBA值(确保给alpha参数指定255)。
对于format参数,要使用诸如
D3DFMT_A1R5G5B5之类的Direct3D纹理存储格式,记住带有透明像素的纹理必须使用alpha通道,因此要确保使用诸如
D3DFMT_A1R5G5B5或D3DFMT_A8R8G8B8的格式。
下面给出测试代码:
点击下载源码和工程
/*****************************************************************************
PURPOSE:
Test for class TEXTURE.
*****************************************************************************/
#include "Core_Global.h"
#pragma warning(disable : 4996)
//===========================================================================
// Defines class APP which public inherits from class APPLICATION.
//===========================================================================
class APP : public APPLICATION
{
private:
GRAPHICS _graphics;
TEXTURE _texture;
VERTEX_BUFFER _vertex_buffer;
// The 3D vertex format and descriptor
typedef struct
{
float x, y, z; // 3D coordinates
float u, v; // texture coordinates
} VERTEX;
#define VERTEX_FVF (D3DFVF_XYZ | D3DFVF_TEX1)
public:
BOOL Init();
BOOL Shutdown();
BOOL Frame();
};
//-----------------------------------------------------------------------------
// Initialize graphics, set display mode, set vertex buffer, load texture file.
//-----------------------------------------------------------------------------
BOOL APP::Init()
{
D3DXMATRIX mat_view;
// initialize vertex data
VERTEX verts[] = {
{ -100.0f, 100.0f, 0.0f, 0.0f, 0.0f },
{ 100.0f, 100.0f, 0.0f, 1.0f, 0.0f },
{ -100.0f, -100.0f, 0.0f, 0.0f, 1.0f },
{ 100.0f, -100.0f, 0.0f, 1.0f, 1.0f }
};
// initialize graphics
if (! _graphics.Init())
return FALSE;
// set display mode for graphics
if(! _graphics.Set_Mode(Get_Hwnd(), TRUE, TRUE, 400, 400, 32))
return FALSE;
// disable D3D lighting
_graphics.Enable_Lighting(FALSE);
// enable z-buffer
_graphics.Enable_ZBuffer(TRUE);
// set perspective projection transform matrix.
_graphics.Set_Perspective(D3DX_PI/4.0f, 1.33333f, 1.0f, 1000.0f);
// create and set the view matrix
D3DXMatrixLookAtLH(&mat_view,
&D3DXVECTOR3(0.0, 0.0, -500.0),
&D3DXVECTOR3(0.0f, 0.0f, 0.0f),
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));
_graphics.Get_Device_COM()->SetTransform(D3DTS_VIEW, &mat_view);
// create the vertex buffer
_vertex_buffer.Create(&_graphics, 8, sizeof(VERTEX), VERTEX_FVF);
// Copy vertex data from VertexList to vertex buffer.
_vertex_buffer.Set(0, 4, verts);
// Create texture object from specified file,
_texture.Load(&_graphics, "texture.jpg");
return TRUE;
}
//-----------------------------------------------------------------------------
// Release all d3d resource.
//-----------------------------------------------------------------------------
BOOL APP::Shutdown()
{
// Free vertex buffer resource, reset data member.
_vertex_buffer.Free();
// free texture resouece
_texture.Free();
// free graphics resouece
_graphics.Shutdown();
return TRUE;
}
//-----------------------------------------------------------------------------
// Render a frame.
//-----------------------------------------------------------------------------
BOOL APP::Frame()
{
D3DXMATRIX mat_world;
// clear display with specified color
_graphics.Clear(D3DCOLOR_RGBA(0, 0, 0, 255), 1.0);
// begin scene
if(_graphics.Begin_Scene())
{
// create and set the world transformation matrix
// rotate object along z-axis
D3DXMatrixRotationZ(&mat_world, (float) (timeGetTime() / 1000.0));
_graphics.Get_Device_COM()->SetTransform(D3DTS_WORLD, &mat_world);
// assigns a texture to a stage for a device
_graphics.Set_Texture(0, &_texture);
// Render vertex buffer into display.
_vertex_buffer.Render(0, 2, D3DPT_TRIANGLESTRIP);
// release texture
_graphics.Get_Device_COM()->SetTexture(0, NULL);
// end the scene
_graphics.End_Scene();
}
// display video buffer
_graphics.Display();
return TRUE;
}
int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
APP app;
return app.Run();
}
运行截图: