C_Sharp 板


LINE

又研究出一些心得分享 https://dl.dropboxusercontent.com/u/61164954/project/RenderingTest/index.html C#一般開發模式風格並不像是C++開發視窗程式需要動到很多底層的WIN32 API, 或是太過於複雜跟系統有關的觀念,但發展到一個需求,如果一些怪怪的需求多了, C#一定會有無法勝任的地方,不然就是靠wrapper.不然就是靠pinvoke, 去存取C/CC++ dll或是win32 api. 特別提到一塊是高速rendering需求,C#用的GDI+是無法勝任的... 尤其在畫面開始慢慢變得大張後. 這時候很多人也許就開始會想借重opengl或是directx去處理, 但還有一個東西叫GDI,這東西一定得靠WIN32 API去做,用pinvoke, 如果你的需求是2d影像,快速播放,而不像是開發遊戲還需要用到一些功能特性, 後來我覺得gdi比opengl或是directx好用,只是看你的用法. 不過像這種native api的使用其實跟c#沒有真正的直接關係就是, 反來會是mfc之類的開發比較需要. 這邊說到gdi(不是c#原來用的gdi+),一般c#用gdi,首先就是一個BitMap物件, 建立Graphics , 建立GDI物件, 到最後顯示 public static void DrawImage(ref Graphics grDest, ref Bitmap grSrcBitmap) { grSrc = Graphics.FromImage(grSrcBitmap); hdcDest = grDest.GetHdc(); hdcSrc = grSrc.GetHdc(); hBitmap = grSrcBitmap.GetHbitmap(); hOldObject = SelectObject(hdcSrc, hBitmap); BitBlt(hdcDest, 0, 0, grSrcBitmap.Width, grSrcBitmap.Height, hdcSrc, 0, 0, 0x00CC0020U); if (hOldObject != IntPtr.Zero) SelectObject(hdcSrc, hOldObject); if (hBitmap != IntPtr.Zero) DeleteObject(hBitmap); if (hdcDest != IntPtr.Zero) grDest.ReleaseHdc(hdcDest); if (hdcSrc != IntPtr.Zero) grSrc.ReleaseHdc(hdcSrc); } 這中間有好幾步驟虛要新的記憶體,產生物件,到釋放..... 步驟多又慢 (但即使如此還是比gdi+強...) 一直覺得這種複製建立的過程不太合理....BitMap也慢... 所以就直接把 bitmap 資料寫入到 BitMap的記憶體中, 少了好幾個步驟 public unsafe static void DrawImageHighSpeed() { SetDIBits(hdcDest, hBitmap, 0, (uint)h, data_ptr, ref info, DIB_RGB_COLORS); BitBlt(hdcDest, 0, 0, w , h , hdcSrc, 0, 0, 0x00CC0020U); } 但要用這方式虛要先做一個初始化,當確定不再坐rendering工作後, 也得自己釋放一下記憶體(c#管不到它自己以外的部分...) public unsafe static void initHighSpeed(ref Graphics _grDest, int width, int height, uint[] data) { w = width; h = height; _Bitmap = new Bitmap(width, height); grSrc = Graphics.FromImage(_Bitmap); grDest = _grDest; hdcDest = grDest.GetHdc(); hdcSrc = grSrc.GetHdc(); hBitmap = _Bitmap.GetHbitmap(); hOldObject = SelectObject(hdcSrc, hBitmap); info = new BITMAPINFO(); info.bmiHeader = new BITMAPINFOHEADER(); info.bmiHeader.biSize = (uint)Marshal.SizeOf(info.bmiHeader); info.bmiHeader.biWidth = w; info.bmiHeader.biHeight = h; info.bmiHeader.biPlanes = 1; info.bmiHeader.biBitCount = 32; info.bmiHeader.biCompression = BitmapCompressionMode.BI_RGB; info.bmiHeader.biSizeImage = (uint)(w * h * 4); fixed (uint* dptr = data) { data_ptr = (IntPtr)dptr;} } public unsafe static void freeHighSpeed() { if (hOldObject != IntPtr.Zero) SelectObject(hdcSrc, hOldObject); if (hBitmap != IntPtr.Zero) DeleteObject(hBitmap); if (hdcDest != IntPtr.Zero) grDest.ReleaseHdc(hdcDest); if (hdcSrc != IntPtr.Zero) grSrc.ReleaseHdc(hdcSrc); try { _Bitmap.Dispose(); } catch { } } 最後再進化一次.... 有沒有辦法直接把自己的data array寫入到圖型裝置記憶體? 有的...而且是最快的方式 public unsafe static void DrawImageHighSpeedtoDevice() { SetDIBitsToDevice(hdcDest, 0, 0, (uint)w, (uint)h, 0, 0, 0, (uint)h, data_ptr, ref info, DIB_RGB_COLORS); } 一個步驟不拖泥帶水...(不過這種方式開始得做一點初始化工作,但只有第一次需要 要更新畫面讀寫一下自己的data arry call SetDIBitsToDevice 重刷一下就好.... 這rendering的模式破1000fps以上....(data array已經準備號,單純刷畫面的速度) 800*600畫面下可以刷的速度 100內 GDI+ 200~300fps 從c#BitMap物件 900~1000fps data array刷到bitmap記憶體中然後rendering 1500~1600fps 直接把data array刷到裝置記憶體 1024*768狀況下 gdi+剩下 40多fps ... 直接把data array刷到裝置記憶體可達到近900fps 最慢的從c#BitMap物件 有150fps左右 data array刷到bitmap記憶體中然後rendering 550fps左右 如果你的需要只是一次又一次產生簡單的2d影像畫面刷上去, 沒牽涉到像是sprite的控制遊戲需求,這就夠好用了.... 重點是省包directx相關wrapper,精簡扼要... (directx使用非常麻煩...而且如果單這種狀況來說directx佔不到便宜) --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 60.248.56.181
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_Sharp/M.1445504557.A.837.html ※ 編輯: erspicu (60.248.56.181), 10/22/2015 17:13:41
1F:推 stu87616: 推 10/23 12:51
2F:推 Litfal: 有種回到VB6時代的感覺ww 10/23 12:51
3F:→ Litfal: 主要還是簡單影像GDI+足矣,複雜影像:需要繪製多個物件/ 10/23 12:54
4F:推 Litfal: 坐標系轉換/遮罩(這個我記得GDI有)/一些resize算法(雖然 10/23 12:58
5F:→ Litfal: GDI+也不強)回去用GDI重新寫過,應該會搞死人XD 10/23 12:58
6F:推 zel: 推 10/23 21:29
7F:推 dreamnook: 推 10/24 10:44
8F:推 name2name2: 推 10/25 21:07
9F:推 Harper34: 現在還有其他選擇WPF 10/25 21:59
10F:推 KanoLoa: 大推 10/25 22:53
11F:推 frank6780: 推 10/29 03:09
12F:推 sunneo: great 10/13 13:23







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Gossiping站內搜尋

TOP