DirectX 其實不像傳聞那麼難懂,學習曲線雖陡峭但一旦跨越,其運作邏輯相當清晰。然而 DirectX API 的易用性確實有提升空間。為此我開發了 dx.h —— 單一標頭檔、近 5,000 行程式碼的現代 C++ 庫,目標在於:借助 C++11 提供更簡便的 DirectX API,且在核心 API 之上不產生任何時空開銷。專案託管於 dx.codeplex.com。
開發者常分兩派:DirectX 鐵桿派樂於掌握複雜 API;另一派因聽聞難度而完全避開。我屬於兩者之間——相信 C++ 與 DirectX 不必如此困難。上月專欄介紹 Direct2D 1.1 時,建立裝置與管理交換鏈約需 35 行程式碼;有了 dx.h,簡化為:
auto device = CreateDevice();
Device1 封裝 ID3D11Device1,繼承自封裝 ID3D11Device 的 Device。它們表現如智慧指標,但提供豐富的非虛擬方法。例如取得 DXGI 介面:
// 傳統作法 wrl::ComPtr<IDXGIDevice2> dxdevice; HR(device->QueryInterface(dxdevice.GetAddressOf())); // dx.h 作法 auto dxdevice = device.AsDxgi();
存取 DXGI 工廠更有捷徑:
auto dxfactory = d3device.GetDxgiFactory();
DirectX 定義大量傳統列舉,非強型別、難以發現。dx.h 使用 scoped enum:
// 傳統 D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, ...); // dx.h auto factory = CreateFactory(FactoryType::MultiThreaded);
DXGI_SWAP_CHAIN_DESC1 成員繁多易混淆。dx.h 提供二進位相容的 SwapChainDescription1,預設值適用大多數案例:
SwapChainDescription1 description; description.SwapEffect = SwapEffect::Discard; // 桌面應用需求
建立線性漸層筆刷(圖 1 對比):
// 傳統
D2D1_GRADIENT_STOP stops[] = { {0.0f, COLOR_WHITE}, {1.0f, COLOR_BLUE} };
HR(target->CreateGradientStopCollection(stops, _countof(stops), ...));
HR(target->CreateLinearGradientBrush(..., collection.Get(), ...));
// dx.h
GradientStop stops[] = { GradientStop(0.0f, COLOR_WHITE), GradientStop(1.0f, COLOR_BLUE) };
auto collection = target.CreateGradientStopCollection(stops);
auto brush = target.CreateLinearGradientBrush(collection);
函數模板自動推導陣列大小,無需 _countof。
HR 內聯函數在 HRESULT 非 S_OK 時拋出例外,實現錯誤自動傳播。以 AsDxgi 為例:
inline auto Device::AsDxgi() const -> Dxgi::Device2 {
Dxgi::Device2 result;
HR(m_ptr.CopyTo(result.GetAddressOf()));
return result;
}
所有方法標記 const(唯一資料成員 ComPtr 無需修改),利用移動語義避免執行期 AddRef/Release 開銷,並回傳最具體類別減少呼叫端 QueryInterface。
初期嘗試以 C++ 繼承對應 COM 介面繼承(DeviceContext 繼承 RenderTarget),但會導致雙重引用問題。最終採用「COM 取巧」策略:所有類別持有 IUnknown 泛型引用,由 C++ 型別系統提供型別安全:
class Object { ComPtr<IUnknown> ptr; };
class RenderTarget : public Object {};
class DeviceContext : public RenderTarget {};
此設計完美對應 COM 介面層級,編程模型自然實用。
目前涵蓋幾乎所有 Direct2D、Windows 動畫管理器、部分 DirectWrite、WIC、Direct3D 與 DXGI。定期更新中,歡迎深入研讀原始碼體驗現代 C++ 與 DirectX 的結合之美。