游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3381|回复: 2

DXT1 ~ DXT5 解码例子。

[复制链接]

4

主题

10

帖子

28

积分

注册会员

Rank: 2

积分
28
QQ
发表于 2006-9-22 10:02:00 | 显示全部楼层 |阅读模式
参考代码:


#pragma pack(push, 1)

struct CGeColor565
{
        WORD blue  : 5;
        WORD green : 6;
        WORD red   : 5;
};

struct CGeColor444
{
        WORD blue  : 4;
        WORD green : 4;
        WORD red   : 4;
        WORD alpha : 4;
};

struct CGeDXTColBlock
{
        CGeColor565                                        m_Color565Table[2];
        BYTE                                                m_Row[4];
};

struct CGeDXTAlphaBlockExplicit
{
        WORD                                                m_Row[4];
};

struct CGeDXTAlphaBlock3BitLinear
{
        BYTE                                                m_AlphaValue[2];
        BYTE                                                m_Data[6];
};

struct CGeDXT1Block
{
        CGeDXTColBlock                                m_ColorBlock;
};

struct CGeDXT3Block        // also used by dxt2
{
        CGeDXTAlphaBlockExplicit        m_AlphaBlock;
        CGeDXTColBlock                                m_ColorBlock;
};

struct CGeDXT5Block        // also used by dxt4
{
        CGeDXTAlphaBlock3BitLinear        m_AlphaBlock;
        CGeDXTColBlock                                m_ColorBlock;
};

#pragma pack(pop)


BOOL CGePixLayer::Create(CGeTexture* lpImage)
{
        UINT pitch;
        BYTE* lpSrcData= NULL;

        CGeAutoTexturToSurface atts(lpImage);
        if ( (lpSrcData=(BYTE*)atts.Lock(pitch)) == NULL )
        {
                return FALSE;
        }

        ASSERT( m_PixLayer == NULL);

        SAFE_DELETE(m_PixLayer);

        m_PixLayer = new CGePix32Layer;
        m_PixLayer->Create(lpImage->GetTextureWidth(), lpImage->GetTextureHeight());

        switch(lpImage->GetFormat())
        {
        case D3DFMT_A4R4G4B4:
                return __CreateForm4444(lpSrcData, pitch);

        case D3DFMT_DXT1:
                return __CreateFormDXT1(lpSrcData, pitch);

        case D3DFMT_DXT2:
        case D3DFMT_DXT3:
                return __CreateFormDXT2(lpSrcData, pitch);

        case D3DFMT_R5G6B5:
                return __CreateForm565(lpSrcData, pitch);

        case D3DFMT_DXT4:
        case D3DFMT_DXT5:
                return __CreateFormDXT4(lpSrcData, pitch);
        }

        return TRUE;
}


static void GetBlockColors(const CGeDXTColBlock &block, CGePix32 m_ColorTable[4], bool isDXT1)
{
        for (int i = 0; i < 2; i++)
        {
                m_ColorTable.alpha        = 0xff;
                m_ColorTable.red                = block.m_Color565Table.red        * 0xff / 0x1f;
                m_ColorTable.green        = block.m_Color565Table.green* 0xff / 0x3f;
                m_ColorTable.blue        = block.m_Color565Table.blue        * 0xff / 0x1f;
        }

        WORD *wCol = (WORD *)block.m_Color565Table;

        if (wCol[0] > wCol[1] || !isDXT1)
        {
                // 4 color block
                for (int i = 0; i < 2; i++)
                {
                        m_ColorTable[i + 2].alpha        = 0xff;
                        m_ColorTable[i + 2].red                = (WORD (m_ColorTable[0].red        ) * (2 - i) +        WORD (m_ColorTable[1].red        ) * (1 + i)) / 3;
                        m_ColorTable[i + 2].green        = (WORD (m_ColorTable[0].green        ) * (2 - i) +        WORD (m_ColorTable[1].green        ) * (1 + i)) / 3;
                        m_ColorTable[i + 2].blue        = (WORD (m_ColorTable[0].blue        ) * (2 - i) +        WORD (m_ColorTable[1].blue        ) * (1 + i)) / 3;
                }
        }
        else
        {
                // 3 color block, number 4 is transparent
                m_ColorTable[2].alpha        = 0xff;
                m_ColorTable[2].red                = (WORD (m_ColorTable[0].red        ) +        WORD (m_ColorTable[1].red        )) / 2;
                m_ColorTable[2].green        = (WORD (m_ColorTable[0].green        ) + WORD (m_ColorTable[1].green        )) / 2;
                m_ColorTable[2].blue        = (WORD (m_ColorTable[0].blue        ) + WORD (m_ColorTable[1].blue        )) / 2;

                m_ColorTable[3].alpha        = 0x00;
                m_ColorTable[3].red                = 0x00;
                m_ColorTable[3].green        = 0x00;
                m_ColorTable[3].blue        = 0x00;
        }
}

BOOL CGePixLayer::__CreateFormDXT1(BYTE* lpData, UINT pitch)
{
        CGePix32 Color32Table[4];
        CGePix32* lpDestData= (CGePix32*)m_PixLayer->GetData();

        int nDestHeight= m_PixLayer->GetHeight();
        int nDestWidth = m_PixLayer->GetWidth();

        for(int block_y=0; block_y< nDestHeight; block_y+= 4)
        {
                for(int block_x=0; block_x< nDestWidth; block_x+= 4)
                {
                        BYTE* lpCurrSrcData = lpData+ (pitch* block_y >> 2)  + ( block_x  << 1 );
                        CGeDXT1Block* lpBlock= (CGeDXT1Block*)(lpCurrSrcData);
                        GetBlockColors(lpBlock->m_ColorBlock, Color32Table, TRUE);

                        for(int row=0; row<4; ++row) // line
                        {
                                /// column
                                CGePix32* lpDestDataW= &lpDestData[ (block_y+ row)* nDestWidth + block_x];

                                int Data = lpBlock->m_ColorBlock.m_Row[row];
                                int nMask= 0;
                                int Mask = 0x03;

                                for(int j=0; j<4; ++j)
                                {
                                        int bit= (Data & Mask) >> nMask;
                                        Mask <<= 2;
                                        nMask+=2;
                                        *lpDestDataW++ = Color32Table[bit];
                                }
                        }
                }
        }

        return TRUE;
}

BOOL CGePixLayer::__CreateFormDXT2(BYTE* lpData, UINT pitch)
{
        CGePix32 Color32Table[4];
        CGePix32* lpDestData= (CGePix32*)m_PixLayer->GetData();

        int nDestHeight= m_PixLayer->GetHeight();
        int nDestWidth = m_PixLayer->GetWidth();

        for(int block_y=0; block_y< nDestHeight; block_y+= 4)
        {
                for(int block_x=0; block_x< nDestWidth; block_x+= 4)
                {
                        /// each block
                        BYTE* lpCurrSrcData = lpData+ (pitch* block_y >> 2)  + ( block_x  << 2 );
                        CGeDXT3Block* lpBlock= (CGeDXT3Block*)(lpCurrSrcData);
                        GetBlockColors(lpBlock->m_ColorBlock, Color32Table, TRUE);

                        for(int row=0; row<4; ++row) //row
                        {
                                /// column
                                CGePix32* lpDestDataW= &lpDestData[ (block_y+ row)* nDestWidth + block_x];

                                BYTE Data = lpBlock->m_ColorBlock.m_Row[row];
                                WORD Alpha= lpBlock->m_AlphaBlock.m_Row[row];

                                int nMask= 0;
                                int Mask = 0x03;
                                int Mask2= 0x0F;
                                int nMask2=0;

                                for(int j=0; j<4; ++j)
                                {
                                        int bit= (Data & Mask) >> nMask;
                                        int alp= (Alpha& Mask2) >> nMask2;

                                        Mask <<= 2;
                                        Mask2 <<= 4;

                                        nMask+=2;
                                        nMask2+=4;

                                        *lpDestDataW = Color32Table[bit];
                                        lpDestDataW->alpha = alp * 0x11;

                                        lpDestDataW++;
                                }
                        }
                }
        }

        return TRUE;
}

BOOL CGePixLayer::__CreateFormDXT4(BYTE* lpData, UINT pitch)
{
        CGePix32 Color32Table[4];
        CGePix32* lpDestData= (CGePix32*)m_PixLayer->GetData();

        int nDestHeight= m_PixLayer->GetHeight();
        int nDestWidth = m_PixLayer->GetWidth();

        for(int block_y=0; block_y< nDestHeight; block_y+= 4)
        {
                for(int block_x=0; block_x< nDestWidth; block_x+= 4)
                {
                        unsigned m_alphas[8];
                        unsigned m_alphaBits;
                        int m_offset;

                        /// each block
                        BYTE* lpCurrSrcData = lpData+ (pitch* block_y >> 2)  + ( block_x  << 2 );
                        CGeDXT5Block* lpBlock= (CGeDXT5Block*)(lpCurrSrcData);

                        GetBlockColors(lpBlock->m_ColorBlock, Color32Table, TRUE);
                        const CGeDXTAlphaBlock3BitLinear& ABlineBlock= lpBlock->m_AlphaBlock;

                        m_alphas[0] = ABlineBlock.m_AlphaValue[0];
                        m_alphas[1] = ABlineBlock.m_AlphaValue[1];

                        if(m_alphas[0]> m_alphas[1])
                        {
                                // 8 alpha block
                                for(int i=0; i<6; ++i)
                                        m_alphas[i+2] = ((6-i)* m_alphas[0] + (1+i) * m_alphas[1]+ 3) / 7;
                        }
                        else
                        {
                                // 6 alpha block
                                for (int i = 0; i < 4; i++)
                                        m_alphas[i + 2] = ((4 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 2) / 5;
                                m_alphas[6] = 0;
                                m_alphas[7] = 0xFF;
                        }

                        for(int row=0; row<4; ++row) //  line
                        {
                                int i = row >> 1;
                                m_alphaBits = unsigned( ABlineBlock.m_Data[0+i*3]) | (unsigned( ABlineBlock.m_Data[1+i*3]) << 8) | ( unsigned)((ABlineBlock.m_Data[2+i*3]) << 16 );
                                m_offset = (row & 1) * 12;

                                /// column
                                CGePix32* lpDestDataW= &lpDestData[ (block_y+ row)* nDestWidth + block_x];

                                BYTE Data = lpBlock->m_ColorBlock.m_Row[row];

                                int nMask= 0;
                                int Mask = 0x03;

                                for(int j=0; j<4; ++j)
                                {
                                        int bit= (Data & Mask) >> nMask;
                                        Mask <<= 2;
                                        nMask+=2;
                                        *lpDestDataW = Color32Table[bit];

                                        unsigned bits = (m_alphaBits >> (j * 3 + m_offset)) & 7;
                                        lpDestDataW->alpha = m_alphas[bits];

                                        lpDestDataW++;
                                }
                        }
                }
        }


        return TRUE;
}


以上代码,如果有错误,希望指正。

MSN: liushaojing2004@hotmail.com

8

主题

239

帖子

239

积分

中级会员

Rank: 3Rank: 3

积分
239
发表于 2006-9-23 20:36:00 | 显示全部楼层

Re:DXT1 ~ DXT5 解码例子。

不错,呵呵,有编码的吗?

8

主题

716

帖子

716

积分

高级会员

Rank: 4

积分
716
发表于 2006-9-25 11:02:00 | 显示全部楼层

Re:DXT1 ~ DXT5 解码例子。

推荐用freeimage或Devil

编码的话DX、ATI和NV都提供了工具
或者自己写个tool用d3dx批量转换
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 12:44

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表