[Direct2D開發] 繪制網格


轉載請注明出處:http://www.cnblogs.com/Ray1024

 

一、引言

最近在使用Direct2D進行繪制工作中,需要實現使用Direct2D繪制網格的功能。在網上查了很多資料,終於實現了,把方法貼到這里供大家參考。

 

二、繪制網格

2.1 API接口

首先介紹一下繪制網格中使用到的重要接口ID2D1BitmapRenderTarget,它繼承自ID2D1RenderTarget,會寫入到中間紋理。對於創建與 ID2D1BitmapBrush 結合使用的圖案,或緩存要反復使用的繪制數據,這十分有用。它僅僅比基類多了一個函數GetBitmap,此函數可以將內部的繪制數據輸出到位圖ID2D1Bitmap中,如下:

語法:	virtual HRESULT GetBitmap([out]  ID2D1Bitmap **bitmap) = 0;
功能:	檢索此呈現器目標的位圖。返回的位圖可用於繪制操作。
參數:	bitmap 		此方法返回時,包含指向此呈現器目標的位圖的指針地址。此位圖可用於繪制操作。
返回值:HRESULT		如果該方法成功,則返回 S_OK。 否則,將返回錯誤代碼。HRESULT.

創建ID2D1BitmapRenderTarget對象的函數為ID2D1RenderTarget::CreateCompatibleRenderTarget,這個函數有6個重載,我們只介紹其中一個,有興趣的朋友可以查看msdn文檔,介紹如下:

語法:HRESULT CreateCompatibleRenderTarget(D2D1_SIZE_F desiredSize,[out]  ID2D1BitmapRenderTarget **bitmapRenderTarget);
功能:創建新位圖呈現器目標,以供在中間屏幕外繪制期間使用。新位圖呈現器目標與當前呈現器目標兼容,並且與當前呈現器目標有相同的像素格式。
參數:
	desiredSize			以與設備無關的像素表示的新呈現器目標的所需大小。
	bitmapRenderTarget 	此方法返回時將包含一個指針的地址,該指針指向一個新位圖呈器現目標。此參數以未初始化的狀態傳遞。
返回值:HRESULT 如果該方法成功,則返回 S_OK。 否則,將返回錯誤代碼。HRESULT.

我們還要用到位圖畫刷ID2D1BitmapBrush,這個接口不用特殊介紹,我們介紹一下創建畫刷時需要的一個結構體,這個結構體用來描述 ID2D1BitmapBrush 的擴展模式和內插模式:

struct D2D1_BITMAP_BRUSH_PROPERTIES {
  D2D1_EXTEND_MODE               extendModeX;		//一個值,用來描述畫筆對超過其位圖范圍的區域進行水平平鋪的方式。
  D2D1_EXTEND_MODE               extendModeY;		//一個值,用來描述畫筆對超過其位圖范圍的區域進行垂直平鋪的方式。
  D2D1_BITMAP_INTERPOLATION_MODE interpolationMode;	//一個值,用來指定對位圖進行縮放或旋轉時使用的內插方式。
};

這個結構體前兩個成員的類型都是枚舉類型D2D1_EXTEND_MODE,它指定畫筆如何在其常規內容區域之外的區域進行繪制。如下:

typedef enum  {
  D2D1_EXTEND_MODE_CLAMP    = 0,//在常規內容區域以外的所有區域重復畫筆內容邊上的像素。
  D2D1_EXTEND_MODE_WRAP     = 1,//重復畫筆的內容。
  D2D1_EXTEND_MODE_MIRROR   = 2 //與 D2D1_EXTEND_MODE_WRAP 相同,但畫筆的內容將翻轉顯示。(畫筆的常規內容在繪制時不會進行轉換。)
} D2D1_EXTEND_MODE;

還有一個枚舉類型D2D1_BITMAP_INTERPOLATION_MODE,用來指定縮放或旋轉圖像時所使用的算法。如下:

typedef enum  {
  D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR   = 0,//使用離當前呈現像素最近的位圖像素的精確顏色。
  D2D1_BITMAP_INTERPOLATION_MODE_LINEAR             = 1 //從離當前呈現像素最近的四個位圖像素來內插顏色。
} D2D1_BITMAP_INTERPOLATION_MODE;

要拉伸圖像,原始圖像中的每個像素都必須映射到較大的圖像中的一組像素。要壓縮圖像,原始圖像中的一組像素必須映射到較小的圖像中的單個像素。我們這里用不到這些,就不過多介紹了。

 

到這里我們所需要的API接口就介紹完了。

 

2.2 思路介紹

介紹完需要的API接口之后,我們來看一下實現網格繪制的思路:

  a.創建一個網格粒度大小的ID2D1BitmapRenderTarget;

  b.在ID2D1BitmapRenderTarget上繪制兩條直線,分別在ID2D1BitmapRenderTarget的左邊和上邊;

  c.從ID2D1BitmapRenderTarget創建位圖;

  d.指定畫刷的的屬性,讓它對超過位圖畫刷范圍外的區域進行重復繪制。

也就是說在一個位圖畫刷上保存一個網格,並指定畫刷繪制的時候對范圍外的區域進行重復繪制,如下圖所示:

 

2.3 代碼實現

這是繪制網格的代碼部分:

// 網格粒度
float meshLength = 20.f;

// 創建bitmapRT
if (SUCCEEDED(hr))
{
	hr = m_pRT->CreateCompatibleRenderTarget(
	D2D1::SizeF(meshLength,meshLength),
	&m_pBitmapRT);
}

// 創建bitmapBrush
if (SUCCEEDED(hr))
{
	m_pBitmapRT->BeginDraw();
	m_pBitmapRT->DrawLine(D2D1::Point2F(0,0),D2D1::Point2F(meshLength,0),m_pBrush);
	m_pBitmapRT->DrawLine(D2D1::Point2F(0,0),D2D1::Point2F(0,meshLength),m_pBrush);
	m_pBitmapRT->EndDraw();

	m_pBitmapRT->GetBitmap(&m_pBitmap);

	D2D1_BITMAP_BRUSH_PROPERTIES bbp;
	bbp.extendModeX = D2D1_EXTEND_MODE_WRAP;
	bbp.extendModeY = D2D1_EXTEND_MODE_WRAP;
	bbp.interpolationMode = D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
	m_pRT->CreateBitmapBrush(m_pBitmap, bbp, &m_pBitmapBrush);
}

上面的代碼中先創建了bitmapRT,然后在bitmapRT上繪制一個網格的兩個邊,再從bitmapRT上獲取位圖,根據位圖創建位圖畫刷。

下面是繪制部分的代碼:

RECT clientRect;
GetClientRect(m_hwnd, &clientRect);
D2D1_RECT_F rc = D2D1::RectF(clientRect.left,clientRect.top,clientRect.right,clientRect.bottom);

// 開始繪制
m_pRT->BeginDraw();

m_pRT->SetTransform(D2D1::Matrix3x2F::Identity());
m_pRT->Clear(D2D1::ColorF(D2D1::ColorF::Black));

// 繪制
m_pRT->FillRectangle(
	rc,
	m_pBitmapBrush);
		
// 結束繪制
hr = m_pRT->EndDraw();

 

繪制的演示效果如下圖:

在這里完整代碼代碼就不貼出了,有興趣的朋友可以點擊此處下載Demo源碼,Demo源碼是Direct2DTests目錄下的D2DMesh文件。

 

三、結語

這樣我們就成功地利用Direct2D繪制出了網格,希望可以幫到大家。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM