程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 真彩色轉成高彩色的快速算法

真彩色轉成高彩色的快速算法

編輯:關於VC++

為什麼要實時轉換顏色深度?

通常, 2D 游戲中的位圖, 無論在外存中按什麼顏色深度存放, 加栽後都被轉換成了需要的顏色深度. 我們不太注意顏色深度轉換說需要的時間.

但是, 現在不同了. 雲風未來的計劃中, 最重要的一項是制作一個超級 2D 引擎. 將支持 Voxel 物體和實時光線處理這樣的特性, 而且在光線處理中, 32 級的光線亮度級別也遠遠不夠, 所以, 未來的 2D 游戲的發展趨勢應該是采用真彩色, 至少是在內部運算時使用. 在某些場合下, 我們可能需要做 15/16bit 高彩色的輸出, 所以有必要找到更快的方法實時處理.

下面, 我們對此做一些探討, 雖然顯卡可以支持 15 或 16 bit 色中的一種, 但這裡全部用 16bit 色舉例:

先來看看 C 版本:

red=(truecolor>>8)&0xf800;
green=(truecolor>>5)&0x7e0;
blue=(truecolor>>3)&0x1f;
hicolor=red|green|blue;
這樣當然是相當慢的, 所以我們還是要借助匯編. 而匯編能極大的優化它: lodsd    ;RRRRRRRR GGGGGGGG BBBBBBBB
shr eax,3    ;000RRRRR RRRGGGGG GGGBBBBB
shl al,2    ;000RRRRR RRRGGGGG GBBBBBxx
shl ax,3    ;000RRRRR GGGGGGBBB BBxxxxx
dec esi
shr eax,5    ;00000000 RRRRRGGG GGGBBBBB
stosw
是不是精簡了很多? 但不幸的是, 雖然看起來很簡潔, 但由於大量使用部分寄存器, 對流水線的沖擊很大. 代碼幾乎把流水線的效率減到了最低. 優化方案很多, 我們可以在一次循環裡處理兩個點, 分別使用 eax 和 ebx, 然後交錯那些代碼; 又或者將上面代碼的後半部分改為查表, 相信都能提高速度. 但是下面我還想提出另一種方案, 采用 MMX 指令級: mm7=F800F800F800F800
mm6=FC00FC00FC00FC00
------------------------------
punpcklbw mm0,[red+edx]
;mm0=RRRRRRRR 00000000 RRRRRRRR 00000000 RRRRRRRR 00000000 RRRRRRRR 00000000
punpcklbw mm1,[green+edx]
;mm1=GGGGGGGG 00000000 GGGGGGGG 00000000 GGGGGGGG 00000000 GGGGGGGG 00000000
punpcklbw mm2,[blue+edx]
;mm2=BBBBBBBB 00000000 BBBBBBBB 00000000 BBBBBBBB 00000000 BBBBBBBB 00000000
pand mm0,mm7
;mm0=RRRRR000 00000000 RRRRR000 00000000 RRRRR000 00000000 RRRRR000 00000000
pand mm1,mm6
;mm1=GGGGGG00 00000000 GGGGGG00 00000000 GGGGGG00 00000000 GGGGGG00 00000000
psrlw mm2,11
;mm2=00000000 000BBBBB 00000000 000BBBBB 00000000 000BBBBB 00000000 000BBBBB
psrlw mm1,5
;mm1=00000GGG GGG00000 00000GGG GGG00000 00000GGG GGG00000 00000GGG GGG00000
por mm0,mm2
por mm0,mm1
;mm0=RRRRRGGG GGGBBBBB RRRRRGGG GGGBBBBB RRRRRGGG GGGBBBBB RRRRRGGG GGGBBBBB
movq [dis+edx*2],mm0
add edx,4
我們對 MMX 的運用是針對它的並行運算, 直接從 RGB888 格式利用並行處理變成 RGB565 似乎不可能, 但是, 如果我們將 RGB 三個色素分開存放, 就將其變為了可能. 可以同時讀入 4 個色素, 並行處理, 然後合並, 這樣便在一個循環內處理了 4 個點. 考慮到 CACHE 的效率, 最好不要將 RGB 三塊內存分的太開. 我的建議是, 位圖的每一行分成三個部分, 即為 Red 段, Green 段 和 Blue 段.

上面的方法都是可以繼續優化的, 本文旨在啟發朋友們的靈感, 找出更好的方法.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved