• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
              顯然DirectDraw是Windows下寫2D圖形程序的最好選擇,雖然Direct3D也可以寫,但是沒DirectDraw簡單方便,特別對于初學者,一來就接觸那么多函數和參數總不是件愉快的事,所以我的文章主要結合我做的工作,談談DirectDraw編程中一些比較關鍵的技術,大多是我自己想出來的。我想先聲明,我的文章可以任意轉載,源代碼可以任意使用和修改。

              由于我是業余時間寫的文章,所以只能每次發表一篇,希望我的工作可以為大家的游戲增光添彩,同時我的文章主要面向有基本C++,DirectDraw,匯編和MMX編程經驗的朋友,如果你對這些了解不夠,請先學習一下再閱讀。也歡迎大家和我交流,我的QQ是35830152,EMAIL:EUHO@SINA.COM。

              作為第一篇,我想先談談Alpha混合的問題。這里32位色的圖形模式我們不考慮,因為技巧并不多,占用顯存和內存大,實際應用的也不多。我們把焦點放在16位色的模式上。我們把源點C2和Alpha通道點C1用Alpha混合,混合后得到點C,如果Alpha取0~1,公式如下:

            C = C2*Alpha + C1*(1-Alpha)

            如果Alpha取0~32,公式如下:

            C = (C2*Alpha + C1*(1-Alpha))>>5

            每個點由R,G,B 3個分量組成,所以上面的運算要分別對每個分量進行計算,如果整體計算,由于進位的關系我們會得到錯誤的結果。我們只考慮用得較多的565格式,即16位的顏色值為RRRRRGGGGGGBBBBB,555格式原理是一樣的。顯然我們每次處理一個點似乎只能按照“拆分-分別運算-拆分”來寫代碼,但是這樣是低效的,想想1024*768模式下運算一幀要進行多少次運算,一定快不到哪里去。

              Intel有段很長的代碼,我沒仔細看,也沒試驗,總覺得不太可靠(呵呵)。還看了GameRes上的一些相關文章,還是有值得參考的地方,就是覺得看了還是有些茫然。

              下面說我的算法,首先說明這個快速算法是針對每個Alpha值建立一個函數進行運算,如果在一個函數里實現任意Alpha的運算,一次只能運算2個點,而且匯編代碼是26行,而且有2次乘法,也用到了部分MMX加速。經過針對每一級Alpha的優化處理,每次處理4個點,代碼只要8行左右,移位代替了乘法運算,完全發揮了MMX的威力。我只做了17級變換,0級和17級不用做,1到15原理一樣,只有少少的不同,現在我舉例半透明的算法,其他大家可以自己實現,有問題也可以和我交流。

              Alpha運算中每個點3個色素,每個色素都要按上面那個公式運算,也就是每個色素要做2次乘法和一次加發,盡管可以變換一下不做浮點運算,但性能又能提高多少?我先講一下我算法的一個基本原理,即“任意分組移位”,意思就是把一個數中分為N組,每組位數并不要求相同,我們用一次移位和一次與運算就能做到好像是每個分組移位而互不影響的效果。比半透明下Alpha=0.5,換成移位就是>>1,我們先把C右移一位,然后AND 一個2進制的數0111101111101111(0x7BEF),就完成了3個色素同時*0.5的運算,簡單吧。

              代碼相信大家很容易就看懂了,大家把匯編部分和自己的程序結合就可以了,只要提供一些參數,比如頁面數據指針和長度高度等資料.下次我會發布帶Colorkey和Clip功能的代碼,同樣是MMX處理的,而且不用if(這會大大降低流水線的效率).以后還會介紹動態光源,灰度圖,動畫控制等高級主題,歡迎大家指導,由于水平和打字原因,可能文章中會有錯誤,請諒解.

            下面是任意Alpha的混合運算

            BOOL
            CAresMaterial::DrawAlpha( LONG X, LONG Y, LPRECT pRect, BYTE Alpha )
            {
                unsigned __int16 *pSrc, *pDest;
               
            unsigned __int32 A, PA;
               
            unsigned __int16 Width, Height;
               
            unsigned __int32 D1, D2;
               
            RECT Rect;

               
            A = Alpha & 0x1F;
               
            PA = 0x1F - A;
               
            Width = (unsigned __int16)(pRect->right - pRect->left + 1);
               
            Height = (unsigned __int16)(pRect->bottom - pRect->top + 1);
               
            D1 = (m_Desc.dwPitch - Width + 1)<<1 ;
               
            D2 = (m_Desc.pAres->GetScreenPitch() - Width + 1)<<1 ;
               
            SetRect( &Rect, X, Y, X+Width-1, Y+Height-1 );
               
            m_Desc.pAres->BackToDILayer( &Rect );
               
            pSrc = m_Desc.pData + pRect->top*m_Desc.dwPitch + pRect->left;
               
            pDest = m_Desc.pAres->GetDILayerData() + Y*m_Desc.pAres->GetScreenPitch() + X;


               
            __asm
               
            {
               
               
            mov esi,pSrc
               
               
            mov edi,pDest
               
               
            movd mm2,A
               
               
            movd mm3,PA

               
               
            mov cx,Height
               
               
            shl ecx,16
               
               
            mov cx,Width

               
            LOOPA:
               
               
            ror ecx,16
               
               
            dec cx
               
               
            jz DONE
               
               
            ror ecx,16

               
            LOOPB:
               
               
            dec cx
               
               
            jz NEXTLINE
               
               
            //Process one point
               
               
            mov ax,[esi]
               
               
            mov dx,ax
               
               
            shl eax,16
               
               
            mov ax,dx
               
               
            and eax,0x7E0F81F
               
               
            movd edx,mm2
               
               
            mul edx
               
               
            movd mm0,eax

               
               
            mov ax,[edi]
               
               
            mov dx,ax
               
               
            shl eax,16
               
               
            mov ax,dx
               
               
            and eax,0x7E0F81F
               
               
            movd edx,mm3
               
               
            mul edx
               
               
            movd mm1,eax

               
               
            paddd mm0,mm1
               
               
            psrlq mm0,5
               
               
            movd eax,mm0
               
               
            and eax,0x7E0F81F
               
               
            mov edx,eax
               
               
            shr edx,16
               
               
            or eax,edx
               
               
            mov [edi],ax

               
               
            inc esi
               
               
            inc edi
               
               
            inc esi
               
               
            inc edi
               
               
            jmp LOOPB

               
            NEXTLINE:
               
               
            add esi,D1
               
               
            add edi,D2
               
               
            mov cx,Width
               
               
            jmp LOOPA

               
            DONE:
               
               
            emms
               
            }

               
            m_Desc.pAres->DILayerToBack( &Rect );

               
            return TRUE;
            }



            下面是半透明Alpha的混合運算

            void
            CAresMaterial::DrawAlpha1( LONG X, LONG Y, LPRECT pRect )
            {

                unsigned __int16 *pSrc, *pDest;
                unsigned __int16 Width, Height, DW, DLeft;
                unsigned __int32 D1, D2;
                static unsigned __int64 MASKER = 0x7BEF7BEF7BEF7BEF;
                RECT Rect;

                Width = (unsigned __int16)(pRect->right - pRect->left);
                Height = (unsigned __int16)(pRect->bottom - pRect->top + 1 );
                pSrc = m_Desc.pData + pRect->top*m_Desc.dwPitch + pRect->left;
                pDest = m_Desc.pAres->GetBackData() + Y*m_Desc.pAres->GetScreenPitch() + X;

                DLeft = (Width % 4) + 1;
                DW = (Width>>2) + 1;

                D1 = (m_Desc.dwPitch - Width)<<1 ;
                D2 = (m_Desc.pAres->GetScreenPitch() - Width)<<1 ;
                SetRect( &Rect, X, Y, X+Width, Y+Height-1 );

                __asm
                {
                    mov esi,pSrc
                    mov edi,pDest
                    mov bx,DLeft

                    mov cx,Height
                    shl ecx,16
                    mov cx,DW

                LOOPA:
                    ror ecx,16
                    dec cx
                    jz DONE
                    ror ecx,16

                LOOPB:
                    dec cx
                    jz ENDLINE
                    //Process four points once
                    movq mm0,[esi]
                    movq mm1,[edi]
                    psrlq mm0,1
                    psrlq mm1,1
                    pand mm0,MASKER
                    pand mm1,MASKER
                    paddw mm0,mm1
                    movq [edi],mm0

                    add esi,8
                    add edi,8
                    jmp LOOPB

                ENDLINE:
                    dec bx
                    jz NEXTLINE
                    mov ax,[esi]
                    mov dx,[edi]
                    shr ax,1
                    shr dx,1
                    and ax,0x7BEF
                    and dx,0x7BEF
                    add ax,dx
                    mov [edi],ax
                    inc esi
                    inc esi
                    inc edi
                    inc edi
                    jmp ENDLINE

                NEXTLINE:
                    add esi,D1
                    add edi,D2
                    mov cx,DW
                    mov bx,DLeft
                    jmp LOOPA

                DONE:
                    emms
                }
            }

            posts - 15, comments - 0, trackbacks - 0, articles - 0

            Copyright © 莫失莫忘

            国产一区二区精品久久凹凸 | 思思久久99热只有频精品66| 国产高潮国产高潮久久久91 | 久久A级毛片免费观看| av无码久久久久久不卡网站| 久久夜色精品国产亚洲| 久久精品无码一区二区三区日韩| 欧美精品一区二区久久| 亚洲成色WWW久久网站| 9191精品国产免费久久| 久久99热这里只频精品6| 91久久九九无码成人网站| 青青草原综合久久大伊人导航| 亚洲AV无码一区东京热久久| 青青青国产成人久久111网站| 超级97碰碰碰碰久久久久最新| 欧美一区二区精品久久| 伊人久久大香线蕉亚洲五月天| 国产精品激情综合久久| 久久精品www| 久久精品国产亚洲AV大全| 超级97碰碰碰碰久久久久最新| 色综合久久中文综合网| 久久大香香蕉国产| 午夜天堂av天堂久久久| 久久精品国产亚洲av麻豆图片| 久久WWW免费人成—看片| 久久美女网站免费| 国产精品免费看久久久| 久久一日本道色综合久久| 国产69精品久久久久APP下载| 国产高潮国产高潮久久久91 | 久久久久久久久无码精品亚洲日韩 | 久久亚洲精品无码aⅴ大香| 久久精品无码一区二区app| 99久久精品国产综合一区 | 一级做a爰片久久毛片看看| 久久久久人妻一区精品| 久久精品国产精品亚洲下载 | 久久久久亚洲爆乳少妇无| 久久精品一区二区影院|