【游戏程序设计】Direct 3D纹理过滤与寻址
运行结果:
首先我们对DirectInput进行封装便于我们以后的使用。
DirectInputClass.h
//=============================================================================
//封装了DirectInput键盘输入处理类的头文件
//=============================================================================
#pragma once
#include <dinput.h>
#include "D3DUtil.h"
//DirectInputClass类定义开始
class DirectInputClass
{
private:
LPDIRECTINPUT8 m_pDirectInput; //IDirectInput8接口对象
LPDIRECTINPUTDEVICE8 m_MouseDevice; //鼠标设备接口对象
DIMOUSESTATE m_MouseState; //用于鼠标键值存储的一个结构
LPDIRECTINPUTDEVICE8 m_KeyboardDevice; //键盘设备接口对象
char m_KeyboardBuffer[256]; //用于键盘键值存储的数组
public:
//初始化DirectInput键盘及鼠标输入设备
HRESULT Init(HWND hWnd, HINSTANCE hInstance, DWORD keyboardCoopFlags, DWORD mouseCoopFlags);
void GetInput(); //用于获取设备信息的函数
bool IsKeyDown(int iKey); //判断键盘上某键是否按下
bool IsMouseButtonDown(int button); //判断鼠标按键是否被按下
float MouseDX(); //返回鼠标的X轴坐标值
float MouseDY(); //返回鼠标的Y轴坐标值
float MouseDZ(); //返回鼠标的Z轴坐标值
DirectInputClass(void); //构造函数
~DirectInputClass(void); //析构函数
};
DirectInputClass.cpp
//=============================================================================
//封装了DirectInput鼠标键盘输入处理类的源文件
//=============================================================================
#include "DirectInputClass.h"
//-----------------------------------------------------------------------------
//构造函数
//-----------------------------------------------------------------------------
DirectInputClass::DirectInputClass(void)
{
m_pDirectInput = NULL;
m_KeyboardDevice = NULL;
m_MouseDevice= NULL;
ZeroMemory(m_KeyboardBuffer,sizeof(char)*256);
ZeroMemory(&m_MouseState, sizeof(m_MouseState));
}
//-----------------------------------------------------------------------------
//初始化DirectInput键盘及鼠标输入设备
//-----------------------------------------------------------------------------
HRESULT DirectInputClass::Init(HWND hWnd, HINSTANCE hInstance, DWORD keyboardCoopFlags, DWORD mouseCoopFlags)
{
HRESULT hr;
//初始化一个IDirectInput8接口对象
HR(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&m_pDirectInput, NULL));
//进行键盘设备的初始化
HR(m_pDirectInput->CreateDevice(GUID_SysKeyboard, &m_KeyboardDevice, NULL));
HR(m_KeyboardDevice->SetCooperativeLevel(hWnd, keyboardCoopFlags));
HR(m_KeyboardDevice->SetDataFormat(&c_dfDIKeyboard));
//进行鼠标设备的初始化
HR(m_pDirectInput->CreateDevice(GUID_SysMouse, &m_MouseDevice, NULL));
HR(m_MouseDevice->SetCooperativeLevel(hWnd, mouseCoopFlags));
HR(m_MouseDevice->SetDataFormat(&c_dfDIMouse));
return S_OK;
}
//-----------------------------------------------------------------------------
//用于获取设备信息的函数
//-----------------------------------------------------------------------------
void DirectInputClass::GetInput()
{
//鼠标设备轮询
m_MouseDevice->Poll();
//获取鼠标设备的控制权
m_MouseDevice->Acquire();
//获取鼠标输入信息
m_MouseDevice->GetDeviceState(sizeof(m_MouseState), &m_MouseState);
//键盘设备轮询
m_KeyboardDevice->Poll();
//获取键盘设备的控制权
m_KeyboardDevice->Acquire();
//获取键盘输入信息
m_KeyboardDevice->GetDeviceState(sizeof(m_KeyboardBuffer), &m_KeyboardBuffer);
}
//-----------------------------------------------------------------------------
//判断键盘上某个键是否按下
//-----------------------------------------------------------------------------
bool DirectInputClass::IsKeyDown(int iKey)
{
return (m_KeyboardBuffer[iKey] & 0x80) != 0;
}
//-----------------------------------------------------------------------------
//判断鼠标上某个键是否按下
//-----------------------------------------------------------------------------
bool DirectInputClass::IsMouseButtonDown(int button)
{
return (m_MouseState.rgbButtons[button] & 0x80) != 0;
}
//-----------------------------------------------------------------------------
//返回鼠标指针的X轴坐标值
//-----------------------------------------------------------------------------
float DirectInputClass::MouseDX()
{
return (float)m_MouseState.lX;
}
//-----------------------------------------------------------------------------
//返回鼠标指针的Y轴坐标值
//-----------------------------------------------------------------------------
float DirectInputClass::MouseDY()
{
return (float)m_MouseState.lY;
}
//-----------------------------------------------------------------------------
//返回鼠标指针的Z轴坐标值(滚轮)
//-----------------------------------------------------------------------------
float DirectInputClass::MouseDZ()
{
return (float)m_MouseState.lZ;
}
//-----------------------------------------------------------------------------
//析构函数
//-----------------------------------------------------------------------------
DirectInputClass::~DirectInputClass(void)
{
SAFE_RELEASE(m_pDirectInput);
if(m_KeyboardDevice)
m_KeyboardDevice->Unacquire();
if(m_MouseDevice)
m_MouseDevice->Unacquire();
SAFE_RELEASE(m_KeyboardDevice);
SAFE_RELEASE(m_MouseDevice);
}
我们再下一个头文件D3DUti.h来定义各种自定义操作。
D3DUti.h:
//自定义一个HR,方便执行错误的返回
#ifndef HR
#define HR(x) {hr = x; if(FAILED(hr)) return hr;}
#endif
//自定义一个SAFE_RELEASE宏,方便COM资源的释放
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) {if(p) {(p)->Release(); (p)=NULL;}}
#endif
//自定义一个SAFE_DELETE宏,方便指针资源的释放
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) {if(p) {delete (p); (p)=NULL;}}
#endif
WinMain源代码:
#include <d3d9.h>
#include <d3dx9.h>
#include <tchar.h>
#include "DirectInputClass.h"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE L"Direct 3D纹理过滤与寻址"
struct CUSTOMVERTEX
{
float x, y, z; //顶点的位置
float u, v; //纹理坐标
CUSTOMVERTEX(float _x, float _y, float _z, float _u, float _v):
x(_x), y(_y), z(_z), u(_u), v(_v){}
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
//---------------------------------------【全局变量声明部分】------------------------------------------------
//描述:全局变量的声明
//-----------------------------------------------------------------------------------------------------------
LPDIRECT3DDEVICE9 g_pd3dDevice; //Direct 3D设备对象
wchar_t g_strFPS[50]; //包含帧频率的字符数组
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer; //顶点缓存对象
LPDIRECT3DINDEXBUFFER9 g_pIndexBuffer; //索引缓存对象
LPDIRECT3DTEXTURE9 g_pMipTexture; //纹理接口对象,用于渐进纹理
D3DXMATRIX g_matWorld; //世界矩阵
DirectInputClass *g_pDInput; //一个DirectInput类的指针
LPD3DXFONT g_pTextAdapterName; //显卡名字的2D文本
LPD3DXFONT g_pTextHelpter; //帮助文本的2D文本
LPD3DXFONT g_pTextInfor; //绘制信息的2D文本
LPD3DXFONT g_pTextFPS; //FPS文本的2D文本
wchar_t g_strAdapterName[60]; //包括显卡名字的字符串 //包含帧频率的字符数组
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT Direct3D_Init(HWND); //在这个函数中继续Direct3D的初始化
HRESULT Objects_Init(HWND); //在这个函数中进行要绘制的物体的资源初始化
void Direct3D_Render(HWND); //在这个函数中进行Direct3D渲染代码的书写
void Direct3D_Update();
void Direct3D_ClearUp(); //在这个函数中清理COM资源以及其他资源
float Get_FPS();
void Matrix_Set();
//----------------------------------------【WinMain()函数】-------------------------------------------------
//描述:Windows应用程序的入口函数
//-------------------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wndClass = {0};
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = (WNDPROC)WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = (HICON)LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = L"3DGameBase";
if(!RegisterClassEx(&wndClass))
return -1;
HWND hWnd = CreateWindow(L"3DGameBase", WINDOW_TITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
MoveWindow(hWnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//进行DirectInput类的初始化
g_pDInput = new DirectInputClass();
g_pDInput->Init(hWnd, hInstance, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
PlaySound(L"Final Fantasy XIII.wav", NULL, SND_LOOP | SND_ASYNC | SND_FILENAME);
if(FAILED(Direct3D_Init(hWnd)))
MessageBox(hWnd, L"Direct3D 初始化失败!", L"消息窗口", 0);
MSG msg = {0};
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Direct3D_Update();
Direct3D_Render(hWnd);
}
}
UnregisterClass(L"3DGameBase", wndClass.hInstance);
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_PAINT:
Direct3D_Render(hWnd);
ValidateRect(hWnd, NULL); //使窗口区域生效
break;
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
DestroyWindow(hWnd);
break;
case WM_DESTROY:
//调用自定义的资源清理函数Direct3D_ClearUp();进行退出前的资源清理
Direct3D_ClearUp();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//---------------------------------------------【Direct3D_Init()函数】-----------------------------------------
//描述:Direct3D初始化函数,进行Direct3D的初始化
//---------------------------------------------------------------------------------------------------------------
HRESULT Direct3D_Init(HWND hWnd)
{
//---------------------------------------------------------------------------------------------------------------
//【Direct3D初始化步骤一】:创建Direct3D接口对象,以便用该Direct3D对象创建Direct3D设备对象
//---------------------------------------------------------------------------------------------------------------
LPDIRECT3D9 pD3D = NULL; //Direct3D接口对象的创建。
if((pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) //初始化Direct3D接口对象,并进行DirectX版本协商。
return E_FAIL;
//---------------------------------------------------------------------------------------------------------------
//【Direct3D初始化步骤二】:获取硬件设备信息
//---------------------------------------------------------------------------------------------------------------
D3DCAPS9 caps;
int vp = 0;
if(FAILED(pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps)))
return E_FAIL;
if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //支持硬件顶点运算,采用硬件顶点运算
else
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //不支持硬件顶点运算,采用软件顶点运算
//---------------------------------------------------------------------------------------------------------------
//【Direct3D初始化步骤三】:填充D3DPRESENT_PARAMETERS结构体
//---------------------------------------------------------------------------------------------------------------
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.BackBufferWidth = WINDOW_WIDTH;
d3dpp.BackBufferHeight = WINDOW_HEIGHT;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.Windowed = true;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = 0;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
//---------------------------------------------------------------------------------------------------------------
//【Direct3D初始化步骤四】:创建Direct3D设备接口。
//---------------------------------------------------------------------------------------------------------------
if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, vp, &d3dpp, &g_pd3dDevice)))
return E_FAIL;
//获取显卡信息到g_strAdapterName中,并在显卡名称前加上“当前显卡型号:”字符串
//定义一个D3DADAPTER_IDENTIFIER9结构体,用于存储显卡信息
D3DADAPTER_IDENTIFIER9 Adapter;
//调用GetAdapterIdentifier,获取显卡信息
if(FAILED(pD3D->GetAdapterIdentifier(0, 0, &Adapter)))
return E_FAIL;
//显卡名称现在已经在Adapter.Description中了,但是其为char类型,我们要将其转为wchar_t类型
int len = MultiByteToWideChar(CP_ACP, 0, Adapter.Description, -1, NULL, 0);
//这步操作完成后,g_strAdapterName中就为当前我们的显卡类型名的wchar_t型字符串了
MultiByteToWideChar(CP_ACP, 0, Adapter.Description, -1, g_strAdapterName, len);
//定义一个临时字符串,且方便了把"当前显卡型号:"字符串引入我们的目的字符串中
wchar_t tempName[50] = L"当前显卡型号:";
//把当前我们的显卡名加到“当前显卡型号:”字符串后面,结果存在TempName中
wcscat_s(tempName, g_strAdapterName);
//把TempName中的结果拷贝到全局变量g_strAdapterName中
wcscpy_s(g_strAdapterName, tempName);
SAFE_RELEASE(pD3D); //LPDIRECT3D9接口对象的使命完成,将其释放掉
if(FAILED(Objects_Init(hWnd))) //调用一次Objects_Init,进行渲染资源的初始化
return E_FAIL;
return S_OK;
}
//------------------------------------------【Objects_Init()】函数---------------------------------------------
//描述:渲染资源初始化函数,在此函数中进行要被渲染的物体的资源的初始化
//---------------------------------------------------------------------------------------------------------------
HRESULT Objects_Init(HWND hWnd)
{
//创建字体
if(FAILED(D3DXCreateFont(g_pd3dDevice, 36, 0, 0, 1000, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY, 0, L"Calibri", &g_pTextFPS)))
return E_FAIL;
if(FAILED(D3DXCreateFont(g_pd3dDevice, 20, 0, 0, 1000, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY, 0, L"华文中宋", &g_pTextAdapterName)))
return E_FAIL;
if(FAILED(D3DXCreateFont(g_pd3dDevice, 23, 0, 0, 1000, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY, 0, L"微软雅黑", &g_pTextHelpter)))
return E_FAIL;
if(FAILED(D3DXCreateFont(g_pd3dDevice, 26, 0, 0, 1000, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY, 0, L"黑体", &g_pTextInfor)))
return E_FAIL;
//创建顶点缓存
if(FAILED(g_pd3dDevice->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT,
&g_pVertexBuffer, 0)))
return E_FAIL;
//创建索引缓存
if(FAILED(g_pd3dDevice->CreateIndexBuffer(36*sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT,
&g_pIndexBuffer, 0)))
return E_FAIL;
//填充顶点缓存
CUSTOMVERTEX *pVertices = NULL;
if(FAILED(g_pVertexBuffer->Lock(0, 24*sizeof(CUSTOMVERTEX), (void**)&pVertices, 0)))
return E_FAIL;
// 正面顶点数据
pVertices[0] = CUSTOMVERTEX(-10.0f, 10.0f, -10.0f, 0.0f, 0.0f);
pVertices[1] = CUSTOMVERTEX( 10.0f, 10.0f, -10.0f, 2.0f, 0.0f);
pVertices[2] = CUSTOMVERTEX( 10.0f, -10.0f, -10.0f, 2.0f, 2.0f);
pVertices[3] = CUSTOMVERTEX(-10.0f, -10.0f, -10.0f, 0.0f, 2.0f);
// 背面顶点数据
pVertices[4] = CUSTOMVERTEX( 10.0f, 10.0f, 10.0f, 0.0f, 0.0f);
pVertices[5] = CUSTOMVERTEX(-10.0f, 10.0f, 10.0f, 2.0f, 0.0f);
pVertices[6] = CUSTOMVERTEX(-10.0f, -10.0f, 10.0f, 2.0f, 2.0f);
pVertices[7] = CUSTOMVERTEX( 10.0f, -10.0f, 10.0f, 0.0f, 2.0f);
// 顶面顶点数据
pVertices[8] = CUSTOMVERTEX(-10.0f, 10.0f, 10.0f, 0.0f, 0.0f);
pVertices[9] = CUSTOMVERTEX( 10.0f, 10.0f, 10.0f, 2.0f, 0.0f);
pVertices[10] = CUSTOMVERTEX( 10.0f, 10.0f, -10.0f, 2.0f, 2.0f);
pVertices[11] = CUSTOMVERTEX(-10.0f, 10.0f, -10.0f, 0.0f, 2.0f);
// 底面顶点数据
pVertices[12] = CUSTOMVERTEX(-10.0f, -10.0f, -10.0f, 0.0f, 0.0f);
pVertices[13] = CUSTOMVERTEX( 10.0f, -10.0f, -10.0f, 2.0f, 0.0f);
pVertices[14] = CUSTOMVERTEX( 10.0f, -10.0f, 10.0f, 2.0f, 2.0f);
pVertices[15] = CUSTOMVERTEX(-10.0f, -10.0f, 10.0f, 0.0f, 2.0f);
// 左侧面顶点数据
pVertices[16] = CUSTOMVERTEX(-10.0f, 10.0f, 10.0f, 0.0f, 0.0f);
pVertices[17] = CUSTOMVERTEX(-10.0f, 10.0f, -10.0f, 1.0f, 0.0f);
pVertices[18] = CUSTOMVERTEX(-10.0f, -10.0f, -10.0f, 1.0f, 1.0f);
pVertices[19] = CUSTOMVERTEX(-10.0f, -10.0f, 10.0f, 0.0f, 1.0f);
// 右侧面顶点数据
pVertices[20] = CUSTOMVERTEX( 10.0f, 10.0f, -10.0f, 0.0f, 0.0f);
pVertices[21] = CUSTOMVERTEX( 10.0f, 10.0f, 10.0f, 1.0f, 0.0f);
pVertices[22] = CUSTOMVERTEX( 10.0f, -10.0f, 10.0f, 1.0f, 1.0f);
pVertices[23] = CUSTOMVERTEX( 10.0f, -10.0f, -10.0f, 0.0f, 1.0f);
g_pVertexBuffer->Unlock();
// 填充索引数据
WORD *pIndices = NULL;
g_pIndexBuffer->Lock(0, 0, (void**)&pIndices, 0);
// 正面索引数据
pIndices[0] = 0; pIndices[1] = 1; pIndices[2] = 2;
pIndices[3] = 0; pIndices[4] = 2; pIndices[5] = 3;
// 背面索引数据
pIndices[6] = 4; pIndices[7] = 5; pIndices[8] = 6;
pIndices[9] = 4; pIndices[10] = 6; pIndices[11] = 7;
// 顶面索引数据
pIndices[12] = 8; pIndices[13] = 9; pIndices[14] = 10;
pIndices[15] = 8; pIndices[16] = 10; pIndices[17] = 11;
// 底面索引数据
pIndices[18] = 12; pIndices[19] = 13; pIndices[20] = 14;
pIndices[21] = 12; pIndices[22] = 14; pIndices[23] = 15;
// 左侧面索引数据
pIndices[24] = 16; pIndices[25] = 17; pIndices[26] = 18;
pIndices[27] = 16; pIndices[28] = 18; pIndices[29] = 19;
// 右侧面索引数据
pIndices[30] = 20; pIndices[31] = 21; pIndices[32] = 22;
pIndices[33] = 20; pIndices[34] = 22; pIndices[35] = 23;
g_pIndexBuffer->Unlock();
//设置材质
D3DMATERIAL9 mtrl;
ZeroMemory(&mtrl, sizeof(mtrl));
mtrl.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mtrl.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mtrl.Specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
g_pd3dDevice->SetMaterial(&mtrl);
//创建纹理
D3DXCreateTextureFromFileEx(g_pd3dDevice, L"pal5q.jpg", 0, 0, 6, 0, D3DFMT_X8R8G8B8,
D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0xFF000000, NULL, NULL, &g_pMipTexture);
//各向异性过滤
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 3);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
//线性纹理过滤
//g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
//g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
//最近点采样过滤
//g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
//g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
//渐进纹理过滤
//g_pd3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
//g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAXMIPLEVEL, 16);
Matrix_Set();
g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DXCOLOR(1.0, 1.0f, 1.0f, 1.0)); //设置环境光
return S_OK;
}
void Matrix_Set()
{
D3DXMATRIX matView;
D3DXVECTOR3 vEye(0.0f, 0.0f, -50.0f);
D3DXVECTOR3 vAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4.0f, (float)WINDOW_WIDTH/WINDOW_HEIGHT, 1.0f, 1000.0f);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = WINDOW_WIDTH;
vp.Height = WINDOW_HEIGHT;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
g_pd3dDevice->SetViewport(&vp);
}
//-----------------------------------------【Get_FPS()函数】---------------------------------------------------
//描述:用于计算帧频率
//---------------------------------------------------------------------------------------------------------------
float Get_FPS()
{
//定义四个静态变量
static int frameCount = 0; //帧数
static float currentTime = 0; //当前时间
static float lastTime = 0; //上次计算帧频率的时间
static float fps = 0; //需要计算的fps值
++frameCount; //每调用一次此函数,帧数加一
//获取系统时间, timeGetTime() 返回系统时间,以毫秒为单位,乘以0.001得到秒
currentTime = timeGetTime() * 0.001f;
//如果当前时间减去之前计算帧频率的时间大于1秒钟,就进行帧频率的更新,并将帧数归零
if(currentTime - lastTime > 1.0f) //将时间控制在1秒钟
{
fps = frameCount / (currentTime - lastTime); //计算这一秒的fps值
frameCount = 0; //将本次帧数清零
lastTime = currentTime; //将当前时间赋给上次计算帧频率的时间,作为下一秒的基准时间
}
return fps;
}
void Direct3D_Update()
{
//使用DirectInput类读取数据
g_pDInput->GetInput();
//根据键盘俺家的按下,设置为纹理寻址方式
if(g_pDInput->IsKeyDown(DIK_1))
{
//设置重复纹理寻址模式
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
}
if(g_pDInput->IsKeyDown(DIK_2))
{
///设置镜像纹理寻址模式
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
}
if(g_pDInput->IsKeyDown(DIK_3))
{
//设置夹取纹理寻址模式
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
}
if(g_pDInput->IsKeyDown(DIK_4))
{
//设置边框纹理寻址模式
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
}
//按住鼠标左键并拖动,为平移操作
static float fPosX = 0.0f, fPosY = 0.0f, fPosZ = 0.0f;
if(g_pDInput->IsMouseButtonDown(0))
{
fPosX += g_pDInput->MouseDX() * 0.08f;
fPosY -= g_pDInput->MouseDY() * 0.08f;
}
//鼠标滚轮,为观察点收缩操作
fPosZ -= g_pDInput->MouseDZ() * 0.02f;
//A,W,S,D键平移物体
if(g_pDInput->IsKeyDown(DIK_W))
fPosY += 0.08f;
if(g_pDInput->IsKeyDown(DIK_S))
fPosY -= 0.08f;
if(g_pDInput->IsKeyDown(DIK_A))
fPosX -= 0.08f;
if(g_pDInput->IsKeyDown(DIK_D))
fPosX += 0.08f;
D3DXMatrixTranslation(&g_matWorld, fPosX, fPosY, fPosZ);
// 按住鼠标右键并拖动,为旋转操作
static float fAngleX = 0.0f, fAngleY = 0.0f;
if(g_pDInput->IsMouseButtonDown(1))
{
fAngleX -= g_pDInput->MouseDY() * 0.01f;
fAngleY -= g_pDInput->MouseDX() * 0.01f;
}
//上下左右键旋转物体
if(g_pDInput->IsKeyDown(DIK_UP))
fAngleX += 0.005f;
if(g_pDInput->IsKeyDown(DIK_DOWN))
fAngleX -= 0.005f;
if(g_pDInput->IsKeyDown(DIK_LEFT))
fAngleY -= 0.005f;
if(g_pDInput->IsKeyDown(DIK_RIGHT))
fAngleY += 0.005f;
D3DXMATRIX Rx, Ry;
D3DXMatrixRotationX(&Rx, fAngleX);
D3DXMatrixRotationY(&Ry, fAngleY);
g_matWorld = Rx * Ry * g_matWorld;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_matWorld);
}
//----------------------------------------【Direct3D_Render()函数】--------------------------------------------
//描述:使用Direct3D进行渲染
//---------------------------------------------------------------------------------------------------------------
void Direct3D_Render(HWND hWnd)
{
//---------------------------------------------------------------------------------------------------------------
//【Direct3D渲染步骤一】:清屏操作
//---------------------------------------------------------------------------------------------------------------
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
//定义一个矩形,用来获取主窗口矩形
RECT formatRect;
GetClientRect(hWnd, &formatRect);
//---------------------------------------------------------------------------------------------------------------
//【Direct3D渲染步骤二】:开始绘制
//---------------------------------------------------------------------------------------------------------------
g_pd3dDevice->BeginScene(); //开始绘制
//---------------------------------------------------------------------------------------------------------------
//【Direct3D渲染步骤三】:正式绘制
//---------------------------------------------------------------------------------------------------------------
//在窗口右上角处,显示每秒帧数
swprintf_s(g_strFPS, L"FPS:%.3f", Get_FPS());
g_pTextFPS->DrawText(0, g_strFPS, -1, &formatRect, DT_TOP | DT_RIGHT, D3DCOLOR_XRGB(255,255,255));
//显示显卡类型名
g_pTextAdapterName->DrawText(0, g_strAdapterName, -1, &formatRect, DT_TOP | DT_LEFT, D3DXCOLOR(1.0f, 0.5f, 0.0f, 1.0f));
formatRect.top = 30;
static wchar_t strInfor[256] = {0};
// 输出绘制信息
swprintf_s(strInfor, L"模型坐标:(%.2f, %.2f, %.2f)", g_matWorld._41, g_matWorld._42, g_matWorld._43);
g_pTextInfor->DrawText(0, strInfor, -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(135, 239, 136, 255));
// 输出帮助信息
formatRect.top = 380;
g_pTextHelpter->DrawText(0, L"控制说明:", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235,123,230,255));
formatRect.top += 35;
g_pTextHelpter->DrawText(0, L" 按住鼠标左键并拖动:平移模型", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT,
D3DCOLOR_RGBA(255,200,0,255));
formatRect.top += 25;
g_pTextHelpter->DrawText(0, L" 按住鼠标右键并拖动:旋转模型", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT,
D3DCOLOR_RGBA(255,200,0,255));
formatRect.top += 25;
g_pTextHelpter->DrawText(0, L" 按住鼠标滚轮:拉伸模型", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT,
D3DCOLOR_RGBA(255,200,0,255));
formatRect.top += 25;
g_pTextHelpter->DrawText(0, L" W、S、A、D键:平移模型 ", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT,
D3DCOLOR_RGBA(255,200,0,255));
formatRect.top += 25;
g_pTextHelpter->DrawText(0, L" 上、下、左、右键:旋转模型 ", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT,
D3DCOLOR_RGBA(255,200,0,255));
formatRect.top += 25;
g_pTextHelpter->DrawText(0, L" 键盘上1、2、3、4数字键,在四种寻址模式之间切换", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT,
D3DCOLOR_RGBA(255,200,0,255));
formatRect.top += 25;
g_pTextHelpter->DrawText(0, L" ESC键 : 退出程序", -1, &formatRect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT,
D3DCOLOR_RGBA(255,200,0,255));
g_pd3dDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(CUSTOMVERTEX));
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
g_pd3dDevice->SetIndices(g_pIndexBuffer);
g_pd3dDevice->SetTexture(0, g_pMipTexture); //启用纹理
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
//---------------------------------------------------------------------------------------------------------------
//【Direct3D渲染步骤四】:结束绘制
//---------------------------------------------------------------------------------------------------------------
g_pd3dDevice->EndScene(); //结束绘制
//---------------------------------------------------------------------------------------------------------------
//【Direct3D渲染步骤五】:显示翻转
//---------------------------------------------------------------------------------------------------------------
g_pd3dDevice->Present(NULL, NULL, NULL, NULL); //翻转与显示
}
//------------------------------------------------【 Direct3D_ClearUp函数】------------------------------------------
//描述:资源清理函数,在此函数中进行程序退出前资源的清理工作
//-------------------------------------------------------------------------------------------------------------------
void Direct3D_ClearUp()
{
SAFE_RELEASE(g_pd3dDevice);
//释放COM接口对象
SAFE_RELEASE(g_pVertexBuffer);
SAFE_RELEASE(g_pIndexBuffer);
SAFE_RELEASE(g_pMipTexture);
SAFE_DELETE(g_pDInput);
SAFE_RELEASE(g_pTextAdapterName);
SAFE_RELEASE(g_pTextFPS);
SAFE_RELEASE(g_pTextInfor);
SAFE_RELEASE(g_pTextHelpter);
}