#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
PDIRECT3D9 g_D3D = nullptr; // D3D對象
PDIRECT3DDEVICE9 g_D3DDevice = nullptr; // D3D設備對象
D3DXMATRIX g_projection; // 矩陣變量,用於透視投影變換
bool InitializeD3D(HWND hWnd); // 初始化D3D
void ShutdownD3D(); // 退出窗口之前釋放D3D對象和D3D設備對象
void RenderScene(); // 渲染場景
bool InitializeObjects();// 初始化3D圖形對象
// 頂點數據
struct stD3DVertex
{
float x, y, z; // 座標值(屏幕座標) (左手座標系) rhw 標誌
unsigned long color; // 漫射光顏色
};
// 頂點緩存
PDIRECT3DVERTEXBUFFER9 g_VertexBuffer = nullptr;
// 頂點格式
#define D3DFVF_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // 窗口消息處理過程
void MyCreateWindow(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd); // 創建窗口
/************************************************************************/
/* Windows窗口程序入口函數 */
/************************************************************************/
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
MyCreateWindow(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
return 0;
}
/************************************************************************/
/* 創建窗口 */
/************************************************************************/
void MyCreateWindow(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
// 聲明一個窗口類 包含創建一個窗口所需要的相關數據信息
WNDCLASSEX wc = {
sizeof(WNDCLASSEX), // 窗口類的內存空間大小(字節)
CS_CLASSDC, // 窗口風格
MsgProc, // 處理消息的函數指針
0, // 類額外信息
0, // 窗口額外信息
hInstance, // 句柄,可以看作是窗口的身份標識
nullptr, // 圖標樣式
nullptr, // 鼠標樣式
nullptr, // 背景畫刷 也可以設置爲一個顏色值 調用UnregisterClass後由系統刪除
nullptr, // 菜單
"AppClass", // 窗口類名
nullptr // 窗口小圖標
};
// 註冊窗口類
RegisterClassEx(&wc);
// 創建窗口
HWND hWnd = CreateWindow(
"AppClass", // 窗口類名
"Window Title", // 窗口標題
WS_OVERLAPPEDWINDOW, // 窗口風格 (可重疊)
100, // 窗口左上角在屏幕座標中的X值
100, // 窗口左上角在屏幕座標中的Y值
WINDOW_WIDTH, // 窗口寬度
WINDOW_HEIGHT, // 窗口高度
GetDesktopWindow(), // 窗口父類
nullptr, // 菜單
hInstance, // 句柄
nullptr
);
if (InitializeD3D(hWnd))
{
// 設置指定窗口爲顯示狀態
ShowWindow(hWnd, SW_SHOWDEFAULT);
// 發送繪製消息給窗口
UpdateWindow(hWnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(
&msg, // 存儲消息的結構體指針
nullptr, // 窗口消息和線程消息都會被處理
0, // 消息過濾最小值; 爲0時返回所有可用信息
0, // 消息過濾最大值; 爲0時返回所有可用信息
PM_REMOVE // 指定消息如何處理; 消息在處理完後從隊列中移除
))
{
TranslateMessage(&msg); // 變換虛擬鍵消息到字符消息,字符消息被髮送到調用線程的消息隊列
DispatchMessage(&msg); // 派發消息到窗口過程
}
else
{
// 渲染場景
RenderScene();
}
}
}
// 釋放D3D對象和D3D設備對象資源
ShutdownD3D();
// 註銷窗口類,釋放窗口所佔用資源
UnregisterClass("AppClass", wc.hInstance);
}
/************************************************************************/
/* 窗口消息處理過程 */
/************************************************************************/
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
default:
break;
}
// windows消息的默認處理函數
return DefWindowProc(hWnd, msg, wParam, lParam);
}
/************************************************************************/
/* 初始化D3D對象和D3D設備對象*/
/************************************************************************/
bool InitializeD3D(HWND hWnd)
{
// 顯示模式 (以像素爲單位的屏幕寬高,刷新頻率,surface formt)
D3DDISPLAYMODE displayMode;
// 創建D3D對象 獲取主顯卡硬件信息 最先被創建,最後被釋放
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_D3D == nullptr)
{
return false;
}
// 獲取顯示模式
if (FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT/*查詢主顯卡*/, &displayMode)))
{
return false;
}
// D3D 顯示參數
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = true; // 是否窗口化
d3dpp.BackBufferFormat = displayMode.Format; // D3DFMT_X8R8G8B8 表示爲32位RGB像素格式 每種顏色用一個字節表示
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // 幀緩衝區交換方式; 可能是COPY可能是FLIP,由設備來確定適合當前情況的方式
// 創建D3D設備對象 ---- 代表顯卡
if (FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice)))
{
return false;
}
// 初始化圖形對象需要的頂點數據
if (!InitializeObjects())
{
return false;
}
return true;
}
/************************************************************************/
/* 釋放D3D對象及設備對象資源*/
/************************************************************************/
void ShutdownD3D()
{
if (g_D3DDevice != nullptr)
{
g_D3DDevice->Release(); // 釋放設備對象
g_D3DDevice = nullptr;
}
if (g_VertexBuffer != nullptr)
{
g_VertexBuffer->Release(); // 釋放頂點緩存
g_VertexBuffer = nullptr;
}
if (g_D3D != nullptr)
{
g_D3D->Release(); // 最行創建, 最後釋放
g_D3D = nullptr;
}
}
/************************************************************************/
/* 渲染場景 */
/************************************************************************/
void RenderScene()
{
g_D3DDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
g_D3DDevice->BeginScene();
// 通知D3D設備對象數據源
g_D3DDevice->SetStreamSource(
0,
g_VertexBuffer, // 數據源地址
0, // 頂點緩存起始偏移
sizeof(stD3DVertex) // 每個頂點數據的大小
);
g_D3DDevice->SetFVF(D3DFVF_VERTEX);
// 繪製圖元
g_D3DDevice->DrawPrimitive(
D3DPT_TRIANGLELIST, // 圖元類型; 三角形
0, // 要加載的第一個頂點的索引
1 // 圖元數量, 由圖元類型決定(一個三角形)
);
g_D3DDevice->EndScene();
// 顯示backbuffer內容到屏幕
g_D3DDevice->Present(nullptr, nullptr, nullptr, nullptr);
}
/************************************************************************/
/* 初始化頂點數據 */
/************************************************************************/
bool InitializeObjects()
{
// 基於攝像機視野創建左手座標系透視投影矩陣
D3DXMatrixPerspectiveFovLH(
&g_projection,
45.f, // 剖面的角度範圍
WINDOW_WIDTH / WINDOW_HEIGHT, // Aspect 寬度比
0.1f, // 近裁剪面
1000.f // 遠裁剪面
);
// 設置投影變換
g_D3DDevice->SetTransform(
D3DTS_PROJECTION, // 標識爲投影變換
&g_projection // 變幻矩陣
);
// 設置光照
g_D3DDevice->SetRenderState(
D3DRS_LIGHTING, // 渲染狀態類型; 光照
FALSE // 不使用光照
);
// 裁剪 (背面剔除)
g_D3DDevice->SetRenderState(
D3DRS_CULLMODE,
D3DCULL_NONE // 不進行背面剔除
);
// 三角形頂點數據
stD3DVertex objData[] =
{
{-0.3f, -0.3f, 5.f, D3DCOLOR_XRGB(255, 255, 0)}, // 本地座標系,也稱模型座標
{0.3f, -0.3f, 5.f, D3DCOLOR_XRGB(255, 0, 0)},
{0.f, 0.3f, 5.f, D3DCOLOR_XRGB(0, 0, 255)}
};
// 創建頂點緩存
;
if (FAILED(
g_D3DDevice->CreateVertexBuffer(
sizeof(objData), // 頂點緩衝區的大小
0, // 頂點緩存的處理取決於D3D設備和頂點緩衝區是如何創建的(硬處理 or 軟處理) 創建的設備對象爲 D3DCREATE_HARDWARE_VERTEXPROCESSING 則此值必須爲0
D3DFVF_VERTEX, // 頂點格式
D3DPOOL_DEFAULT, // 默認使用顯卡顯存
&g_VertexBuffer, // 頂點緩存指針
nullptr // 保留值, 適用於Vista以上系統中資源分享
)))
{
return false;
}
void* ptr = nullptr; // 頂點緩存地址
// 在顯存中獲取一塊顯存空間用於存儲頂點數據
if (FAILED(g_VertexBuffer->Lock(
0, // 全部緩存
sizeof(objData), // 頂點數據大小
(void**)&ptr, // 將頂點數據首地址返回給ptr指針
0 // 鎖定標記
)))
{
return false;
}
// 將頂數數據複製到頂點緩存裏(顯存)
memcpy(ptr, objData, sizeof(objData));
g_VertexBuffer->Unlock(); // 解鎖頂點緩存
return true;
}
DirectX 畫三角形 透視投影
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.