本篇是
創建游戲內核(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();
}
運行截圖:
