#include <windows.h>
#include <tchar.h>
#include <d3dx9.h>
#include <cmath>
#pragma comment(lib,"D3D9.lib")
//函数声明
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);//窗口过程
bool InitD3D(HINSTANCE hInstance);
bool Setup();
void Cleanup();
void Render(); //绘制
//窗口相关全局变量
const TCHAR g_szWindowTitleName[] = _T("索引缓存"); //窗口标题
const TCHAR g_szWindowClassName[] = _T("WindowClass"); //窗口类名
int g_cxWindow = 640; //窗口宽
int g_cyWindow = 480; //窗口高
//Direct3D全局变量
IDirect3D9 * g_pD3d = nullptr; //Direct3D对象指针
IDirect3DDevice9 * g_pDevice = nullptr; //Direct3D设备对象指针
IDirect3DVertexBuffer9 * g_pVertexBuffer = nullptr;
IDirect3DIndexBuffer9 * g_pIndexBuffer = nullptr;
//定义顶点结构
struct Vertex
{
Vertex(float x, float y, float z, float rhw,DWORD color)
{
_x = x;
_y = y;
_z = z;
_rhw = rhw;
_color = color;
}
float _x, _y, _z, _rhw;
DWORD _color;
static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
//定义圆的相关参数
int g_numTriangle = 8; //组成圆的三角形个数
int g_numVertex = g_numTriangle + 1; //顶点个数
int g_radius = 200; //圆半径
int g_offsetX = g_cxWindow / 2; //圆心x坐标
int g_offsetY = g_cyWindow / 2; //圆心y坐标
int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPTSTR lpCmdLine,
int nShowCmd)
{
if (!InitD3D(hInstance))
{
MessageBox(NULL, _T("初始化D3D失败"), NULL, MB_OK);
return 0;
}
if (!Setup())
{
MessageBox(NULL, _T("启动失败!"), NULL, MB_OK);
return 0;
}
MSG msg;
memset(&msg, 0, sizeof(msg));
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Render(); //5 绘制
}
}
Cleanup(); //6 清理资源
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
bool InitD3D(HINSTANCE hInstance)
{
WNDCLASS wndClass; //初始化窗口类结构体
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.hInstance = hInstance;
wndClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.lpfnWndProc = WndProc;
wndClass.lpszClassName = g_szWindowClassName;
wndClass.lpszMenuName = NULL;
BOOL bRet;
bRet = RegisterClass(&wndClass); //注册窗口类
if (!bRet)
{
MessageBox(NULL, _T("Register window class fail"), NULL, MB_OK);
return FALSE;
}
HWND hWnd;
hWnd = CreateWindow(g_szWindowClassName,//创建窗口
g_szWindowTitleName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
g_cxWindow,
g_cyWindow,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
{
MessageBox(NULL, _T("Create Window FAil"), NULL, MB_OK);
return FALSE;
}
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
//init Direct3D
g_pD3d = Direct3DCreate9(D3D_SDK_VERSION); //1、创建D3D对象
if (!g_pD3d)
{
MessageBox(NULL, _T("创建D3D对象失败!"), NULL, MB_OK);
return false;
}
D3DCAPS9 caps; //2、检查设备能力,硬件是否支持顶点运算
g_pD3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
int cap;
if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
cap = D3DCREATE_HARDWARE_VERTEXPROCESSING; //用硬件方式处理顶点运算
else
cap = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //用软件方式处理顶点运算
HRESULT hr;
D3DPRESENT_PARAMETERS d3dpp; //3、初始化D3DPRESENT_PARAMETERS结构体
memset(&d3dpp, 0, sizeof(D3DPRESENT_PARAMETERS));
d3dpp.BackBufferWidth = 640;
d3dpp.BackBufferHeight = 480;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferCount = 1;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
hr = g_pD3d->CreateDevice(D3DADAPTER_DEFAULT, //4、创建D3D设备对象
D3DDEVTYPE_HAL,
hWnd,
cap,
&d3dpp,
&g_pDevice);
if (FAILED(hr))
{
MessageBox(NULL, _T("创建D3D设备对象失败!"), NULL, MB_OK);
return false;
}
return true;
}
bool Setup()
{
HRESULT hr;
//创建顶点缓存
hr = g_pDevice->CreateVertexBuffer(sizeof(Vertex)* g_numVertex,
D3DUSAGE_DYNAMIC,
Vertex::FVF,
D3DPOOL_DEFAULT,
&g_pVertexBuffer,
NULL);
if (FAILED(hr))
{
MessageBox(NULL, _T("创建顶点缓存失败!"), NULL, MB_OK);
return false;
}
//初始化顶点数据
Vertex * pVertexs = nullptr;
g_pVertexBuffer->Lock(0, 0, (void**)&pVertexs, 0);
pVertexs[0] = Vertex(g_offsetX, g_offsetY, 1.f, 1.f, D3DCOLOR_XRGB(0, 255, 0));; //设置圆心
for (int i = 0; i < g_numVertex - 1; ++i)
{
int x, y;
//注意角度的增大方向为逆时针,屏幕坐标轴的方向、圆的坐标轴方向
x = g_offsetX + cos(1.f * i / (g_numVertex - 1) * (2 * D3DX_PI)) * g_radius; //顶点x坐标
y = g_offsetY + sin(1.f * i / (g_numVertex - 1) * (2 * D3DX_PI)) * g_radius; //顶点y坐标 ,这里是加上圆的y坐标对其对称变换
pVertexs[i + 1] = Vertex(x, y, 1.f, 1.f, D3DCOLOR_XRGB(i * 10 + 100, 0, 0));
}
g_pVertexBuffer->Unlock();
//创建索引缓存
hr = g_pDevice->CreateIndexBuffer(sizeof(WORD)* g_numTriangle * 3,
D3DUSAGE_DYNAMIC,
D3DFMT_INDEX16,
D3DPOOL_DEFAULT,
&g_pIndexBuffer,
NULL);
if (FAILED(hr))
{
MessageBox(NULL, _T("创建索引缓存失败!"), NULL, MB_OK);
return false;
}
//初始化索引数据
WORD *pIndex;
g_pIndexBuffer->Lock(0, 0, (void**)&pIndex, 0);
*pIndex = 0; //设置第一个三角形的索引
*(pIndex + 1) = 1; //注意设置的顺序
*(pIndex + 2) = 2;
int i;
for (i = 1; i < g_numTriangle; ++i)
{
*(pIndex + i * 3) = 0;
*(pIndex + i * 3 + 1) = *(pIndex + (i - 1) * 3 + 2);
*(pIndex + i * 3 + 2) = *(pIndex + i * 3 + 1) + 1;
}
*(pIndex + --i * 3 + 2) = 1; //设置最后一个索引
g_pIndexBuffer->Unlock();
return true;
}
void Cleanup()
{
if (g_pDevice){ g_pDevice->Release(); g_pDevice = nullptr; }
if (g_pD3d){ g_pD3d->Release(); g_pD3d = nullptr; }
}
void Render()
{
HRESULT hr;
hr = g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 255, 255, 255), 1.f, 0);
hr = g_pDevice->BeginScene();
if (SUCCEEDED(hr))
{
//......render
g_pDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(Vertex));
g_pDevice->SetFVF(Vertex::FVF);
g_pDevice->SetIndices(g_pIndexBuffer); //为顶点缓存设置对应的索引数据
g_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0,g_numVertex, 0,g_numTriangle); //基于索引去绘制图元
g_pDevice->EndScene();
}
hr = g_pDevice->Present(nullptr, nullptr, NULL, nullptr);
}
运行结果: