mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2026-03-20 17:11:16 +01:00
Initial commit
This commit is contained in:
604
neo/renderer/DXT/DXTCodec.h
Normal file
604
neo/renderer/DXT/DXTCodec.h
Normal file
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __DXTCODEC_H__
|
||||
#define __DXTCODEC_H__
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
Contains the DxtEncoder and DxtDecoder declarations.
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================================================
|
||||
idDxtEncoder encodes Images in a number of DXT formats. Raw input Images are assumed to be in
|
||||
4-byte RGBA format. Raw input NormalMaps are assumed to be in 4-byte tangent-space NxNyNz format.
|
||||
|
||||
The supported formats are:
|
||||
* DXT1 = colors in 4x4 block approximated by equidistant points on a line through 3D space
|
||||
* DXT2 = DXT3 + colors are pre-multiplied by alpha
|
||||
* DXT3 = DXT1 + explicit 4-bit alpha
|
||||
* DXT4 = DXT5 + colors are pre-multiplied by alpha
|
||||
* DXT5 = DXT1 + alpha values in 4x4 block approximated by equidistant points on line through alpha space
|
||||
* CTX1 = colors in a 4x4 block approximated by equidistant points on a line through 2D space
|
||||
* DXN1 = one DXT5 alpha block (aka DXT5A, or ATI1N)
|
||||
* DXN2 = two DXT5 alpha blocks (aka 3Dc, or ATI2N)
|
||||
================================================
|
||||
*/
|
||||
class idDxtEncoder {
|
||||
public:
|
||||
idDxtEncoder() { srcPadding = dstPadding = 0; }
|
||||
~idDxtEncoder() {}
|
||||
|
||||
void SetSrcPadding( int pad ) { srcPadding = pad; }
|
||||
void SetDstPadding( int pad ) { dstPadding = pad; }
|
||||
|
||||
// high quality DXT1 compression (no alpha), uses exhaustive search to find a line through color space and is very slow
|
||||
void CompressImageDXT1HQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast DXT1 compression (no alpha), for real-time use at the cost of a little quality
|
||||
void CompressImageDXT1Fast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXT1Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXT1Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// high quality DXT1 compression (with alpha), uses exhaustive search to find a line through color space and is very slow
|
||||
void CompressImageDXT1AlphaHQ( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// fast DXT1 compression (with alpha), for real-time use at the cost of a little quality
|
||||
void CompressImageDXT1AlphaFast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXT1AlphaFast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXT1AlphaFast_SSE2( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// high quality DXT5 compression, uses exhaustive search to find a line through color space and is generally
|
||||
// too slow to actually use for anything
|
||||
void CompressImageDXT5HQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast DXT5 compression for real-time use at the cost of a little quality
|
||||
void CompressImageDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXT5Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXT5Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// high quality CTX1 compression, uses exhaustive search to find a line through 2D space and is very slow
|
||||
void CompressImageCTX1HQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast CTX1 compression for real-time use
|
||||
void CompressImageCTX1Fast( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
void CompressImageCTX1Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
void CompressImageCTX1Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// high quality DXN1 (aka DXT5A or ATI1N) compression, uses exhaustive search to find a line through color space and is very slow
|
||||
void CompressImageDXN1HQ( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// fast single channel compression into, DXN1 (aka DXT5A or ATI1N) format, for real-time use
|
||||
void CompressImageDXN1Fast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXN1Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressImageDXN1Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// high quality YCoCg DXT5 compression, uses exhaustive search to find a line through color space and is very slow
|
||||
void CompressYCoCgDXT5HQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast YCoCg DXT5 compression for real-time use (the input is expected to be in CoCg_Y format)
|
||||
void CompressYCoCgDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressYCoCgDXT5Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressYCoCgDXT5Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast YCoCg-Alpha DXT5 compression for real-time use (the input is expected to be in CoCgAY format)
|
||||
void CompressYCoCgAlphaDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// high quality YCoCg CTX1 + DXT5A compression, uses exhaustive search to find a line through 2D space and is very slow
|
||||
void CompressYCoCgCTX1DXT5AHQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast YCoCg CTX1 + DXT5A compression for real-time use (the input is expected to be in CoCg_Y format)
|
||||
void CompressYCoCgCTX1DXT5AFast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressYCoCgCTX1DXT5AFast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressYCoCgCTX1DXT5AFast_SSE2( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// high quality tangent space NxNyNz normal map compression into DXT1 format (Nz is not used)
|
||||
void CompressNormalMapDXT1HQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressNormalMapDXT1RenormalizeHQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast tangent space NxNyNz normal map compression into DXT1 format (Nz is not used), for real-time use
|
||||
void CompressNormalMapDXT1Fast( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
void CompressNormalMapDXT1Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
void CompressNormalMapDXT1Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// high quality tangent space _Ny_Nx normal map compression into DXT5 format
|
||||
void CompressNormalMapDXT5HQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressNormalMapDXT5RenormalizeHQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast tangent space _Ny_Nx normal map compression into DXT5 format, for real-time use
|
||||
void CompressNormalMapDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressNormalMapDXT5Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressNormalMapDXT5Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// high quality tangent space NxNy_ normal map compression into DXN2 (3Dc, ATI2N) format
|
||||
void CompressNormalMapDXN2HQ( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast tangent space NxNy_ normal map compression into DXN2 (3Dc, ATI2N) format, for real-time use
|
||||
void CompressNormalMapDXN2Fast( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressNormalMapDXN2Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void CompressNormalMapDXN2Fast_SSE2( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// fast single channel conversion from DXN1 (aka DXT5A or ATI1N) to DXT1, reasonably fast (also works in-place)
|
||||
void ConvertImageDXN1_DXT1( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast single channel conversion from DXT1 to DXN1 (aka DXT5A or ATI1N), reasonably fast (also works in-place)
|
||||
void ConvertImageDXT1_DXN1( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// fast tangent space NxNyNz normal map conversion from DXN (3Dc, ATI2N) to DXT5, reasonably fast (also works in-place)
|
||||
void ConvertNormalMapDXN2_DXT5( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// fast tangent space NxNyNz normal map conversion DXT5 to DXN (3Dc, ATI2N), reasonably fast (also works in-place)
|
||||
void ConvertNormalMapDXT5_DXN2( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
private:
|
||||
int width;
|
||||
int height;
|
||||
byte * outData;
|
||||
int srcPadding;
|
||||
int dstPadding;
|
||||
|
||||
void EmitByte( byte b );
|
||||
void EmitUShort( unsigned short s );
|
||||
void EmitUInt( unsigned int i );
|
||||
unsigned int AlphaDistance( const byte a1, const byte a2 ) const;
|
||||
unsigned int ColorDistance( const byte *c1, const byte *c2 ) const;
|
||||
unsigned int ColorDistanceWeighted( const byte *c1, const byte *c2 ) const;
|
||||
unsigned int CTX1Distance( const byte *c1, const byte *c2 ) const;
|
||||
unsigned short ColorTo565( const byte *color ) const;
|
||||
unsigned short ColorTo565( byte r, byte g, byte b ) const;
|
||||
void ColorFrom565( unsigned short c565, byte *color ) const;
|
||||
byte GreenFrom565( unsigned short c565 ) const;
|
||||
|
||||
void NV4XHardwareBugFix( byte *minColor, byte *maxColor ) const;
|
||||
|
||||
bool HasConstantValuePer4x4Block( const byte *inBuf, int width, int height, int channel ) const;
|
||||
void WriteTinyColorDXT1( const byte *inBuf, int width, int height );
|
||||
void WriteTinyColorDXT5( const byte *inBuf, int width, int height );
|
||||
void WriteTinyColorCTX1DXT5A( const byte *inBuf, int width, int height );
|
||||
void WriteTinyNormalMapDXT5( const byte *NxNy, int width, int height );
|
||||
void WriteTinyNormalMapDXN( const byte *NxNy, int width, int height );
|
||||
void WriteTinyDXT5A( const byte *NxNy, int width, int height );
|
||||
|
||||
void GetMinMaxColorsMaxDist( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
void GetMinMaxColorsLuminance( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
int GetSquareAlphaError( const byte *colorBlock, const int alphaOffset, const byte minAlpha, const byte maxAlpha, int lastError ) const;
|
||||
int GetMinMaxAlphaHQ( const byte *colorBlock, const int alphaOffset, byte *minColor, byte *maxColor ) const;
|
||||
int GetSquareColorsError( const byte *colorBlock, const unsigned short color0, const unsigned short color1, int lastError ) const;
|
||||
int GetMinMaxColorsHQ( const byte *colorBlock, byte *minColor, byte *maxColor, bool noBlack ) const;
|
||||
int GetSquareCTX1Error( const byte *colorBlock, const byte *color0, const byte *color1, int lastError ) const;
|
||||
int GetMinMaxCTX1HQ( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
int GetSquareNormalYError( const byte *colorBlock, const unsigned short color0, const unsigned short color1, int lastError, int scale ) const;
|
||||
int GetMinMaxNormalYHQ( const byte *colorBlock, byte *minColor, byte *maxColor, bool noBlack, int scale ) const;
|
||||
int GetSquareNormalsDXT1Error( const int *colorBlock, const unsigned short color0, const unsigned short color1, int lastError, unsigned int &colorIndices ) const;
|
||||
int GetMinMaxNormalsDXT1HQ( const byte *colorBlock, byte *minColor, byte *maxColor, unsigned int &colorIndices, bool noBlack ) const;
|
||||
int GetSquareNormalsDXT5Error( const int *normalBlock, const byte *minNormal, const byte *maxNormal, int lastError, unsigned int &colorIndices, byte *alphaIndices ) const;
|
||||
int GetMinMaxNormalsDXT5HQ( const byte *normalBlock, byte *minColor, byte *maxColor, unsigned int &colorIndices, byte *alphaIndices ) const;
|
||||
int GetMinMaxNormalsDXT5HQFast( const byte *normalBlock, byte *minColor, byte *maxColor, unsigned int &colorIndices, byte *alphaIndices ) const;
|
||||
void ScaleYCoCg( byte *colorBlock ) const;
|
||||
void BiasScaleNormalY( byte *colorBlock ) const;
|
||||
void RotateNormalsDXT1( byte *block ) const;
|
||||
void RotateNormalsDXT5( byte *block ) const;
|
||||
int FindColorIndices( const byte *colorBlock, const unsigned short color0, const unsigned short color1, unsigned int &result ) const;
|
||||
int FindAlphaIndices( const byte *colorBlock, const int alphaOffset, const byte alpha0, const byte alpha1, byte *indexes ) const;
|
||||
int FindCTX1Indices( const byte *colorBlock, const byte *color0, const byte *color1, unsigned int &result ) const;
|
||||
|
||||
void ExtractBlock( const byte *inPtr, int width, byte *colorBlock ) const;
|
||||
void GetMinMaxBBox( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
void InsetColorsBBox( byte *minColor, byte *maxColor ) const;
|
||||
void SelectColorsDiagonal( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
void ScaleYCoCg( byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
void InsetYCoCgAlpaBBox( byte *minColor, byte *maxColor ) const;
|
||||
void InsetYCoCgBBox( byte *minColor, byte *maxColor ) const;
|
||||
void SelectYCoCgDiagonal( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
void InsetNormalsBBoxDXT5( byte *minNormal, byte *maxNormal ) const;
|
||||
void InsetNormalsBBox3Dc( byte *minNormal, byte *maxNormal ) const;
|
||||
void EmitColorIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor );
|
||||
void EmitColorAlphaIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor );
|
||||
void EmitCTX1Indices( const byte *colorBlock, const byte *minColor, const byte *maxColor );
|
||||
void EmitAlphaIndices( const byte *colorBlock, const int channel, const byte minAlpha, const byte maxAlpha );
|
||||
void EmitGreenIndices( const byte *block, const int channel, const byte minGreen, const byte maxGreen );
|
||||
|
||||
// Keeping the ASM versions to keep the performance of 32-bit debug builds reasonable.
|
||||
// The implementation using intrinsics is very slow in debug builds because registers are continuously spilled to memory.
|
||||
void ExtractBlock_SSE2( const byte *inPtr, int width, byte *colorBlock ) const;
|
||||
void GetMinMaxBBox_SSE2( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
void InsetColorsBBox_SSE2( byte *minColor, byte *maxColor ) const;
|
||||
void InsetNormalsBBoxDXT5_SSE2( byte *minNormal, byte *maxNormal ) const;
|
||||
void EmitColorIndices_SSE2( const byte *colorBlock, const byte *minColor, const byte *maxColor );
|
||||
void EmitColorAlphaIndices_SSE2( const byte *colorBlock, const byte *minColor, const byte *maxColor );
|
||||
void EmitCoCgIndices_SSE2( const byte *colorBlock, const byte *minColor, const byte *maxColor );
|
||||
void EmitAlphaIndices_SSE2( const byte *colorBlock, const int minAlpha, const int maxAlpha );
|
||||
void EmitAlphaIndices_SSE2( const byte *colorBlock, const int channelBitOffset, const int minAlpha, const int maxAlpha );
|
||||
void EmitGreenIndices_SSE2( const byte *block, const int channelBitOffset, const int minGreen, const int maxGreen );
|
||||
void ScaleYCoCg_SSE2( byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
void InsetYCoCgBBox_SSE2( byte *minColor, byte *maxColor ) const;
|
||||
void SelectYCoCgDiagonal_SSE2( const byte *colorBlock, byte *minColor, byte *maxColor ) const;
|
||||
|
||||
|
||||
|
||||
void EmitNormalYIndices( const byte *normalBlock, const int offset, const byte minNormalY, const byte maxNormalY );
|
||||
void EmitNormalYIndices_SSE2( const byte *normalBlock, const int offset, const byte minNormalY, const byte maxNormalY );
|
||||
|
||||
void DecodeDXNAlphaValues( const byte *inBuf, byte *values );
|
||||
void EncodeDXNAlphaValues( byte *outBuf, const byte min, const byte max, const byte *values );
|
||||
|
||||
void DecodeNormalYValues( const byte *inBuf, byte &min, byte &max, byte *values );
|
||||
void EncodeNormalRGBIndices( byte *outBuf, const byte min, const byte max, const byte *values );
|
||||
};
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressImageDXT1Fast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressImageDXT1Fast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressImageDXT1Fast_SSE2( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressImageDXT1AlphaFast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressImageDXT1AlphaFast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressImageDXT1AlphaFast_SSE2( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressImageDXT5Fast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressImageDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressImageDXT5Fast_SSE2( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressImageDXN1Fast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressImageDXN1Fast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressImageDXN1Fast_Generic( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressYCoCgDXT5Fast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressYCoCgDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressYCoCgDXT5Fast_SSE2( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressYCoCgCTX1DXT5AFast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressYCoCgCTX1DXT5AFast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressYCoCgCTX1DXT5AFast_Generic( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressNormalMapDXT5Fast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressNormalMapDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressNormalMapDXT5Fast_SSE2( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CompressNormalMapDXN2Fast
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::CompressNormalMapDXN2Fast( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
CompressNormalMapDXN2Fast_Generic( inBuf, outBuf, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::EmitByte
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::EmitByte( byte b ) {
|
||||
*outData = b;
|
||||
outData += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::EmitUShort
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::EmitUShort( unsigned short s ) {
|
||||
*((unsigned short *)outData) = s;
|
||||
outData += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::EmitUInt
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::EmitUInt( unsigned int i ) {
|
||||
*((unsigned int *)outData) = i;
|
||||
outData += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::AlphaDistance
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned int idDxtEncoder::AlphaDistance( const byte a1, const byte a2 ) const {
|
||||
return ( a1 - a2 ) * ( a1 - a2 );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::ColorDistance
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned int idDxtEncoder::ColorDistance( const byte *c1, const byte *c2 ) const {
|
||||
return ( ( c1[ 0 ] - c2[ 0 ] ) * ( c1[ 0 ] - c2[ 0 ] ) ) + ( ( c1[ 1 ] - c2[ 1 ] ) * ( c1[ 1 ] - c2[ 1 ] ) ) + ( ( c1[ 2 ] - c2[ 2 ] ) * ( c1[ 2 ] - c2[ 2 ] ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::ColorDistanceWeighted
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned int idDxtEncoder::ColorDistanceWeighted( const byte *c1, const byte *c2 ) const {
|
||||
int r, g, b;
|
||||
int rmean;
|
||||
|
||||
// http://www.compuphase.com/cmetric.htm
|
||||
rmean = ( (int)c1[0] + (int)c2[0] ) / 2;
|
||||
r = (int)c1[0] - (int)c2[0];
|
||||
g = (int)c1[1] - (int)c2[1];
|
||||
b = (int)c1[2] - (int)c2[2];
|
||||
return ( ( ( 512 + rmean ) * r * r ) >> 8 ) + 4 * g * g + ( ( ( 767 - rmean ) * b * b ) >> 8 );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::CTX1Distance
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned int idDxtEncoder::CTX1Distance( const byte *c1, const byte *c2 ) const {
|
||||
return ( ( c1[ 0 ] - c2[ 0 ] ) * ( c1[ 0 ] - c2[ 0 ] ) ) + ( ( c1[ 1 ] - c2[ 1 ] ) * ( c1[ 1 ] - c2[ 1 ] ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::ColorTo565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned short idDxtEncoder::ColorTo565( const byte *color ) const {
|
||||
return ( ( color[ 0 ] >> 3 ) << 11 ) | ( ( color[ 1 ] >> 2 ) << 5 ) | ( color[ 2 ] >> 3 );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::ColorFrom565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtEncoder::ColorFrom565( unsigned short c565, byte *color ) const {
|
||||
color[0] = byte( ( ( c565 >> 8 ) & ( ( ( 1 << ( 8 - 3 ) ) - 1 ) << 3 ) ) | ( ( c565 >> 13 ) & ((1<<3)-1) ) );
|
||||
color[1] = byte( ( ( c565 >> 3 ) & ( ( ( 1 << ( 8 - 2 ) ) - 1 ) << 2 ) ) | ( ( c565 >> 9 ) & ((1<<2)-1) ) );
|
||||
color[2] = byte( ( ( c565 << 3 ) & ( ( ( 1 << ( 8 - 3 ) ) - 1 ) << 3 ) ) | ( ( c565 >> 2 ) & ((1<<3)-1) ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::ColorTo565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned short idDxtEncoder::ColorTo565( byte r, byte g, byte b ) const {
|
||||
return ( ( r >> 3 ) << 11 ) | ( ( g >> 2 ) << 5 ) | ( b >> 3 );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtEncoder::GreenFrom565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE byte idDxtEncoder::GreenFrom565( unsigned short c565 ) const {
|
||||
byte c = byte( ( c565 & ( ( ( 1 << 6 ) - 1 ) << 5 ) ) >> 3 );
|
||||
return ( c | ( c >> 6 ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================================================
|
||||
idDxtDecoder decodes DXT-compressed Images. Raw output Images are in
|
||||
4-byte RGBA format. Raw output NormalMaps are in 4-byte tangent-space NxNyNz format.
|
||||
================================================
|
||||
*/
|
||||
class idDxtDecoder {
|
||||
public:
|
||||
|
||||
// DXT1 decompression (no alpha)
|
||||
void DecompressImageDXT1( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// DXT5 decompression
|
||||
void DecompressImageDXT5( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// DXT5 decompression with nVidia 7x hardware bug
|
||||
void DecompressImageDXT5_nVidia7x( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// CTX1
|
||||
void DecompressImageCTX1( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// DXN1
|
||||
void DecompressImageDXN1( const byte *inBuf, byte *outBuf, int width, int height ) { /* not implemented */ assert( 0 ); }
|
||||
|
||||
// YCoCg DXT5 (the output is in CoCg_Y format)
|
||||
void DecompressYCoCgDXT5( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// YCoCg CTX1 + DXT5A (the output is in CoCg_Y format)
|
||||
void DecompressYCoCgCTX1DXT5A( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// tangent space normal map decompression from DXT1 format
|
||||
void DecompressNormalMapDXT1( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void DecompressNormalMapDXT1Renormalize( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// tangent space normal map decompression from DXT5 format
|
||||
void DecompressNormalMapDXT5( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
void DecompressNormalMapDXT5Renormalize( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// tangent space normal map decompression from DXN2 format
|
||||
void DecompressNormalMapDXN2( const byte *inBuf, byte *outBuf, int width, int height );
|
||||
|
||||
// decompose a DXT image into indices and two images with colors
|
||||
void DecomposeImageDXT1( const byte *inBuf, byte *colorIndices, byte *pic1, byte *pic2, int width, int height );
|
||||
void DecomposeImageDXT5( const byte *inBuf, byte *colorIndices, byte *alphaIndices, byte *pic1, byte *pic2, int width, int height );
|
||||
|
||||
private:
|
||||
int width;
|
||||
int height;
|
||||
const byte * inData;
|
||||
|
||||
byte ReadByte();
|
||||
unsigned short ReadUShort();
|
||||
unsigned int ReadUInt();
|
||||
unsigned short ColorTo565( const byte *color ) const;
|
||||
void ColorFrom565( unsigned short c565, byte *color ) const;
|
||||
unsigned short NormalYTo565( byte y ) const;
|
||||
byte NormalYFrom565( unsigned short c565 ) const;
|
||||
byte NormalScaleFrom565( unsigned short c565 ) const;
|
||||
byte NormalBiasFrom565( unsigned short c565 ) const;
|
||||
|
||||
void EmitBlock( byte *outPtr, int x, int y, const byte *colorBlock );
|
||||
void DecodeAlphaValues( byte *colorBlock, const int offset );
|
||||
void DecodeColorValues( byte *colorBlock, bool noBlack, bool writeAlpha );
|
||||
void DecodeCTX1Values( byte *colorBlock );
|
||||
|
||||
void DecomposeColorBlock( byte colors[2][4], byte colorIndices[16], bool noBlack );
|
||||
void DecomposeAlphaBlock( byte colors[2][4], byte alphaIndices[16] );
|
||||
|
||||
void DecodeNormalYValues( byte *normalBlock, const int offsetY, byte &bias, byte &scale );
|
||||
void DeriveNormalZValues( byte *normalBlock );
|
||||
};
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::ReadByte
|
||||
========================
|
||||
*/
|
||||
ID_INLINE byte idDxtDecoder::ReadByte() {
|
||||
byte b = *inData;
|
||||
inData += 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::ReadUShort
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned short idDxtDecoder::ReadUShort() {
|
||||
unsigned short s = *((unsigned short *)inData);
|
||||
inData += 2;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::ReadUInt
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned int idDxtDecoder::ReadUInt() {
|
||||
unsigned int i = *((unsigned int *)inData);
|
||||
inData += 4;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::ColorTo565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned short idDxtDecoder::ColorTo565( const byte *color ) const {
|
||||
return ( ( color[ 0 ] >> 3 ) << 11 ) | ( ( color[ 1 ] >> 2 ) << 5 ) | ( color[ 2 ] >> 3 );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::ColorFrom565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE void idDxtDecoder::ColorFrom565( unsigned short c565, byte *color ) const {
|
||||
color[0] = byte( ( ( c565 >> 8 ) & ( ( ( 1 << ( 8 - 3 ) ) - 1 ) << 3 ) ) | ( ( c565 >> 13 ) & ((1<<3)-1) ) );
|
||||
color[1] = byte( ( ( c565 >> 3 ) & ( ( ( 1 << ( 8 - 2 ) ) - 1 ) << 2 ) ) | ( ( c565 >> 9 ) & ((1<<2)-1) ) );
|
||||
color[2] = byte( ( ( c565 << 3 ) & ( ( ( 1 << ( 8 - 3 ) ) - 1 ) << 3 ) ) | ( ( c565 >> 2 ) & ((1<<3)-1) ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::NormalYTo565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE unsigned short idDxtDecoder::NormalYTo565( byte y ) const {
|
||||
return ( ( y >> 2 ) << 5 );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::NormalYFrom565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE byte idDxtDecoder::NormalYFrom565( unsigned short c565 ) const {
|
||||
byte c = byte( ( c565 & ( ( ( 1 << 6 ) - 1 ) << 5 ) ) >> 3 );
|
||||
return ( c | ( c >> 6 ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::NormalBiasFrom565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE byte idDxtDecoder::NormalBiasFrom565( unsigned short c565 ) const {
|
||||
byte c = byte( ( c565 & ( ( ( 1 << 5 ) - 1 ) << 11 ) ) >> 8 );
|
||||
return ( c | ( c >> 5 ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::NormalScaleFrom565
|
||||
========================
|
||||
*/
|
||||
ID_INLINE byte idDxtDecoder::NormalScaleFrom565( unsigned short c565 ) const {
|
||||
byte c = byte( ( c565 & ( ( ( 1 << 5 ) - 1 ) << 0 ) ) << 3 );
|
||||
return ( c | ( c >> 5 ) );
|
||||
}
|
||||
|
||||
#endif // !__DXTCODEC_H__
|
||||
38
neo/renderer/DXT/DXTCodec_local.h
Normal file
38
neo/renderer/DXT/DXTCodec_local.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __DXTCODEC_LOCAL_H__
|
||||
#define __DXTCODEC_LOCAL_H__
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
Contains the DxtEncoder and DxtDecoder declarations.
|
||||
================================================================================================
|
||||
*/
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
#endif // !__DXTCODEC_LOCAL_H__
|
||||
745
neo/renderer/DXT/DXTDecoder.cpp
Normal file
745
neo/renderer/DXT/DXTDecoder.cpp
Normal file
@@ -0,0 +1,745 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
/*
|
||||
================================================================================================
|
||||
Contains the DxtDecoder implementation.
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "DXTCodec_local.h"
|
||||
#include "DXTCodec.h"
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::EmitBlock
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::EmitBlock( byte *outPtr, int x, int y, const byte *colorBlock ) {
|
||||
outPtr += ( y * width + x ) * 4;
|
||||
for ( int j = 0; j < 4; j++ ) {
|
||||
memcpy( outPtr, &colorBlock[j*4*4], 4*4 );
|
||||
outPtr += width * 4;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecodeAlphaValues
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecodeAlphaValues( byte *colorBlock, const int offset ) {
|
||||
int i;
|
||||
unsigned int indexes;
|
||||
byte alphas[8];
|
||||
|
||||
alphas[0] = ReadByte();
|
||||
alphas[1] = ReadByte();
|
||||
|
||||
if ( alphas[0] > alphas[1] ) {
|
||||
alphas[2] = ( 6 * alphas[0] + 1 * alphas[1] ) / 7;
|
||||
alphas[3] = ( 5 * alphas[0] + 2 * alphas[1] ) / 7;
|
||||
alphas[4] = ( 4 * alphas[0] + 3 * alphas[1] ) / 7;
|
||||
alphas[5] = ( 3 * alphas[0] + 4 * alphas[1] ) / 7;
|
||||
alphas[6] = ( 2 * alphas[0] + 5 * alphas[1] ) / 7;
|
||||
alphas[7] = ( 1 * alphas[0] + 6 * alphas[1] ) / 7;
|
||||
} else {
|
||||
alphas[2] = ( 4 * alphas[0] + 1 * alphas[1] ) / 5;
|
||||
alphas[3] = ( 3 * alphas[0] + 2 * alphas[1] ) / 5;
|
||||
alphas[4] = ( 2 * alphas[0] + 3 * alphas[1] ) / 5;
|
||||
alphas[5] = ( 1 * alphas[0] + 4 * alphas[1] ) / 5;
|
||||
alphas[6] = 0;
|
||||
alphas[7] = 255;
|
||||
}
|
||||
|
||||
colorBlock += offset;
|
||||
|
||||
indexes = (int)ReadByte() | ( (int)ReadByte() << 8 ) | ( (int)ReadByte() << 16 );
|
||||
for ( i = 0; i < 8; i++ ) {
|
||||
colorBlock[i*4] = alphas[indexes & 7];
|
||||
indexes >>= 3;
|
||||
}
|
||||
|
||||
indexes = (int)ReadByte() | ( (int)ReadByte() << 8 ) | ( (int)ReadByte() << 16 );
|
||||
for ( i = 8; i < 16; i++ ) {
|
||||
colorBlock[i*4] = alphas[indexes & 7];
|
||||
indexes >>= 3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecodeColorValues
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecodeColorValues( byte *colorBlock, bool noBlack, bool writeAlpha ) {
|
||||
byte colors[4][4];
|
||||
|
||||
unsigned short color0 = ReadUShort();
|
||||
unsigned short color1 = ReadUShort();
|
||||
|
||||
ColorFrom565( color0, colors[0] );
|
||||
ColorFrom565( color1, colors[1] );
|
||||
|
||||
colors[0][3] = 255;
|
||||
colors[1][3] = 255;
|
||||
|
||||
if ( noBlack || color0 > color1 ) {
|
||||
colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
|
||||
colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
|
||||
colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
|
||||
colors[2][3] = 255;
|
||||
|
||||
colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
|
||||
colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
|
||||
colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
|
||||
colors[3][3] = 255;
|
||||
} else {
|
||||
colors[2][0] = ( 1 * colors[0][0] + 1 * colors[1][0] ) / 2;
|
||||
colors[2][1] = ( 1 * colors[0][1] + 1 * colors[1][1] ) / 2;
|
||||
colors[2][2] = ( 1 * colors[0][2] + 1 * colors[1][2] ) / 2;
|
||||
colors[2][3] = 255;
|
||||
|
||||
colors[3][0] = 0;
|
||||
colors[3][1] = 0;
|
||||
colors[3][2] = 0;
|
||||
colors[3][3] = 0;
|
||||
}
|
||||
|
||||
unsigned int indexes = ReadUInt();
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
colorBlock[i*4+0] = colors[indexes & 3][0];
|
||||
colorBlock[i*4+1] = colors[indexes & 3][1];
|
||||
colorBlock[i*4+2] = colors[indexes & 3][2];
|
||||
if ( writeAlpha ) {
|
||||
colorBlock[i*4+3] = colors[indexes & 3][3];
|
||||
}
|
||||
indexes >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecodeCTX1Values
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecodeCTX1Values( byte *colorBlock ) {
|
||||
byte colors[4][2];
|
||||
|
||||
colors[0][0] = ReadByte();
|
||||
colors[0][1] = ReadByte();
|
||||
colors[1][0] = ReadByte();
|
||||
colors[1][1] = ReadByte();
|
||||
|
||||
colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
|
||||
colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
|
||||
colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
|
||||
colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
|
||||
|
||||
unsigned int indexes = ReadUInt();
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
colorBlock[i*4+0] = colors[indexes & 3][0];
|
||||
colorBlock[i*4+1] = colors[indexes & 3][1];
|
||||
indexes >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressImageDXT1
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressImageDXT1( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeColorValues( block, false, true );
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressImageDXT5
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressImageDXT5( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeAlphaValues( block, 3 );
|
||||
DecodeColorValues( block, true, false );
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressImageDXT5_nVidia7x
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressImageDXT5_nVidia7x( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeAlphaValues( block, 3 );
|
||||
DecodeColorValues( block, false, false );
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressYCoCgDXT5
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressYCoCgDXT5( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
DecompressImageDXT5_nVidia7x( inBuf, outBuf, width, height );
|
||||
// descale the CoCg values and set the scale factor effectively to 1
|
||||
for ( int i = 0; i < width * height; i++ ) {
|
||||
int scale = ( outBuf[i*4+2] >> 3 ) + 1;
|
||||
outBuf[i*4+0] = byte( ( outBuf[i*4+0] - 128 ) / scale + 128 );
|
||||
outBuf[i*4+1] = byte( ( outBuf[i*4+1] - 128 ) / scale + 128 );
|
||||
outBuf[i*4+2] = 0; // this translates to a scale factor of 1 for uncompressed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressYCoCgCTX1DXT5A
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressYCoCgCTX1DXT5A( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeAlphaValues( block, 3 );
|
||||
DecodeCTX1Values( block );
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecodeNormalYValues
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecodeNormalYValues( byte *normalBlock, const int offsetY, byte &c0, byte &c1 ) {
|
||||
int i;
|
||||
unsigned int indexes;
|
||||
unsigned short normal0, normal1;
|
||||
byte normalsY[4];
|
||||
|
||||
normal0 = ReadUShort();
|
||||
normal1 = ReadUShort();
|
||||
|
||||
assert( normal0 >= normal1 );
|
||||
|
||||
normalsY[0] = NormalYFrom565( normal0 );
|
||||
normalsY[1] = NormalYFrom565( normal1 );
|
||||
normalsY[2] = ( 2 * normalsY[0] + 1 * normalsY[1] ) / 3;
|
||||
normalsY[3] = ( 1 * normalsY[0] + 2 * normalsY[1] ) / 3;
|
||||
|
||||
c0 = NormalBiasFrom565( normal0 );
|
||||
c1 = NormalScaleFrom565( normal0 );
|
||||
|
||||
byte *normalYPtr = normalBlock + offsetY;
|
||||
|
||||
indexes = ReadUInt();
|
||||
for ( i = 0; i < 16; i++ ) {
|
||||
normalYPtr[i*4] = normalsY[indexes & 3];
|
||||
indexes >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
UShortSqrt
|
||||
========================
|
||||
*/
|
||||
byte UShortSqrt( unsigned short s ) {
|
||||
#if 1
|
||||
int t, b, r, x;
|
||||
|
||||
r = 0;
|
||||
for ( b = 0x10000000; b != 0; b >>= 2 ) {
|
||||
t = r + b;
|
||||
r >>= 1;
|
||||
x = -( t <= s );
|
||||
s = s - (unsigned short)( t & x );
|
||||
r += b & x;
|
||||
}
|
||||
return byte( r );
|
||||
#else
|
||||
int t, b, r;
|
||||
|
||||
r = 0;
|
||||
for ( b = 0x10000000; b != 0; b >>= 2 ) {
|
||||
t = r + b;
|
||||
r >>= 1;
|
||||
if ( t <= s ) {
|
||||
s -= t;
|
||||
r += b;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DeriveNormalZValues
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DeriveNormalZValues( byte *normalBlock ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < 16; i++ ) {
|
||||
int x = normalBlock[i*4+0] - 127;
|
||||
int y = normalBlock[i*4+1] - 127;
|
||||
normalBlock[i*4+2] = 128 + UShortSqrt( (unsigned short)( 16383 - x * x - y * y ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::UnRotateNormals
|
||||
========================
|
||||
*/
|
||||
void UnRotateNormals( const byte *block, float *normals, byte c0, byte c1 ) {
|
||||
int rotation = c0;
|
||||
float angle = -( rotation / 255.0f ) * idMath::PI;
|
||||
float s = sin( angle );
|
||||
float c = cos( angle );
|
||||
|
||||
int scale = ( c1 >> 3 ) + 1;
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
float x = block[i*4+0] / 255.0f * 2.0f - 1.0f;
|
||||
float y = ( ( block[i*4+1] - 128 ) / scale + 128 ) / 255.0f * 2.0f - 1.0f;
|
||||
float rx = c * x - s * y;
|
||||
float ry = s * x + c * y;
|
||||
normals[i*4+0] = rx;
|
||||
normals[i*4+1] = ry;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressNormalMapDXT1
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressNormalMapDXT1( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeColorValues( block, false, true );
|
||||
#if 1
|
||||
float normals[16*4];
|
||||
/*
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
normals[k*4+0] = block[k*4+0] / 255.0f * 2.0f - 1.0f;
|
||||
normals[k*4+1] = block[k*4+1] / 255.0f * 2.0f - 1.0f;
|
||||
}
|
||||
*/
|
||||
UnRotateNormals( block, normals, block[0*4+2], 0 );
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
float x = normals[k*4+0];
|
||||
float y = normals[k*4+1];
|
||||
float z = 1.0f - x * x - y * y;
|
||||
if ( z < 0.0f ) z = 0.0f;
|
||||
normals[k*4+2] = sqrt( z );
|
||||
}
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
block[k*4+0] = idMath::Ftob( ( normals[k*4+0] + 1.0f ) / 2.0f * 255.0f );
|
||||
block[k*4+1] = idMath::Ftob( ( normals[k*4+1] + 1.0f ) / 2.0f * 255.0f );
|
||||
block[k*4+2] = idMath::Ftob( ( normals[k*4+2] + 1.0f ) / 2.0f * 255.0f );
|
||||
}
|
||||
#else
|
||||
DeriveNormalZValues( block );
|
||||
#endif
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressNormalMapDXT1Renormalize
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressNormalMapDXT1Renormalize( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeColorValues( block, false, true );
|
||||
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
float normal[3];
|
||||
normal[0] = block[k*4+0] / 255.0f * 2.0f - 1.0f;
|
||||
normal[1] = block[k*4+1] / 255.0f * 2.0f - 1.0f;
|
||||
normal[2] = block[k*4+2] / 255.0f * 2.0f - 1.0f;
|
||||
float rsq = idMath::InvSqrt( normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2] );
|
||||
normal[0] *= rsq;
|
||||
normal[1] *= rsq;
|
||||
normal[2] *= rsq;
|
||||
block[k*4+0] = idMath::Ftob( ( normal[0] + 1.0f ) / 2.0f * 255.0f + 0.5f );
|
||||
block[k*4+1] = idMath::Ftob( ( normal[1] + 1.0f ) / 2.0f * 255.0f + 0.5f );
|
||||
block[k*4+2] = idMath::Ftob( ( normal[2] + 1.0f ) / 2.0f * 255.0f + 0.5f );
|
||||
}
|
||||
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressNormalMapDXT5Renormalize
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressNormalMapDXT5Renormalize( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeAlphaValues( block, 3 );
|
||||
DecodeColorValues( block, false, false );
|
||||
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
float normal[3];
|
||||
#if 0 // object-space
|
||||
normal[0] = block[k*4+0] / 255.0f * 2.0f - 1.0f;
|
||||
normal[1] = block[k*4+1] / 255.0f * 2.0f - 1.0f;
|
||||
normal[2] = block[k*4+3] / 255.0f * 2.0f - 1.0f;
|
||||
#else
|
||||
normal[0] = block[k*4+3] / 255.0f * 2.0f - 1.0f;
|
||||
normal[1] = block[k*4+1] / 255.0f * 2.0f - 1.0f;
|
||||
normal[2] = block[k*4+2] / 255.0f * 2.0f - 1.0f;
|
||||
#endif
|
||||
float rsq = idMath::InvSqrt( normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2] );
|
||||
normal[0] *= rsq;
|
||||
normal[1] *= rsq;
|
||||
normal[2] *= rsq;
|
||||
block[k*4+0] = idMath::Ftob( ( normal[0] + 1.0f ) / 2.0f * 255.0f + 0.5f );
|
||||
block[k*4+1] = idMath::Ftob( ( normal[1] + 1.0f ) / 2.0f * 255.0f + 0.5f );
|
||||
block[k*4+2] = idMath::Ftob( ( normal[2] + 1.0f ) / 2.0f * 255.0f + 0.5f );
|
||||
}
|
||||
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::BiasScaleNormalY
|
||||
========================
|
||||
*/
|
||||
void BiasScaleNormalY( byte *normals, const int offsetY, const byte c0, const byte c1 ) {
|
||||
int bias = c0 - 4;
|
||||
int scale = ( c1 >> 3 ) + 1;
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
normals[i*4+offsetY] = byte( ( normals[i*4+offsetY] - 128 ) / scale + bias );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::BiasScaleNormals
|
||||
========================
|
||||
*/
|
||||
void BiasScaleNormals( const byte *block, float *normals, const byte c0, const byte c1 ) {
|
||||
int bias = c0 - 4;
|
||||
int scale = ( c1 >> 3 ) + 1;
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
normals[i*4+0] = block[i*4+0] / 255.0f * 2.0f - 1.0f;
|
||||
normals[i*4+1] = ( ( block[i*4+1] - 128.0f ) / scale + bias ) / 255.0f * 2.0f - 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressNormalMapDXT5
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressNormalMapDXT5( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
byte c0, c1;
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeAlphaValues( block, 0 );
|
||||
DecodeNormalYValues( block, 1, c0, c1 );
|
||||
#if 1
|
||||
float normals[16*4];
|
||||
//BiasScaleNormals( block, normals, c0, c1 );
|
||||
UnRotateNormals( block, normals, c0, c1 );
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
float x = normals[k*4+0];
|
||||
float y = normals[k*4+1];
|
||||
float z = 1.0f - x * x - y * y;
|
||||
if ( z < 0.0f ) z = 0.0f;
|
||||
normals[k*4+2] = sqrt( z );
|
||||
}
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
block[k*4+0] = idMath::Ftob( ( normals[k*4+0] + 1.0f ) / 2.0f * 255.0f );
|
||||
block[k*4+1] = idMath::Ftob( ( normals[k*4+1] + 1.0f ) / 2.0f * 255.0f );
|
||||
block[k*4+2] = idMath::Ftob( ( normals[k*4+2] + 1.0f ) / 2.0f * 255.0f );
|
||||
}
|
||||
#else
|
||||
BiasScaleNormalY( block, 1, c0, c1 );
|
||||
DeriveNormalZValues( block );
|
||||
#endif
|
||||
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecompressNormalMapDXN2
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecompressNormalMapDXN2( const byte *inBuf, byte *outBuf, int width, int height ) {
|
||||
byte block[64];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecodeAlphaValues( block, 0 );
|
||||
DecodeAlphaValues( block, 1 );
|
||||
#if 1
|
||||
float normals[16*4];
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
normals[k*4+0] = block[k*4+0] / 255.0f * 2.0f - 1.0f;
|
||||
normals[k*4+1] = block[k*4+1] / 255.0f * 2.0f - 1.0f;
|
||||
}
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
float x = normals[k*4+0];
|
||||
float y = normals[k*4+1];
|
||||
float z = 1.0f - x * x - y * y;
|
||||
if ( z < 0.0f ) z = 0.0f;
|
||||
normals[k*4+2] = sqrt( z );
|
||||
}
|
||||
for ( int k = 0; k < 16; k++ ) {
|
||||
block[k*4+0] = idMath::Ftob( ( normals[k*4+0] + 1.0f ) / 2.0f * 255.0f );
|
||||
block[k*4+1] = idMath::Ftob( ( normals[k*4+1] + 1.0f ) / 2.0f * 255.0f );
|
||||
block[k*4+2] = idMath::Ftob( ( normals[k*4+2] + 1.0f ) / 2.0f * 255.0f );
|
||||
}
|
||||
#else
|
||||
DeriveNormalZValues( block );
|
||||
#endif
|
||||
EmitBlock( outBuf, i, j, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecomposeColorBlock
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecomposeColorBlock( byte colors[2][4], byte colorIndices[16], bool noBlack ) {
|
||||
int i;
|
||||
unsigned int indices;
|
||||
unsigned short color0, color1;
|
||||
int colorRemap1[] = { 3, 0, 2, 1 };
|
||||
int colorRemap2[] = { 1, 3, 2, 0 };
|
||||
int *crm;
|
||||
|
||||
color0 = ReadUShort();
|
||||
color1 = ReadUShort();
|
||||
|
||||
ColorFrom565( color0, colors[0] );
|
||||
ColorFrom565( color1, colors[1] );
|
||||
|
||||
if ( noBlack || color0 > color1 ) {
|
||||
crm = colorRemap1;
|
||||
} else {
|
||||
crm = colorRemap2;
|
||||
}
|
||||
|
||||
indices = ReadUInt();
|
||||
for ( i = 0; i < 16; i++ ) {
|
||||
colorIndices[i] = (byte)crm[ indices & 3 ];
|
||||
indices >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecomposeAlphaBlock
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecomposeAlphaBlock( byte colors[2][4], byte alphaIndices[16] ) {
|
||||
int i;
|
||||
unsigned char alpha0, alpha1;
|
||||
unsigned int indices;
|
||||
int alphaRemap1[] = { 7, 0, 6, 5, 4, 3, 2, 1 };
|
||||
int alphaRemap2[] = { 1, 6, 2, 3, 4, 5, 0, 7 };
|
||||
int *arm;
|
||||
|
||||
alpha0 = ReadByte();
|
||||
alpha1 = ReadByte();
|
||||
|
||||
colors[0][3] = alpha0;
|
||||
colors[1][3] = alpha1;
|
||||
|
||||
if ( alpha0 > alpha1 ) {
|
||||
arm = alphaRemap1;
|
||||
} else {
|
||||
arm = alphaRemap2;
|
||||
}
|
||||
|
||||
indices = (int)ReadByte() | ( (int)ReadByte() << 8 ) | ( (int)ReadByte() << 16 );
|
||||
for ( i = 0; i < 8; i++ ) {
|
||||
alphaIndices[i] = (byte)arm[ indices & 7 ];
|
||||
indices >>= 3;
|
||||
}
|
||||
|
||||
indices = (int)ReadByte() | ( (int)ReadByte() << 8 ) | ( (int)ReadByte() << 16 );
|
||||
for ( i = 8; i < 16; i++ ) {
|
||||
alphaIndices[i] = (byte)arm[ indices & 7 ];
|
||||
indices >>= 3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecomposeImageDXT1
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecomposeImageDXT1( const byte *inBuf, byte *colorIndices, byte *pic1, byte *pic2, int width, int height ) {
|
||||
byte colors[2][4];
|
||||
byte indices[16];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
// extract the colors from the DXT
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecomposeColorBlock( colors, indices, false );
|
||||
|
||||
memcpy( colorIndices + (j+0) * width + i, indices+ 0, 4 );
|
||||
memcpy( colorIndices + (j+1) * width + i, indices+ 4, 4 );
|
||||
memcpy( colorIndices + (j+2) * width + i, indices+ 8, 4 );
|
||||
memcpy( colorIndices + (j+3) * width + i, indices+12, 4 );
|
||||
|
||||
memcpy( pic1 + j * width / 4 + i, colors[0], 4 );
|
||||
|
||||
memcpy( pic2 + j * width / 4 + i, colors[1], 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idDxtDecoder::DecomposeImageDXT5
|
||||
========================
|
||||
*/
|
||||
void idDxtDecoder::DecomposeImageDXT5( const byte *inBuf, byte *colorIndices, byte *alphaIndices, byte *pic1, byte *pic2, int width, int height ) {
|
||||
byte colors[2][4];
|
||||
byte colorInd[16];
|
||||
byte alphaInd[16];
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->inData = inBuf;
|
||||
|
||||
// extract the colors from the DXT
|
||||
for ( int j = 0; j < height; j += 4 ) {
|
||||
for ( int i = 0; i < width; i += 4 ) {
|
||||
DecomposeAlphaBlock( colors, alphaInd );
|
||||
DecomposeColorBlock( colors, colorInd, true );
|
||||
|
||||
memcpy( colorIndices + (j+0) * width + i, colorInd+ 0, 4 );
|
||||
memcpy( colorIndices + (j+1) * width + i, colorInd+ 4, 4 );
|
||||
memcpy( colorIndices + (j+2) * width + i, colorInd+ 8, 4 );
|
||||
memcpy( colorIndices + (j+3) * width + i, colorInd+12, 4 );
|
||||
|
||||
memcpy( colorIndices + (j+0) * width + i, alphaInd+ 0, 4 );
|
||||
memcpy( colorIndices + (j+1) * width + i, alphaInd+ 4, 4 );
|
||||
memcpy( colorIndices + (j+2) * width + i, alphaInd+ 8, 4 );
|
||||
memcpy( colorIndices + (j+3) * width + i, alphaInd+12, 4 );
|
||||
|
||||
memcpy( pic1 + j * width / 4 + i, colors[0], 4 );
|
||||
|
||||
memcpy( pic2 + j * width / 4 + i, colors[1], 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4691
neo/renderer/DXT/DXTEncoder.cpp
Normal file
4691
neo/renderer/DXT/DXTEncoder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1580
neo/renderer/DXT/DXTEncoder_SSE2.cpp
Normal file
1580
neo/renderer/DXT/DXTEncoder_SSE2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user