遊戲開發學堂:2D模式下的alpha混合(轉)
遊戲開發學堂:2D模式下的alpha混合(轉)[@more@] alpha混合是一種常見的顏色處理,是把源點的顏色值和目標點的顏色值按照一定的演算法進行運算,得到一個透明的效果. alpha混合的基本公式: result = ALPHA * srcPixel + ( 1 - ALPHA ) * destPixel 其中: ALPHA:0到1之間的一個數,表示混合時的透明程度,為0的時候結果就是目標點的原值,為1的時候是源點的原值 srcPixel:源點顏色值 destPixel:目標點顏色值 result:結果,將會賦給目標點 這個是最基本的公式,但是我們在寫程式的時候可以做一些最佳化.公式裡面有兩個乘號,乘法消耗的時鐘週期要多得多,我們要想方法去掉它.做一個變換. alpha混合的改進公式1: result = ALPHA * ( srcPixel - destPixel ) + destPixel 然後我們也看到ALPHA是一個浮點數,我們可以把它轉換成整數,因為一種顏色最多佔8bit,所以ALPHA的值也最多到256,那我們把ALPHA的值先乘上256,然後運算的時候再除以256就得到下面的公式: alpha混合的改進公式2: result = ALPHA * ( srcPixel - destPixel )/256 + destPixel 其中: ALPHA是一個0到256的數 有了這個公式,我們的第一份code也就出來了. alpha混合程式碼1: //16位565格式 i = height;?// 混合矩形高度 do { j = width; ?// 混合矩形寬度 do { sTemp = *((WORD*)lpSour);// 源點顏色值,16位--WORD型別,(lpSour和lpDest都是BYTE*) if ( sTemp != sColorKey ) ? // 不是colorkey { dTemp = *((WORD*)lpDest); // 目標點 sb = sTemp & 0x1f; ? // 藍色分量 db = dTemp & 0x1f; sg = (sTemp >> 5) & 0x3f; // 綠色分量 dg = (dTemp >> 5) & 0x3f; sr = (sTemp >> 11) & 0x1f;// 紅色分量 dr = (dTemp >> 11) & 0x1f; blue = (ALPHA * (sb - db) >> 8) + db;// 按照改進公式2運算三個分量 green = (ALPHA * (sg - dg) >> 8) + dg; red = (ALPHA * (sr - dr) >> 8) + dr; *((WORD*)lpDest) = blue | (green << 5) | (red << 11); // 565格式生成結果並賦給目標點 } lpDest += 2; // 下一個點,16位佔2個位元組 lpSour += 2; }while ( --j > 0 ); lpDest += dPadding; // 下一行 lpSour += sPadding; }while (--i > 0); 到此alpha混合也就差不多了,但是不得不說說MMX版本的alpha混合.上面的方式進行alpha混合的時候效率不高,而MMX使用64位的MMX暫存器,一次操作8(byte)/4(word)/2(dword)個資料單元,也就是所謂的"單指令多資料SIMD結構".這樣我們就可以一次處理幾個點.下面的程式碼是寫給16位565模式的. 因為是16位模式,那麼我們可以一次處理4個點,但是因為編譯器不會主動的生成MMX程式碼,所以我們使用inline asm的方式進行.因為我們的點是定義成無符號的word型,不能出現負數,所以我們要修改我們的alpha混合公式: alpha混合mmx版公式: result = ( ALPHA * ( ( srcPixel+ 64 ) - destPixel) ) / 256 + destPixel- (ALPHA / 4) 這個公式是這樣來的:因為16位模式下每個點的分量最多6位,換成10進位制也就是63,那麼我們在srcPixel上面加上64然後再減去destPixel,就不會出現負數了.加了之後當然要減回來,那這個公式就是這樣的: result = ( ALPHA * ( ( srcPixel+ 64 -64) - destPixel) ) / 256 + destPixel 然後把紫色的-64提出來也就得到了上面的公式了. 好了我們可以動手寫code了,看起來的code應該如下: alpha混合code2: MASKRED = 0xF800F800F800F800;?// 三種顏色的掩碼的64位擴充套件 MASKGREEN = 0x07E007E007E007E0; MASKBLUE = 0x001F001F001F001F; __int64 ALPHA64, COLORKEY64, ALPHABY4; __int64 MASKRED, MASKGREEN, MASKBLUE; __int64 ADD64 = 0x0040004000400040; _asm { movd mm2,ALPHA // ALPHA值放入mm2 punpcklwd mm2,mm2 // mm2 -> 0000 0000 00aa 00aa punpckldq mm2,mm2 // mm2 - 00aa 00aa 00aa 00aa,生成alpha的64位擴充套件 movq ALPHA64,mm2 ?// 結果放入到 ALPHA64 psrlw mm2, 2 ?// 每個ALPHA 除以4 movq ALPHABY4,mm2 // 放到 ALPHABY4 movd mm4,ColorKey // ColorKey -> mm4 punpcklwd mm4,mm4 // mm4 -> 0000 0000 cccc cccc punpckldq mm4,mm4 // mm4 -> cccc cccc cccc cccc,生成Colorkey的64位擴充套件 movq COLORKEY64,mm4 ; // 結果放到 COLORKEY64 } i = height; do { j = width/4; // 兩行寫在一起表示假設他們同時在uv管道里面執行 _asm { push edi ? // 儲存edi和esi push esi mov edi,lpDest // edi指向dest緩衝區 mov esi,lpSour; // esi指向sour緩衝區 SPAN_RUN_565: movq mm7,[edi] // dest的8 bytes 到 mm7--4個dest點到mm7 movq mm6,[esi] // sour的8 bytes 到 mm6--4個sour點到mm6 movq mm2,ALPHA64 ? // ALPHA64 -> mm2 movq mm0,mm7 ? // 紅色 - 複製 mm7 到 mm0,目標點 pand mm0,MASKRED ? // 紅色 - 與上紅色掩碼 -> [0r00 0r00 0r00 0r00],目標點 movq mm1,mm6 ? // 紅色 - 複製 mm6 到 mm1,源點 pand mm1,MASKRED ? // 紅色 - 與上紅色掩碼 -> [0r00 0r00 0r00 0r00],源點 psrlw mm0,11 ? // 紅色 - 右移 11 位 -> [000r 000r 000r 000r],目標點 movq mm5,mm7 ? // 綠色 - 複製 mm7 到 mm5,目標點 psrlw mm1,11 ? // 紅色 - 右移 11 位 -> [000r 000r 000r 000r],源點 paddw mm1, ADD64// 紅色 - 源點加上64 movq mm3,mm6 ? // 綠色 - 複製 mm6 到 mm3,源點 psubsw mm1,mm0 // 紅色 - 減去目標點 pand mm5,MASKGREEN // 綠色 - 與上綠色掩碼 -> [00g0 00g0 00g0 00g0],目標點 pmullw mm1,mm2 // 紅色 - 乘以ALPHA pand mm3,MASKGREEN // 綠色 - 與上綠色掩碼 -> [00g0 00g0 00g0 00g0],源點 psrlw mm5,5 // 紅色 - 右移 5 位 -> [000g 000g 000g 000g],目標點 psrlw mm3,5 // 紅色 - 右移 5 位 -> [000g 000g 000g 000g],源點 nop // 空操作 - 指令配對 paddw mm3, ADD64// 綠色 - 源點加上64 psrlw mm1,8 // 紅色 - 除以 256 (右移8位) psubsw mm3,mm5 // 綠色 - 減去目標點 pmullw mm3,mm2 // 綠色 - 乘以ALPHA paddw mm1,mm0 ?// 紅色 - 加上目標點 psubw mm1, ALPHABY4 // 紅色 - 減去alpha的四分之一 psllw mm1,11 ? // 紅色 - 左移11位,還原[0r00 0r00 0r00 0r00] movq mm0,mm7 ? // 藍色 - 複製 mm7 到 mm0,目標點 pand mm0, MASKBLUE // 藍色 - 與上藍色掩碼 -> [000b 000b 000b 000b],目標點 psrlw mm3,8 // 綠色 - 除以 256 (右移8位) paddw mm3,mm5 ?// 綠色 - 加上目標點 movq mm4, mm6 ?// 藍色 - 複製 mm6 到 mm4,源點 psubw mm3, ALPHABY4 // 綠色 - 減去alpha的四分之一 pand mm4, MASKBLUE?// 藍色 - 與上藍色掩碼 -> [000b 000b 000b 000b],源點 psllw mm3,5 // 綠色 - 左移5位,還原[00g0 00g0 00g0 00g0] paddw mm4, ADD64// 藍色 - 加上64 psubsw mm4,mm0 // 藍色 - 減去目標點 por mm1,mm3 // 組合紅色和綠色分量 pmullw mm4,mm2 // 藍色 - 乘以alpha movq mm3,COLORKEY64 // COLORKEY64 -> mm3 psrlw mm4,8 // 藍色 - 除以256(右移8位) pcmpeqw mm3,mm6 // 比較 colorKey 和原來的sour,如果相等,則相應的mm3的位為1 paddw mm4,mm0 ?// 藍色 - 加上目標點 movq mm5,mm3 ? // mm3 -> mm5 psubw mm4, ALPHABY4 // 藍色 - 減去alpha的四分之一 por mm1,mm4 // 合成3種顏色 pand mm5,mm7 ? // mm5與上目標點 - 取出源點是colorkey的點的目標點的顏色值 pandn mm3,mm1 ?// mm3取反然後與上mm1,mm1放的是運算結果,這樣就把源點是colorkey的點的結果清0 por mm3,mm5 // mm3或上mm5,一個是源點是colorkey的點的目標點一個是源點不是colorkey的結果,兩個 ? ? ? ? ? ? ? ? ? ? ? ? // 對立位都是0,這樣就組合乘一個結果點 movq [edi],mm3 ? ? ? // 最終結果放回目標點 add edi,8 ?// 下一個目標點,一次64 bits = 8 bytes mov eax,dword ptr [j] ?// j -> eax add esi,8 ?// 下一個源點 sub eax,1 ?// j-- mov dword ptr [lpDest], edi // 儲存lpDest mov dword ptr [j],eax ?// 賦回 j mov dword ptr [lpSour], esi // 儲存lpSour cmp eax,0 ?// 這一行是不是處理完了 jg SPAN_RUN_565 // 下一個點 emms ? // 清除mmx暫存器 pop es
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-952249/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 64K色模式下的快速Alpha混合演算法(轉)模式演算法
- 16位Alpha混合的簡單演算法 (轉)演算法
- 遊戲開發學堂:關於遊戲性的概念和實物(轉)遊戲開發
- 遊戲開發學堂:Direct3D入門之我見(轉)遊戲開發3D
- Windows 2d遊戲開發Windows遊戲開發
- 利用MMX最佳化64K色Alpha混合演算法(轉)演算法
- 混合使用Direct3D立即模式和保留模式(轉)3D模式
- 菜鳥學堂之破解Sessioncookie的方法(轉)SessionCookie
- 設計模式學習筆記(二)工廠模式、模板模式和策略模式的混合使用設計模式筆記
- Photoshop圖層混合模式計算公式大全(轉)模式公式
- Unity 2D遊戲開發快速入門第1章建立一個簡單的2D遊戲Unity遊戲開發
- Unity3D 2D實戰遊戲開發Unity3D遊戲開發
- 思科Dave West:世界未來必將轉向混合模式模式
- C#泡泡堂遊戲開發全套系列C#遊戲開發
- Alpha上安裝Linux(轉)Linux
- 帶你認識Photoshop的混合模式模式
- dui框架開發系列:32位和565BMP的ALPHA混合和資源打包UI框架
- Unity 4.x 2D遊戲開發基礎教程Unity遊戲開發
- 駭客學堂:常用的九種網路攻擊方法(轉)
- 學術派 |用深度學習實現2D到3D的轉換深度學習3D
- Unity 2D遊戲開發快速入門(內部資料)Unity遊戲開發
- 新手學堂:防火牆在網路中的功能和作用(轉)防火牆
- 玩轉混合加密加密
- 混合式 App 開發模式下的熱更新技術方案,你知道多少?APP模式
- MAC下嘗試PHP7 alpha版本的安裝MacPHP
- 新手學堂:防火牆概念與訪問控制列表(轉)防火牆
- 強大的CSS:濾鏡和混合模式處理的圖片如何上傳下載?CSS模式
- Unity 4.x 2D遊戲開發基礎教程 大學霸Unity遊戲開發
- Unity和Cocos2D在2D遊戲開發上的對比Unity遊戲開發
- Shader 中的顏色混合模式(Blend Mode)模式
- 不可思議的混合模式 background-blend-mode模式
- CSS3 2D轉換CSSS3
- 硬核模式下的中小遊戲開發團隊,如何挺過今年冬天?模式遊戲開發
- 雲學堂培訓
- 活下來的 VR 遊戲開發者VR遊戲開發
- Reactv16.7.0-alpha.2 Hooks學習ReactHook
- 遊戲開發學院:小談遊戲中的各種平衡(轉)遊戲開發
- 《Unity 2D與3D手機遊戲開發實戰》簡介Unity3D遊戲開發