crossxtex/DirectXTex/BC4BC5.cpp

562 lines
17 KiB
C++
Raw Normal View History

2016-08-22 18:26:36 +00:00
//-------------------------------------------------------------------------------------
// BC4BC5.cpp
//
// Block-compression (BC) functionality for BC4 and BC5 (DirectX 10 texture compression)
//
// Copyright (c) Microsoft Corporation. All rights reserved.
2018-02-24 06:24:46 +00:00
// Licensed under the MIT License.
2016-08-22 18:26:36 +00:00
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
#include "directxtexp.h"
#include "BC.h"
2016-09-09 02:09:46 +00:00
using namespace DirectX;
2016-08-22 18:26:36 +00:00
//------------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------------
// Because these are used in SAL annotations, they need to remain macros rather than const values
#define BLOCK_LEN 4
2016-09-09 02:09:46 +00:00
// length of each block in texel
2016-08-22 18:26:36 +00:00
#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN)
2016-09-09 02:09:46 +00:00
// total texels in a 4x4 block.
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
namespace
{
//------------------------------------------------------------------------------------
// Structures
//-------------------------------------------------------------------------------------
2016-08-22 18:26:36 +00:00
#pragma warning(push)
#pragma warning(disable : 4201)
2016-09-09 02:09:46 +00:00
// BC4U/BC5U
struct BC4_UNORM
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
float R(size_t uOffset) const
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
float DecodeFromIndex(size_t uIndex) const
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
if (uIndex == 0)
return red_0 / 255.0f;
if (uIndex == 1)
return red_1 / 255.0f;
float fred_0 = red_0 / 255.0f;
float fred_1 = red_1 / 255.0f;
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
if (uIndex == 6)
return 0.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
}
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
size_t GetIndex(size_t uOffset) const
{
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
}
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
}
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
union
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
struct
{
uint8_t red_0;
uint8_t red_1;
uint8_t indices[6];
};
uint64_t data;
2016-08-22 18:26:36 +00:00
};
};
2016-09-09 02:09:46 +00:00
// BC4S/BC5S
struct BC4_SNORM
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
float R(size_t uOffset) const
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
float DecodeFromIndex(size_t uIndex) const
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
int8_t sred_0 = (red_0 == -128) ? -127 : red_0;
int8_t sred_1 = (red_1 == -128) ? -127 : red_1;
if (uIndex == 0)
return sred_0 / 127.0f;
if (uIndex == 1)
return sred_1 / 127.0f;
float fred_0 = sred_0 / 127.0f;
float fred_1 = sred_1 / 127.0f;
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
if (uIndex == 6)
return -1.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
}
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
size_t GetIndex(size_t uOffset) const
{
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
}
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
}
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
union
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
struct
{
int8_t red_0;
int8_t red_1;
uint8_t indices[6];
};
uint64_t data;
2016-08-22 18:26:36 +00:00
};
};
#pragma warning(pop)
2016-09-09 02:09:46 +00:00
//-------------------------------------------------------------------------------------
// Convert a floating point value to an 8-bit SNORM
//-------------------------------------------------------------------------------------
void inline FloatToSNorm(_In_ float fVal, _Out_ int8_t *piSNorm)
{
const uint32_t dwMostNeg = (1 << (8 * sizeof(int8_t) - 1));
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
if (_isnan(fVal))
fVal = 0;
2016-08-22 18:26:36 +00:00
else
2016-09-09 02:09:46 +00:00
if (fVal > 1)
fVal = 1; // Clamp to 1
else
if (fVal < -1)
fVal = -1; // Clamp to -1
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
fVal = fVal * (int8_t)(dwMostNeg - 1);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
if (fVal >= 0)
fVal += .5f;
else
fVal -= .5f;
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
*piSNorm = (int8_t)(fVal);
}
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
//------------------------------------------------------------------------------
void FindEndPointsBC4U(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_Out_ uint8_t &endpointU_0,
_Out_ uint8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
2017-01-05 21:48:23 +00:00
const float MIN_NORM = 0.f;
const float MAX_NORM = 1.f;
2016-09-09 02:09:46 +00:00
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
2017-01-05 21:48:23 +00:00
for (size_t i = 0; i < BLOCK_SIZE; ++i)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
if (theTexelsU[i] < fBlockMin)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i] > fBlockMax)
{
fBlockMax = theTexelsU[i];
}
2016-08-22 18:26:36 +00:00
}
2017-01-05 21:48:23 +00:00
// If there are boundary values in input texels, should use 4 interpolated color values to guarantee
2016-09-09 02:09:46 +00:00
// the exact code of the boundary values.
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
// Using Optimize
float fStart, fEnd;
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
if (!bUsing4BlockCodec)
{
2017-01-05 21:48:23 +00:00
// 6 interpolated color values
2016-09-09 02:09:46 +00:00
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
2016-08-22 18:26:36 +00:00
2017-01-05 21:48:23 +00:00
uint8_t iStart = static_cast<uint8_t>(fStart * 255.0f);
uint8_t iEnd = static_cast<uint8_t>(fEnd * 255.0f);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
{
2017-01-05 21:48:23 +00:00
// 4 interpolated color values
2016-09-09 02:09:46 +00:00
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
2016-08-22 18:26:36 +00:00
2017-01-05 21:48:23 +00:00
uint8_t iStart = static_cast<uint8_t>(fStart * 255.0f);
uint8_t iEnd = static_cast<uint8_t>(fEnd * 255.0f);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
void FindEndPointsBC4S(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_Out_ int8_t &endpointU_0,
_Out_ int8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
2017-01-05 21:48:23 +00:00
const float MIN_NORM = -1.f;
const float MAX_NORM = 1.f;
2016-09-09 02:09:46 +00:00
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
2017-01-05 21:48:23 +00:00
for (size_t i = 0; i < BLOCK_SIZE; ++i)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
if (theTexelsU[i] < fBlockMin)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i] > fBlockMax)
{
fBlockMax = theTexelsU[i];
}
2016-08-22 18:26:36 +00:00
}
2017-01-05 21:48:23 +00:00
// If there are boundary values in input texels, should use 4 interpolated color values to guarantee
2016-09-09 02:09:46 +00:00
// the exact code of the boundary values.
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
// Using Optimize
float fStart, fEnd;
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
if (!bUsing4BlockCodec)
{
2017-01-05 21:48:23 +00:00
// 6 interpolated color values
2016-09-09 02:09:46 +00:00
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 8);
2016-08-22 18:26:36 +00:00
2017-01-05 21:48:23 +00:00
int8_t iStart, iEnd;
2016-09-09 02:09:46 +00:00
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
{
2017-01-05 21:48:23 +00:00
// 4 interpolated color values
2016-09-09 02:09:46 +00:00
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 6);
2016-08-22 18:26:36 +00:00
2017-01-05 21:48:23 +00:00
int8_t iStart, iEnd;
2016-09-09 02:09:46 +00:00
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
//------------------------------------------------------------------------------
inline void FindEndPointsBC5U(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ uint8_t &endpointU_0,
_Out_ uint8_t &endpointU_1,
_Out_ uint8_t &endpointV_0,
_Out_ uint8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4U(theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4U(theTexelsV, endpointV_0, endpointV_1);
}
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
inline void FindEndPointsBC5S(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ int8_t &endpointU_0,
_Out_ int8_t &endpointU_1,
_Out_ int8_t &endpointV_0,
_Out_ int8_t &endpointV_1)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4S(theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4S(theTexelsV, endpointV_0, endpointV_1);
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
//------------------------------------------------------------------------------
void FindClosestUNORM(
_Inout_ BC4_UNORM* pBC,
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
float rGradient[8];
2017-01-05 21:48:23 +00:00
for (size_t i = 0; i < 8; ++i)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
rGradient[i] = pBC->DecodeFromIndex(i);
}
2017-01-05 21:48:23 +00:00
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
2016-09-09 02:09:46 +00:00
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
}
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
pBC->SetIndex(i, uBestIndex);
2016-08-22 18:26:36 +00:00
}
}
2016-09-09 02:09:46 +00:00
void FindClosestSNORM(
_Inout_ BC4_SNORM* pBC,
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
float rGradient[8];
2017-01-05 21:48:23 +00:00
for (size_t i = 0; i < 8; ++i)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
rGradient[i] = pBC->DecodeFromIndex(i);
}
2017-01-05 21:48:23 +00:00
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
2016-09-09 02:09:46 +00:00
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
}
2016-08-22 18:26:36 +00:00
}
2016-09-09 02:09:46 +00:00
pBC->SetIndex(i, uBestIndex);
2016-08-22 18:26:36 +00:00
}
}
}
//=====================================================================================
// Entry points
//=====================================================================================
//-------------------------------------------------------------------------------------
// BC4 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXDecodeBC4U(XMVECTOR *pColor, const uint8_t *pBC)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
assert(pColor && pBC);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
2016-09-09 02:09:46 +00:00
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
}
2016-08-22 18:26:36 +00:00
}
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
assert(pColor && pBC);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
2016-09-09 02:09:46 +00:00
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
}
2016-08-22 18:26:36 +00:00
}
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXEncodeBC4U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
UNREFERENCED_PARAMETER(flags);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
assert(pBC && pColor);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
float theTexelsU[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
2016-09-09 02:09:46 +00:00
theTexelsU[i] = XMVectorGetX(pColor[i]);
2016-08-22 18:26:36 +00:00
}
FindEndPointsBC4U(theTexelsU, pBC4->red_0, pBC4->red_1);
FindClosestUNORM(pBC4, theTexelsU);
}
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXEncodeBC4S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
UNREFERENCED_PARAMETER(flags);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
assert(pBC && pColor);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
float theTexelsU[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
2016-09-09 02:09:46 +00:00
theTexelsU[i] = XMVectorGetX(pColor[i]);
2016-08-22 18:26:36 +00:00
}
FindEndPointsBC4S(theTexelsU, pBC4->red_0, pBC4->red_1);
FindClosestSNORM(pBC4, theTexelsU);
}
//-------------------------------------------------------------------------------------
// BC5 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
assert(pColor && pBC);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
auto pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
2016-09-09 02:09:46 +00:00
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
2016-08-22 18:26:36 +00:00
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
2016-09-09 02:09:46 +00:00
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
2016-08-22 18:26:36 +00:00
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
2016-09-09 02:09:46 +00:00
}
2016-08-22 18:26:36 +00:00
}
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
assert(pColor && pBC);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
auto pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
2016-09-09 02:09:46 +00:00
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
2016-08-22 18:26:36 +00:00
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
2016-09-09 02:09:46 +00:00
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
2016-08-22 18:26:36 +00:00
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
2016-09-09 02:09:46 +00:00
}
2016-08-22 18:26:36 +00:00
}
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXEncodeBC5U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
UNREFERENCED_PARAMETER(flags);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
assert(pBC && pColor);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
2016-08-22 18:26:36 +00:00
auto pBCR = reinterpret_cast<BC4_UNORM*>(pBC);
2016-09-09 02:09:46 +00:00
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
2016-08-22 18:26:36 +00:00
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
2016-09-09 02:09:46 +00:00
{
2016-08-22 18:26:36 +00:00
XMFLOAT4A clr;
2016-09-09 02:09:46 +00:00
XMStoreFloat4A(&clr, pColor[i]);
2016-08-22 18:26:36 +00:00
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
FindEndPointsBC5U(
theTexelsU,
theTexelsV,
pBCR->red_0,
pBCR->red_1,
pBCG->red_0,
pBCG->red_1);
FindClosestUNORM(pBCR, theTexelsU);
FindClosestUNORM(pBCG, theTexelsV);
}
_Use_decl_annotations_
2016-09-09 02:09:46 +00:00
void DirectX::D3DXEncodeBC5S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
2016-08-22 18:26:36 +00:00
{
2016-09-09 02:09:46 +00:00
UNREFERENCED_PARAMETER(flags);
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
assert(pBC && pColor);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
2016-08-22 18:26:36 +00:00
2016-09-09 02:09:46 +00:00
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
2016-08-22 18:26:36 +00:00
auto pBCR = reinterpret_cast<BC4_SNORM*>(pBC);
2016-09-09 02:09:46 +00:00
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
2016-08-22 18:26:36 +00:00
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMFLOAT4A clr;
2016-09-09 02:09:46 +00:00
XMStoreFloat4A(&clr, pColor[i]);
2016-08-22 18:26:36 +00:00
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
FindEndPointsBC5S(
theTexelsU,
theTexelsV,
pBCR->red_0,
pBCR->red_1,
pBCG->red_0,
pBCG->red_1);
FindClosestSNORM(pBCR, theTexelsU);
FindClosestSNORM(pBCG, theTexelsV);
2016-09-09 02:09:46 +00:00
}