WarmGUI(3-0) 對DirectX2D繪圖類封裝、多線程繪圖和優化處理(0)
這一篇距離上一篇整整隔了3個月,主要的原因大部分在學習繪圖和DirectX2D的用法,學習C++,學習各種東西,另外部分原因是工作忙,不過這是借口。我學習DirectX2D的過程并不很愉快,經常看到不理解的古怪的行為,這可能是我沒有開發過圖形界面,現在把我學習到的總結出來,請高人們指正。關于繪圖方法應該有很很話題可以討論,第0篇只是簡單把基礎的封裝類作個說明,下一篇開始討論多線程繪圖和優化的一些方法作個鋪墊。我用的平臺是Win7+VC2010+SDK7.0a+DirectX June 2010
1.CDxFactorys對工廠封裝
首先用CDxFactorys對幾個工廠作個封裝,他的工作有:1 初始化的時候生成ID2D1Factory,IWICImagingFactory,IDWriteFactory的實例。
2.創建ID2D1HwndRenderTarget
3.獲取屏幕Dpi
CDxFactorys應是Sigleton模式,在程序的各處都可以訪問到唯一的實例。
這個類很平常,沒有太多可說的。
1 class WARMGUI_API CDxFactorys {
2 private:
3 CDxFactorys();
4 ~CDxFactorys();
5
6 public:
7 HRESULT CreateRenderTarget(HWND hwnd, ID2D1HwndRenderTarget ** pHwndRenderTarget);
8 ID2D1Factory* GetD2DFactory();
9 IWICImagingFactory* GetImgFactory();
10 IDWriteFactory* GetDWriteFactory();
11
12 HRESULT InitDxFactory();
13 void ReleaseResource();
14
15 static CDxFactorys * GetInstance();
16 public:
17 float m_dpiScaleX;
18 float m_dpiScaleY;
19
20 protected:
21 ID2D1Factory * m_pD2DFactory;
22 IWICImagingFactory * m_pImgFactory;
23 IDWriteFactory * m_pDWriteFactory;
24 };
2 private:
3 CDxFactorys();
4 ~CDxFactorys();
5
6 public:
7 HRESULT CreateRenderTarget(HWND hwnd, ID2D1HwndRenderTarget ** pHwndRenderTarget);
8 ID2D1Factory* GetD2DFactory();
9 IWICImagingFactory* GetImgFactory();
10 IDWriteFactory* GetDWriteFactory();
11
12 HRESULT InitDxFactory();
13 void ReleaseResource();
14
15 static CDxFactorys * GetInstance();
16 public:
17 float m_dpiScaleX;
18 float m_dpiScaleY;
19
20 protected:
21 ID2D1Factory * m_pD2DFactory;
22 IWICImagingFactory * m_pImgFactory;
23 IDWriteFactory * m_pDWriteFactory;
24 };
2. eArtist對繪圖函數作封裝
MFC用CDC類對繪制圖形和文本作封裝,我對應的類叫做藝術家,前面加個e表示電子藝術家eArtist,以區別傳統的作畫方法,以后會有特效動畫什么的,但目前我用到的,還僅僅是對繪圖和文字部分作的封裝.有幾點需要說明:1. 在Direct2D的文檔中特別強調繪圖資源在GPU上的時間開銷很大,因此建議盡量保留已有的繪圖資源,不要頻繁的創建和刪除繪圖資源。這寫在文檔Improving the Performance of Direct2D Applications中,因此上eArtist初始化如下的資源,直到應用程序退出再銷毀他們:一個Hwnd-RenderTarget和從他派生出來的Bitmap-RenderTarget,默認的畫刷SolidColorBrush,一個默認的StrokeStyle,以及默認的TextFormat等等。
2. Dx2D的繪圖要在ID2D1RenderTarget接口的BeginDraw()和EndDraw()之中完成,這兩個函數成對出現。如果想要在屏幕上看到圖形,則必須在Hwnd-RT的調用EndDraw之后,才會把結果呈現出來。
3. 坐標變換在繪圖過程中經常用到,最好在GPU上完成,必須小心的使用才能在正確的位置畫出圖形,我現在還經常被這個搞暈菜,這點在后面的例程中再討論。
4. 指定artist當前使用Hwnd-RT或Bitmap-RT,Bitmap-RT有點類似于以前常用的MemoryDC,這兩種RenderTarget各種用場,要參考DX2D的文檔。
5. 用CreateBitmap創建一個位圖,用CopyFromRenderTarget從當前的RenderTarget上拷貝到位圖,Again,創建資源是消耗GPU時間的,應盡量避免,創建之后盡可能多的使用CopyFromXXX函數
eArtist的代碼看起來是這樣的:
1 class WARMGUI_API eArtist
2 {
3 public:
4 eArtist(void);
5 ~eArtist(void);
6
7 ///初始化
8 void Init(HWND hwnd);
9 ///重新設置RenderTarget大小
10 inline HRESULT ResizeRenderTarget(int cx, int cy);
11
12 ///設定資源屬性
13 inline HRESULT SetStrokeStyle(
.);
14 inline HRESULT SetSolidColorBrush(
);
15 inline HRESULT SetTextFormat(
);
16
17 ///繪圖函數
18 inline void DrawText(
);
19 inline void DrawLine(
);
20 inline void DrawBitmap(
);
21 inline void DrawRectangle(
);
22 inline void FillRectangle(
);
23 inline void DrawEllipse(
);
24 inline void FillEllipse(
);
25
26 ///用默認的Bitmap-RenderTarget繪圖
27 inline void BeginBmpDraw(bool clear = false);
28 inline HRESULT EndBmpDraw();
29 ///用默認的Hwnd-RenderTarget繪圖
30 inline void BeginDraw(bool clear = false);
31 inline HRESULT EndDraw();
32
33 ///設定當前使用的RenderTarget為Hwnd-RenderTarget
34 inline void UsingHwndRT();
35 ///設定當前使用的RenderTarget為Bitmap-RenderTarget
36 inline void UsingBmpRT();
37 ///執行所有阻塞的繪圖動作
38 inline HRESULT Flush();
39
40 ///坐標變換
41 inline void SetTransform(MATRIX_2D_t* trans, bool bIsHwndRT = true);
42 inline void GetTransform(MATRIX_2D_t* trans, bool bIsHwndRT = true);
43
44 ///創建一個Bitmap
45 inline HRESULT CreateBitmap(ID2D1Bitmap** pBitmap, RECT& rect);
46 ///拷貝RenderTarget圖形到位圖
47 inline HRESULT CopyFromRenderTarget(ID2D1Bitmap* pBitmap, POINT pointDest, RECT rectSrc);
48
49
50 private:
51 ID2D1HwndRenderTarget* _pHwndRT;
52 ID2D1BitmapRenderTarget* _pDefaultBmpRT;
53 ID2D1SolidColorBrush* _pscBrush;
54 ID2D1StrokeStyle* _pStroke;
55 IDWriteTextFormat* _pTextFormat;
56 IDWriteTextLayout* _pTextLayout;
57 HWND _hwnd;
58 };
59
2 {
3 public:
4 eArtist(void);
5 ~eArtist(void);
6
7 ///初始化
8 void Init(HWND hwnd);
9 ///重新設置RenderTarget大小
10 inline HRESULT ResizeRenderTarget(int cx, int cy);
11
12 ///設定資源屬性
13 inline HRESULT SetStrokeStyle(

14 inline HRESULT SetSolidColorBrush(

15 inline HRESULT SetTextFormat(

16
17 ///繪圖函數
18 inline void DrawText(

19 inline void DrawLine(

20 inline void DrawBitmap(

21 inline void DrawRectangle(

22 inline void FillRectangle(

23 inline void DrawEllipse(

24 inline void FillEllipse(

25
26 ///用默認的Bitmap-RenderTarget繪圖
27 inline void BeginBmpDraw(bool clear = false);
28 inline HRESULT EndBmpDraw();
29 ///用默認的Hwnd-RenderTarget繪圖
30 inline void BeginDraw(bool clear = false);
31 inline HRESULT EndDraw();
32
33 ///設定當前使用的RenderTarget為Hwnd-RenderTarget
34 inline void UsingHwndRT();
35 ///設定當前使用的RenderTarget為Bitmap-RenderTarget
36 inline void UsingBmpRT();
37 ///執行所有阻塞的繪圖動作
38 inline HRESULT Flush();
39
40 ///坐標變換
41 inline void SetTransform(MATRIX_2D_t* trans, bool bIsHwndRT = true);
42 inline void GetTransform(MATRIX_2D_t* trans, bool bIsHwndRT = true);
43
44 ///創建一個Bitmap
45 inline HRESULT CreateBitmap(ID2D1Bitmap** pBitmap, RECT& rect);
46 ///拷貝RenderTarget圖形到位圖
47 inline HRESULT CopyFromRenderTarget(ID2D1Bitmap* pBitmap, POINT pointDest, RECT rectSrc);
48
49
50 private:
51 ID2D1HwndRenderTarget* _pHwndRT;
52 ID2D1BitmapRenderTarget* _pDefaultBmpRT;
53 ID2D1SolidColorBrush* _pscBrush;
54 ID2D1StrokeStyle* _pStroke;
55 IDWriteTextFormat* _pTextFormat;
56 IDWriteTextLayout* _pTextLayout;
57 HWND _hwnd;
58 };
59