Improve normal map VRAM Compression with RGTC
This commit is contained in:
parent
7233bc6736
commit
5837e1fe3f
|
@ -13,6 +13,7 @@ thirdparty_dir = "#thirdparty/etcpak/"
|
||||||
thirdparty_sources = [
|
thirdparty_sources = [
|
||||||
"Dither.cpp",
|
"Dither.cpp",
|
||||||
"ProcessDxtc.cpp",
|
"ProcessDxtc.cpp",
|
||||||
|
"ProcessRgtc.cpp",
|
||||||
"ProcessRGB.cpp",
|
"ProcessRGB.cpp",
|
||||||
"Tables.cpp",
|
"Tables.cpp",
|
||||||
]
|
]
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include <ProcessDxtc.hpp>
|
#include <ProcessDxtc.hpp>
|
||||||
#include <ProcessRGB.hpp>
|
#include <ProcessRGB.hpp>
|
||||||
|
#include <ProcessRgtc.hpp>
|
||||||
|
|
||||||
EtcpakType _determine_etc_type(Image::UsedChannels p_channels) {
|
EtcpakType _determine_etc_type(Image::UsedChannels p_channels) {
|
||||||
switch (p_channels) {
|
switch (p_channels) {
|
||||||
|
@ -62,9 +63,9 @@ EtcpakType _determine_dxt_type(Image::UsedChannels p_channels) {
|
||||||
case Image::USED_CHANNELS_LA:
|
case Image::USED_CHANNELS_LA:
|
||||||
return EtcpakType::ETCPAK_TYPE_DXT5;
|
return EtcpakType::ETCPAK_TYPE_DXT5;
|
||||||
case Image::USED_CHANNELS_R:
|
case Image::USED_CHANNELS_R:
|
||||||
return EtcpakType::ETCPAK_TYPE_DXT5;
|
return EtcpakType::ETCPAK_TYPE_RGTC_R;
|
||||||
case Image::USED_CHANNELS_RG:
|
case Image::USED_CHANNELS_RG:
|
||||||
return EtcpakType::ETCPAK_TYPE_DXT5_RA_AS_RG;
|
return EtcpakType::ETCPAK_TYPE_RGTC_RG;
|
||||||
case Image::USED_CHANNELS_RGB:
|
case Image::USED_CHANNELS_RGB:
|
||||||
return EtcpakType::ETCPAK_TYPE_DXT1;
|
return EtcpakType::ETCPAK_TYPE_DXT1;
|
||||||
case Image::USED_CHANNELS_RGBA:
|
case Image::USED_CHANNELS_RGBA:
|
||||||
|
@ -127,6 +128,10 @@ void _compress_etcpak(EtcpakType p_compresstype, Image *r_img) {
|
||||||
r_img->convert_rg_to_ra_rgba8();
|
r_img->convert_rg_to_ra_rgba8();
|
||||||
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_DXT5) {
|
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_DXT5) {
|
||||||
target_format = Image::FORMAT_DXT5;
|
target_format = Image::FORMAT_DXT5;
|
||||||
|
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_RGTC_R) {
|
||||||
|
target_format = Image::FORMAT_RGTC_R;
|
||||||
|
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_RGTC_RG) {
|
||||||
|
target_format = Image::FORMAT_RGTC_RG;
|
||||||
} else {
|
} else {
|
||||||
ERR_FAIL_MSG("Invalid or unsupported etcpak compression format, not ETC or DXT.");
|
ERR_FAIL_MSG("Invalid or unsupported etcpak compression format, not ETC or DXT.");
|
||||||
}
|
}
|
||||||
|
@ -229,6 +234,10 @@ void _compress_etcpak(EtcpakType p_compresstype, Image *r_img) {
|
||||||
CompressDxt1Dither(src_mip_read, dest_mip_write, blocks, mip_w);
|
CompressDxt1Dither(src_mip_read, dest_mip_write, blocks, mip_w);
|
||||||
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_DXT5 || p_compresstype == EtcpakType::ETCPAK_TYPE_DXT5_RA_AS_RG) {
|
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_DXT5 || p_compresstype == EtcpakType::ETCPAK_TYPE_DXT5_RA_AS_RG) {
|
||||||
CompressDxt5(src_mip_read, dest_mip_write, blocks, mip_w);
|
CompressDxt5(src_mip_read, dest_mip_write, blocks, mip_w);
|
||||||
|
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_RGTC_RG) {
|
||||||
|
CompressRgtcRG(src_mip_read, dest_mip_write, blocks, mip_w);
|
||||||
|
} else if (p_compresstype == EtcpakType::ETCPAK_TYPE_RGTC_R) {
|
||||||
|
CompressRgtcR(src_mip_read, dest_mip_write, blocks, mip_w);
|
||||||
} else {
|
} else {
|
||||||
ERR_FAIL_MSG("etcpak: Invalid or unsupported compression format.");
|
ERR_FAIL_MSG("etcpak: Invalid or unsupported compression format.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,8 @@ enum class EtcpakType {
|
||||||
ETCPAK_TYPE_DXT1,
|
ETCPAK_TYPE_DXT1,
|
||||||
ETCPAK_TYPE_DXT5,
|
ETCPAK_TYPE_DXT5,
|
||||||
ETCPAK_TYPE_DXT5_RA_AS_RG,
|
ETCPAK_TYPE_DXT5_RA_AS_RG,
|
||||||
|
ETCPAK_TYPE_RGTC_R,
|
||||||
|
ETCPAK_TYPE_RGTC_RG,
|
||||||
};
|
};
|
||||||
|
|
||||||
void _compress_etc1(Image *r_img);
|
void _compress_etc1(Image *r_img);
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
// -- GODOT start --
|
||||||
|
|
||||||
|
#include "ForceInline.hpp"
|
||||||
|
#include "ProcessRgtc.hpp"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const uint8_t AlphaIndexTable[8] = { 1, 7, 6, 5, 4, 3, 2, 0 };
|
||||||
|
|
||||||
|
static etcpak_force_inline uint64_t ProcessAlpha( const uint8_t* src )
|
||||||
|
{
|
||||||
|
uint8_t solid8 = *src;
|
||||||
|
uint16_t solid16 = uint16_t( solid8 ) | ( uint16_t( solid8 ) << 8 );
|
||||||
|
uint32_t solid32 = uint32_t( solid16 ) | ( uint32_t( solid16 ) << 16 );
|
||||||
|
uint64_t solid64 = uint64_t( solid32 ) | ( uint64_t( solid32 ) << 32 );
|
||||||
|
if( memcmp( src, &solid64, 8 ) == 0 && memcmp( src+8, &solid64, 8 ) == 0 )
|
||||||
|
{
|
||||||
|
return solid8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t min = src[0];
|
||||||
|
uint8_t max = min;
|
||||||
|
for( int i=1; i<16; i++ )
|
||||||
|
{
|
||||||
|
const auto v = src[i];
|
||||||
|
if( v > max ) max = v;
|
||||||
|
else if( v < min ) min = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t range = ( 8 << 13 ) / ( 1 + max - min );
|
||||||
|
uint64_t data = 0;
|
||||||
|
for( int i=0; i<16; i++ )
|
||||||
|
{
|
||||||
|
uint8_t a = src[i] - min;
|
||||||
|
uint64_t idx = AlphaIndexTable[( a * range ) >> 13];
|
||||||
|
data |= idx << (i*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return max | ( min << 8 ) | ( data << 16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompressRgtcR(const uint32_t *src, uint64_t *dst, uint32_t blocks, size_t width)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
auto ptr = dst;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uint32_t rgba[4 * 4];
|
||||||
|
uint8_t r[4 * 4];
|
||||||
|
|
||||||
|
auto tmp = (char *)rgba;
|
||||||
|
memcpy(tmp, src + width * 0, 4 * 4);
|
||||||
|
memcpy(tmp + 4 * 4, src + width * 1, 4 * 4);
|
||||||
|
memcpy(tmp + 8 * 4, src + width * 2, 4 * 4);
|
||||||
|
memcpy(tmp + 12 * 4, src + width * 3, 4 * 4);
|
||||||
|
src += 4;
|
||||||
|
if (++i == width / 4)
|
||||||
|
{
|
||||||
|
src += width * 3;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
r[i] = rgba[i] & 0x000000FF;
|
||||||
|
}
|
||||||
|
*ptr++ = ProcessAlpha(r);
|
||||||
|
}
|
||||||
|
while (--blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompressRgtcRG(const uint32_t *src, uint64_t *dst, uint32_t blocks, size_t width)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
auto ptr = dst;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uint32_t rgba[4 * 4];
|
||||||
|
uint8_t r[4 * 4];
|
||||||
|
uint8_t g[4 * 4];
|
||||||
|
|
||||||
|
auto tmp = (char *)rgba;
|
||||||
|
memcpy(tmp, src + width * 0, 4 * 4);
|
||||||
|
memcpy(tmp + 4 * 4, src + width * 1, 4 * 4);
|
||||||
|
memcpy(tmp + 8 * 4, src + width * 2, 4 * 4);
|
||||||
|
memcpy(tmp + 12 * 4, src + width * 3, 4 * 4);
|
||||||
|
src += 4;
|
||||||
|
if (++i == width / 4)
|
||||||
|
{
|
||||||
|
src += width * 3;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
r[i] = rgba[i] & 0x000000FF;
|
||||||
|
g[i] = (rgba[i] & 0x0000FF00) >> 8;
|
||||||
|
}
|
||||||
|
*ptr++ = ProcessAlpha(r);
|
||||||
|
*ptr++ = ProcessAlpha(g);
|
||||||
|
}
|
||||||
|
while (--blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- GODOT end --
|
|
@ -0,0 +1,14 @@
|
||||||
|
// -- GODOT start --
|
||||||
|
|
||||||
|
#ifndef __PROCESSRGTC_HPP__
|
||||||
|
#define __PROCESSRGTC_HPP__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void CompressRgtcR(const uint32_t *src, uint64_t *dst, uint32_t blocks, size_t width);
|
||||||
|
void CompressRgtcRG(const uint32_t *src, uint64_t *dst, uint32_t blocks, size_t width);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// -- GODOT end --
|
Loading…
Reference in New Issue