遊戲開發學堂: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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 硬核模式下的中小遊戲開發團隊,如何挺過今年冬天?模式遊戲開發
- 混合式 App 開發模式下的熱更新技術方案,你知道多少?APP模式
- 區塊鏈遊戲NFT遊戲開發DAPP模式定製區塊鏈遊戲開發APP模式
- 活下來的 VR 遊戲開發者VR遊戲開發
- Flutter 2.0 下混合開發淺析Flutter
- Alpha世代和Z世代:遊戲業的未來遊戲
- 打造獨立遊戲孵化新模式,騰訊遊戲學院助力遊戲多元發展遊戲模式
- 《Unity 2D與3D手機遊戲開發實戰》簡介Unity3D遊戲開發
- NFT遊戲鏈遊系統開發技術詳細丨NFT遊戲鏈遊DAPP開發原始碼模式遊戲APP原始碼模式
- 2D遊戲如何提升遊戲體驗? 2D關卡設計的六大正規化遊戲
- 鏈金莊園遊戲系統模式開發遊戲模式
- Demole NFT3D鏈遊系統開發模式(3D遊戲開發)3D模式遊戲開發
- 格鬥遊戲修羅場:鬼人和他的遊戲開發哲學遊戲開發
- win102004怎麼才能開啟遊戲模式_win10 2004開啟遊戲模式的方法Win10遊戲模式
- 遊戲開發入門(一)遊戲開發概述遊戲開發
- 微信小遊戲首度亮相 ChinaJoy,助力開發者玩轉小遊戲遊戲
- 影片時代下,蹭流量的遊戲開發者們遊戲開發
- Python遊戲開發工程師的起步,幾款遊戲開發案例Python遊戲開發工程師
- NFT鏈遊功能開發丨DAPP智慧合約遊戲系統技術開發模式APP遊戲模式
- 永春堂1300模式系統開發詳細介紹模式
- 【方向思考】中重度遊戲的輕量化開發與混合變現商業化案例分析遊戲
- NFT遊戲系統開發/遊戲開發技術遊戲開發
- Flutter - 混合開發Flutter
- Flutter混合開發Flutter
- 使用Laya引擎開發微信小遊戲(下)遊戲
- 【遊戲設計隨筆10】解密遊戲設計的30堂課遊戲設計解密
- hash雜湊競猜遊戲開發模式丨雜湊遊戲競猜玩法系統開發技術功能遊戲開發模式
- 專訪混合變現遊戲《兵多多》研發Mandrill VR 講述與Lion Studios合作開發的故事遊戲VRiOS
- HASH雜湊遊戲競猜模式系統開發方案(原始碼部署)區塊鏈雜湊遊戲開發多種遊戲介紹模式原始碼區塊鏈遊戲開發
- 遊戲開發中遊戲效能的最佳化遊戲開發
- 遊戲開發中不同時區下的時間問題遊戲開發
- 遊戲分類學丨吃雞遊戲的FPP和TPP模式之爭遊戲模式
- 泰山學堂選拔遊記
- 手遊開發者談遊戲營收模式設計中的最重要規則遊戲營收模式
- NFT元宇宙鏈遊/系統開發/NFT數藏/NFT鏈遊遊戲模式元宇宙遊戲模式
- 遊戲名人堂:“電子遊戲教父”席德·梅爾遊戲
- 波克城市:用“遊戲+”模式發揮遊戲的正向社會價值遊戲模式
- 遊戲開發雜記(三) 開發及學習過程中的體會遊戲開發
- 遊戲開發流程遊戲開發