C#使用原生的Directx和OpenGL繪圖的方法

由于項目需要做一些圖形展示,所以就想到了使用Directx和OpenGL來繪圖,但項目準(zhǔn)備使用C#來開發(fā)(大家比較熟悉C#),在網(wǎng)上看了相關(guān)的資料,有一些第三方的控件可用,試用了下,一運行就占了幾百M的內(nèi)存,而且也不知道是否穩(wěn)定,教程也少,還不如直接使用原生的。在網(wǎng)上看的Directx和OpenGL的教程基本上都是C/C++的,找了很久也就找到相關(guān)介紹,只能自己研究下。

我以前做過C#和C++混合語言編程相關(guān)的東西,在C++實現(xiàn)一些C#不好實現(xiàn)的功能,C#動態(tài)調(diào)用DLL文件,所以也想到了用C++的代碼來控制Winform控件的繪畫,這樣就可實現(xiàn)用Direct和OpenGL在Winform的控件上繪畫了。

由于我對Direct和OpenGL都不熟悉,沒有這方面的編程經(jīng)驗,只能去瞎折騰,下面分別說說最近在Directx和OpenGL怎么試驗的。

Directx:

之前沒學(xué)過Directx,拿了同學(xué)的代碼來看,也是霧里看花啊,不過有一點啟示了我,在初始化的時候,要傳入一個句柄去創(chuàng)建設(shè)備(CreateDevice),通常都是傳入窗口的設(shè)備,我想如果傳入一個控件的句柄,那所有的繪畫都將在這個控件上實現(xiàn),因為控件也是繼承自Window的。而Winform的控件在底層的實現(xiàn)應(yīng)該和WIN32是一樣的。這樣的話只要把Winform的控件的句柄傳入C++代碼進(jìn)行初始化,那么繪畫的結(jié)果將顯示在這個控件上。結(jié)果一試,還真行。關(guān)鍵代碼如下:

復(fù)制代碼代碼如下:

extern "C" _declspec(dllexport) HRESULT InitD3D( HWND hWnd );

extern "C" _declspec(dllexport) VOID Render();

在InitD3D傳入控件的句柄進(jìn)行初始化,C#再調(diào)用Render進(jìn)行繪畫,以下是C#代碼:

復(fù)制代碼代碼如下:

HWND handle = this.button1.Handle;

InitD3D(handle);

private void Draw()

? {

???????? for (; ; )

??????????? {

??????????????? Render();

??????????? }

}

效果圖:

OpenGL:

查看了OpenGL的相關(guān)教程(推薦http://www.yakergong.net/nehe/),OpenGL是通過RC來執(zhí)行的,創(chuàng)建RC時就必須指定一個DC,還要設(shè)置DC的像素格式。每個線程有且只能擁有一個RC。

如果在初始化OpenGL的繪畫環(huán)境時傳入一個Winform的控件句柄,再通過這個句柄取到HDC,就可使用這個HDC來創(chuàng)建RC,這樣OpenGL的繪畫環(huán)境就準(zhǔn)備好了,并且這個RC關(guān)聯(lián)到Winform的控件上。

在給制前,先為當(dāng)前線程選擇RC(之前通過HDC創(chuàng)建的),再進(jìn)行繪制,這樣繪制的結(jié)果將顯示在這個Winform控件上。

關(guān)鍵代碼如下:

C++:

復(fù)制代碼代碼如下:

extern "C" _declspec(dllexport) void Init( HWND hWnd);

extern "C" _declspec(dllexport) void Render();

void Init(HWND hWnd)

{

int PixelFormat;

int bits = 16;

hDC = GetDC(hWnd);

static? PIXELFORMATDESCRIPTOR pfd=?????????? // pfd Tells Windows How We Want Things To Be

{

sizeof(PIXELFORMATDESCRIPTOR),????????????? // Size Of This Pixel Format Descriptor

1,????????????????????????????????????????????????????????    // Version Number

PFD_DRAW_TO_WINDOW |??????????????????????? // Format Must Support Window

PFD_SUPPORT_OPENGL |????????????????????????? // Format Must Support OpenGL

PFD_DOUBLEBUFFER,?????????????????????????????? // Must Support Double Buffering

PFD_TYPE_RGBA,???????????????????????????????????? // Request An RGBA Format

bits,??????????????????????????????????????????????????????? // Select Our Color Depth

0, 0, 0, 0, 0, 0,?????????????????????????????????????? // Color Bits Ignored

0,???????????????????????????????????????????????????????? // No Alpha Buffer

0,???????????????????????????????????????????????????????? // Shift Bit Ignored

0,??????????????????????????????????????????????????????? // No Accumulation Buffer

0, 0, 0, 0,?????????????????????????????????????????? // Accumulation Bits Ignored

16,??????????????????????????????????????????????????? // 16Bit Z-Buffer (Depth Buffer)

0,???????????????????????????????????????????????????? // No Stencil Buffer

0,???????????????????????????????????????????????????? // No Auxiliary Buffer

PFD_MAIN_PLANE,???????????????????????? // Main Drawing Layer

0,????????????????????????????????????????????????? // Reserved

0, 0, 0????????????????????????????????????????? // Layer Masks Ignored

};

PixelFormat=ChoosePixelFormat(hDC,&pfd);

SetPixelFormat(hDC,PixelFormat,&pfd);

hRC=wglCreateContext(hDC);

}

void Render()

{

wglMakeCurrent(hDC, hRC);

draw();

SwapBuffers(hDC);

wglMakeCurrent(NULL, NULL);

}

C#:

復(fù)制代碼代碼如下:

Init(this.pictureBox1.Handle);

//開始繪制

var timer = new System.Timers.Timer();

timer.Interval = 100;

timer.Elapsed += (tsender, te) =>

{

Render();

};

timer.AutoReset = true;

timer.Enabled = true;

效果圖:

WPF:WPF的控件沒有句柄,但是可以換個思路,把繪畫代碼封裝在Winform控件上,在WPF使用自定義的Winform控件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容