D3D中的纹理映射(3)
该例程演示了怎样对一个立方体映射板条纹理。
截图:
vertex.h:
#ifndef __VERTEX_H__
#define __VERTEX_H__
class cTextureVertex
{
public:
float m_x, m_y, m_z;
float m_nx, m_ny, m_nz;
float m_u, m_v; // texture coordinates
cTextureVertex() { }
cTextureVertex(float x, float y, float z,
float nx, float ny, float nz,
float u, float v)
{
m_x = x; m_y = y; m_z = z;
m_nx = nx; m_ny = ny; m_nz = nz;
m_u = u; m_v = v;
}
};
#define TEXTURE_VERTEX_FVF (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
#endif
cube.h:
#ifndef __CUBE_H__
#define __CUBE_H__
#include <d3dx9.h>
class cCube
{
public:
cCube(IDirect3DDevice9* d3d_device);
~cCube();
void draw(const D3DMATRIX* world, const D3DMATERIAL9* material, IDirect3DTexture9* texture);
private:
IDirect3DDevice9* m_d3d_device;
IDirect3DVertexBuffer9* m_vertex_buffer;
IDirect3DIndexBuffer9* m_index_buffer;
};
#endif
cube.cpp:
/****************************************************************************
Provides an interface to create and render a cube.
****************************************************************************/
#include "cube.h"
#include "vertex.h"
cCube::cCube(IDirect3DDevice9* d3d_device)
{
m_d3d_device = d3d_device;
m_d3d_device->CreateVertexBuffer(24 * sizeof(cTextureVertex), D3DUSAGE_WRITEONLY, TEXTURE_VERTEX_FVF,
D3DPOOL_MANAGED, &m_vertex_buffer, NULL);
cTextureVertex* v;
m_vertex_buffer->Lock(0, 0, (void**)&v, 0);
// build box
// fill in the front face vertex data
v[0] = cTextureVertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
v[1] = cTextureVertex(-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
v[2] = cTextureVertex( 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);
v[3] = cTextureVertex( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
// fill in the back face vertex data
v[4] = cTextureVertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
v[5] = cTextureVertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f);
v[6] = cTextureVertex( 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
v[7] = cTextureVertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f);
// fill in the top face vertex data
v[8] = cTextureVertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
v[9] = cTextureVertex(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
v[10] = cTextureVertex( 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);
v[11] = cTextureVertex( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
// fill in the bottom face vertex data
v[12] = cTextureVertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f);
v[13] = cTextureVertex( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f);
v[14] = cTextureVertex( 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f);
v[15] = cTextureVertex(-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
// fill in the left face vertex data
v[16] = cTextureVertex(-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
v[17] = cTextureVertex(-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
v[18] = cTextureVertex(-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
v[19] = cTextureVertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f);
// fill in the right face vertex data
v[20] = cTextureVertex( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
v[21] = cTextureVertex( 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
v[22] = cTextureVertex( 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
v[23] = cTextureVertex( 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f);
m_vertex_buffer->Unlock();
m_d3d_device->CreateIndexBuffer(36 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED,
&m_index_buffer, NULL);
WORD* index_ptr = NULL;
m_index_buffer->Lock(0, 0, (void**)&index_ptr, 0);
// fill in the front face index data
index_ptr[0] = 0; index_ptr[1] = 1; index_ptr[2] = 2;
index_ptr[3] = 0; index_ptr[4] = 2; index_ptr[5] = 3;
// fill in the back face index data
index_ptr[6] = 4; index_ptr[7] = 5; index_ptr[8] = 6;
index_ptr[9] = 4; index_ptr[10] = 6; index_ptr[11] = 7;
// fill in the top face index data
index_ptr[12] = 8; index_ptr[13] = 9; index_ptr[14] = 10;
index_ptr[15] = 8; index_ptr[16] = 10; index_ptr[17] = 11;
// fill in the bottom face index data
index_ptr[18] = 12; index_ptr[19] = 13; index_ptr[20] = 14;
index_ptr[21] = 12; index_ptr[22] = 14; index_ptr[23] = 15;
// fill in the left face index data
index_ptr[24] = 16; index_ptr[25] = 17; index_ptr[26] = 18;
index_ptr[27] = 16; index_ptr[28] = 18; index_ptr[29] = 19;
// fill in the right face index data
index_ptr[30] = 20; index_ptr[31] = 21; index_ptr[32] = 22;
index_ptr[33] = 20; index_ptr[34] = 22; index_ptr[35] = 23;
m_index_buffer->Unlock();
}
cCube::~cCube()
{
if(m_vertex_buffer)
{
m_vertex_buffer->Release();
m_vertex_buffer = NULL;
}
if(m_index_buffer)
{
m_index_buffer->Release();
m_index_buffer = NULL;
}
}
void cCube::draw(const D3DMATRIX* world, const D3DMATERIAL9* material, IDirect3DTexture9* texture)
{
if(world)
m_d3d_device->SetTransform(D3DTS_WORLD, world);
if(material)
m_d3d_device->SetMaterial(material);
if(texture)
m_d3d_device->SetTexture(0, texture);
m_d3d_device->SetStreamSource(0, m_vertex_buffer, 0, sizeof(cTextureVertex));
m_d3d_device->SetIndices(m_index_buffer);
m_d3d_device->SetFVF(TEXTURE_VERTEX_FVF);
m_d3d_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
}
TexCube.cpp:
/**************************************************************************************
Renders a textured cube. Demonstrates creating a texture, setting texture filters,
enabling a texture, and texture coordinates. Use the arrow keys to orbit the scene.
**************************************************************************************/
#include "d3dUtility.h"
#include "cube.h"
#include "vertex.h"
#pragma warning(disable : 4100)
const int WIDTH = 640;
const int HEIGHT = 480;
IDirect3DDevice9* g_d3d_device;
cCube* g_cube;
IDirect3DTexture9* g_d3d_texture;
////////////////////////////////////////////////////////////////////////////////////////////////////
bool setup()
{
g_cube = new cCube(g_d3d_device);
// set a directional light
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(light));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Ambient = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);
light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
light.Specular = D3DXCOLOR(0.2f, 0.2f, 0.2f, 1.0f);
light.Direction = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
// set and enable the light
g_d3d_device->SetLight(0, &light);
g_d3d_device->LightEnable(0, TRUE);
// turn off specular lighting and instruct Direct3D to renormalize normals
g_d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
g_d3d_device->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
D3DXCreateTextureFromFile(g_d3d_device, "crate.jpg", &g_d3d_texture);
// set texture filter states
g_d3d_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
g_d3d_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_d3d_device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
// set the projection matrix
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.5f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
g_d3d_device->SetTransform(D3DTS_PROJECTION, &proj);
return true;
}
void cleanup()
{
safe_delete<cCube*>(g_cube);
safe_release<IDirect3DTexture9*>(g_d3d_texture);
}
bool display(float time_delta)
{
// update the scene: update camera position
static float angle = (3.0f * D3DX_PI) / 2.0f;
static float height = 2.0f;
if(GetAsyncKeyState(VK_LEFT) & 0x8000f)
angle -= 0.5f * time_delta;
if(GetAsyncKeyState(VK_RIGHT) & 0x8000f)
angle += 0.5f * time_delta;
if(GetAsyncKeyState(VK_UP) & 0x8000f)
height += 5.0f * time_delta;
if(GetAsyncKeyState(VK_DOWN) & 0x8000f)
height -= 5.0f * time_delta;
D3DXVECTOR3 position(cosf(angle) * 3.0f, height, sinf(angle) * 3.0f);
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX view_matrix;
D3DXMatrixLookAtLH(&view_matrix, &position, &target, &up);
g_d3d_device->SetTransform(D3DTS_VIEW, &view_matrix);
// draw the scene
g_d3d_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
g_d3d_device->BeginScene();
g_cube->draw(NULL, &WHITE_MATERIAL, g_d3d_texture);
g_d3d_device->EndScene();
g_d3d_device->Present(NULL, NULL, NULL, NULL);
return true;
}
LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
if(word_param == VK_ESCAPE)
DestroyWindow(hwnd);
break;
}
return DefWindowProc(hwnd, msg, word_param, long_param);
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
{
if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_d3d_device))
{
MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
return 0;
}
if(! setup())
{
MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
return 0;
}
enter_msg_loop(display);
cleanup();
g_d3d_device->Release();
return 0;
}