㈠ 關於Direct2D
Direct2D是一個硬件加速的,提供立即模式的二維圖形API。它提供了二維的幾何體,位圖,文本的高性能,高質量的渲染。十分方便的是,Direct2D與GDI,GDI+和D3D都是可以交互的。一項技術總是有其受眾面,看看微軟本身怎么說的
:
- 大型企業級本機應用程序開發人員。
- 創建供下游開發人員使用的控件工具包和庫的開發人員。
- 需要對二維圖形進行服務器端呈現的開發人員。
- 使用 Direct3D 圖形,並且需要在菜單、用戶界面 (UI) 元素和抬頭顯示器 (HUD) 中使用高性能的簡單二維和文本呈現的開發人員。
㈡ Direct2D的架構
Direct2D是基於使用Direct3D 10.1的API,所以Direct2D的應用可以再渲染的時候受益於顯卡的硬件加速。以下是其架構圖,來源於Direct2D的document:
在Direct2D的右下方,有一個軟件光柵化(software rasterizer),假如顯卡不支持硬件加速,那么Direct2D可以使用軟件方式渲染,即便是這樣,其效果還是要優於GDI的。在Direct 3D下面還有一層叫DXGI(DirectX Graphics Infrastructure (DXGI) ),對於DXGI,現在我還不是很了解,這里就不敢亂說了
。抱歉抱歉。。
㈢ 視覺效果
使用Direct2D渲染出來的效果要比GDI要好的多。因為Direct2D使用基於圖元的反鋸齒效果(這樣會使線條更加的平滑),而且在渲染二維圖元的時候,完全支持透明和alpha混合。以下是對比的照片:
兩者的對比很明顯吧!顯然,右邊的Direct2D的線條效果要好於左邊的GDI。
㈢ 交互性
介紹交互性,先看看下面這張圖:
此張圖介紹了Direct2D與Direct3D,GDI+,GDI,DirectWrite,Windows Imaging Component (WIC)的交互性。在這張圖中列出了與各個不同的平台交互的函數。雖然對其中的某些平台不了解,但看起來好像很厲害的樣子。
㈣ Direct2D的Hello World
⑴ Direct2D的頭文件
Direct2D API定義於以下頭文件中:
頭文件 |
描述 |
d2d1.h | 定義了主要的Direct2D API |
d2d1helper.h | 定義了C++幫助函數,類和結構 |
d2dbasetypes.h | 定義了Direct2D的主要繪圖,例如:點,矩形等。其頭文件也包含在d2d1.h之中。 |
d2derr.h | 定義了異常代碼在Direct2D中。其頭文件也包含在d2d1.h之中。 |
除了包含這些頭文件,還有包含d2d1.lib這個庫。你可以在Windows Software Development Kit (SDK) for Windows 7中可以找到以上這些東西。
⑵ 基本術語解釋
① Direct2D Resources(資源)
所謂的資源,指的是視頻內存或系統內存的某種分配。舉例來說,位圖和畫筆就是資源。Direct2D提供了更直接的映射來充分利用 GPU。它提供了兩類資源:與設備無關的資源和與設備有關的資源。(以下兩部分內容來自msdn上的解釋)
ⅰ 與設備無關的資源(如 ID2D1Geometry)保留在 CPU 上。
- ID2D1DrawingStateBlock
- ID2D1Factory
- ID2D1Geometry 以及從其繼承的接口。
- ID2D1GeometrySink 和 ID2D1SimplifiedGeometrySink
- ID2D1StrokeStyle
ⅱ 與設備有關的資源(如 ID2D1RenderTarget 和 ID2D1LinearGradientBrush)直接映射到 GPU 上的資源(如果硬件加速可用)。通過將來自幾何對象的頂點和覆蓋信息與由與設備有關的資源生成的紋理信息進行組合,來執行呈現調用。
- ID2D1Brush 以及從其繼承的接口。使用呈現器目標可創建畫筆。
- ID2D1Layer 使用呈現器目標可創建層。
- ID2D1RenderTarget 以及從其繼承的接口。若要創建呈現器目標,請使用工廠或其他呈現器目標。
② RenderTarget(渲染目標)
渲染目標是從ID2D1RenderTarget 接口繼承的資源。其用於創建繪制的資源,並執行實際的繪制操作。你可以通過以下方式使用多種類型的渲染目標來呈現圖形:。(以下部分內容來自msdn上的解釋)
- ID2D1HwndRenderTarget 對象將內容呈現到窗口。
- ID2D1DCRenderTarget 對象呈現到 GDI 設備上下文。
- 位圖呈現器目標對象將內容呈現到屏幕外位圖。
- DXGI 呈現器目標對象呈現到用於 Direct3D 的 DXGI 圖面。
③ Brush(畫筆)
畫筆用其輸出來“繪制”區域,不同的畫筆具有不同的輸出類型。Direct2D 提供了四種畫筆:。(以下部分內容來自msdn上的解釋)
- ID2D1SolidColorBrush 用純色繪制區域
- ID2D1LinearGradientBrush 用線性漸變繪制區域
- ID2D1RadialGradientBrush 用徑向漸變繪制區域
- ID2D1BitmapBrush 用位圖繪制區域
④ ID2D1Geometry(幾何對象)
Direct2D 幾何對象是由 ID2D1Factory 創建的與設備無關的不可變資源。其對象可以是簡單幾何對象(ID2D1RectangleGeometry、ID2D1RoundedRectangleGeometry 或 ID2D1EllipseGeometry)、路徑幾何對象 (ID2D1PathGeometry) 或復合幾何對象(ID2D1GeometryGroup 和ID2D1TransformedGeometry)。
⑤ Bitmap(位圖)
Direct2D 不提供用於加載或存儲位圖的方法;而是使您可以使用 Windows 圖像處理組件 (WIC) 創建位圖。位圖資源可以使用 WIC 進行加載,然后通過 ID2D1RenderTarget::CreateBitmapFromWicBitmap 方法用於創建 ID2D1Bitmap。
⑶ Hello World來了,創建一個矩形!
① 包含 Direct2D 頭文件
// windows的頭文件
#include <windows.h>
// Direct2D的頭文件
#include <d2d1.h>
② 創建一個ID2D1Factory
ID2D1Factory是使用 Direct2D 的起點,使用 ID2D1Factory 可創建 Direct2D 資源。
ID2D1Factory* pd2dfactory = null;
HRESULT hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&pd2dfactory
);
③ 創建 ID2D1HwndRenderTarget
創建工廠之后,我們要創建渲染目標。具體見下面的代碼:
HRESULT hr = S_OK;
if (!m_pRenderTarget)
{
RECT rc;
GetClientRect(m_hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);
// 創建一個Direct2D渲染目標,m_pRenderTarget這是我們要創建的。
hr = m_pDirect2dFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(m_hwnd, size),
&m_pRenderTarget
);
if (SUCCEEDED(hr))
{
// 創建一個灰色的畫筆,調用的是CreateSolidColorBrush函數,LightSlateGray這是筆的顏色
hr = m_pRenderTarget->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::LightSlateGray),
&m_pLightSlateGrayBrush
);
}
if (SUCCEEDED(hr))
{
// 創建一個藍色的畫筆
hr = m_pRenderTarget->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::CornflowerBlue),
&m_pCornflowerBlueBrush
);
}
}
④ 繪制矩形
HRESULT hr = S_OK;
hr = CreateDeviceResources(); // 創建好了m_pRenderTarget
if (SUCCEEDED(hr))
{
m_pRenderTarget->BeginDraw(); // 繪制就在BeginDraw()和EndDraw()之間
m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue)); // 背景顏色
D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize();
// 繪制一個網格背景
int width = static_cast<int>(rtSize.width);
int height = static_cast<int>(rtSize.height);
for (int x = 0; x < width; x += 10)
{
m_pRenderTarget->DrawLine(
D2D1::Point2F(static_cast<FLOAT>(x), 0.0f),
D2D1::Point2F(static_cast<FLOAT>(x), rtSize.height),
m_pLightSlateGrayBrush,
0.5f
);
}
for (int y = 0; y < height; y += 10)
{
m_pRenderTarget->DrawLine(
D2D1::Point2F(0.0f, static_cast<FLOAT>(y)),
D2D1::Point2F(rtSize.width, static_cast<FLOAT>(y)),
m_pLightSlateGrayBrush,
0.5f
);
}
//繪制兩個矩形
D2D1_RECT_F rectangle1 = D2D1::RectF(
rtSize.width/2 - 50.0f,
rtSize.height/2 - 50.0f,
rtSize.width/2 + 50.0f,
rtSize.height/2 + 50.0f
);
D2D1_RECT_F rectangle2 = D2D1::RectF(
rtSize.width/2 - 100.0f,
rtSize.height/2 - 100.0f,
rtSize.width/2 + 100.0f,
rtSize.height/2 + 100.0f
);
// 繪制一個實心的矩形
m_pRenderTarget->FillRectangle(&rectangle1, m_pLightSlateGrayBrush);
// 繪制一個空心的矩形
m_pRenderTarget->DrawRectangle(&rectangle2, m_pCornflowerBlueBrush);
// 結束繪制
hr = m_pRenderTarget->EndDraw();
}
if (hr == D2DERR_RECREATE_TARGET)
{
hr = S_OK;
DiscardDeviceResources(); // 釋放資源
}
⑤ 釋放資源
template<class Interface>
inline void SafeRelease(
Interface **ppInterfaceToRelease
)
{
if (*ppInterfaceToRelease != NULL)
{
(*ppInterfaceToRelease)->Release();
(*ppInterfaceToRelease) = NULL;
}
}
// 上面是釋放函數,下面是釋放的對象!
SafeRelease(&m_pRenderTarget);
SafeRelease(&m_pLightSlateGrayBrush);
SafeRelease(&m_pCornflowerBlueBrush);
這是執行的結果:
弄了兩天才寫好,上面的有些東西也不是特別了解,請見諒!但是應該會隨着時間的推移,了解更深的。如果大牛們看到其中的不足,請大牛們指正,本人不甚感激!
參考文獻
1. msdn文檔:http://msdn.microsoft.com/zh-cn/library/dd370990(v=vs.85).aspx
2.還是msdn文檔。。。。因為本文是基於文檔寫成的。