mirror of https://github.com/AxioDL/metaforce.git
Specialized C8PC format for indexed image data
This commit is contained in:
parent
b9de12223f
commit
8b234fafb8
|
@ -88,6 +88,12 @@ static inline uint8_t Convert6To8(uint8_t v)
|
|||
return (v << 2) | (v >> 4);
|
||||
}
|
||||
|
||||
static inline uint16_t Convert8To16(uint16_t v)
|
||||
{
|
||||
/* Swizzle bits: 01234567 -> 0123456701234567 */
|
||||
return (v << 8) | v;
|
||||
}
|
||||
|
||||
static inline uint8_t Lookup4BPP(const uint8_t* texels, int width, int x, int y)
|
||||
{
|
||||
int bwidth = (width + 7) / 8;
|
||||
|
@ -299,10 +305,10 @@ static const uint8_t* DecodePaletteSPLT(png_structrp png, png_infop info,
|
|||
GXEntry.name = (char*)"GX_IA8";
|
||||
for (int e=0 ; e<numEntries ; ++e)
|
||||
{
|
||||
entries[e].red = data[e*2];
|
||||
entries[e].green = data[e*2];
|
||||
entries[e].blue = data[e*2];
|
||||
entries[e].alpha = data[e*2+1];
|
||||
entries[e].red = Convert8To16(data[e*2]);
|
||||
entries[e].green = Convert8To16(data[e*2]);
|
||||
entries[e].blue = Convert8To16(data[e*2]);
|
||||
entries[e].alpha = Convert8To16(data[e*2+1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -314,10 +320,10 @@ static const uint8_t* DecodePaletteSPLT(png_structrp png, png_infop info,
|
|||
for (int e=0 ; e<numEntries ; ++e)
|
||||
{
|
||||
uint16_t texel = hecl::SBig(data16[e]);
|
||||
entries[e].red = Convert5To8(texel >> 11 & 0x1f);
|
||||
entries[e].green = Convert6To8(texel >> 5 & 0x3f);
|
||||
entries[e].blue = Convert5To8(texel & 0x1f);
|
||||
entries[e].alpha = 0xff;
|
||||
entries[e].red = Convert8To16(Convert5To8(texel >> 11 & 0x1f));
|
||||
entries[e].green = Convert8To16(Convert6To8(texel >> 5 & 0x3f));
|
||||
entries[e].blue = Convert8To16(Convert5To8(texel & 0x1f));
|
||||
entries[e].alpha = Convert8To16(0xff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -331,17 +337,17 @@ static const uint8_t* DecodePaletteSPLT(png_structrp png, png_infop info,
|
|||
uint16_t texel = hecl::SBig(data16[e]);
|
||||
if (texel & 0x8000)
|
||||
{
|
||||
entries[e].red = Convert5To8(texel >> 10 & 0x1f);
|
||||
entries[e].green = Convert5To8(texel >> 5 & 0x1f);
|
||||
entries[e].blue = Convert5To8(texel & 0x1f);
|
||||
entries[e].alpha = 0xff;
|
||||
entries[e].red = Convert8To16(Convert5To8(texel >> 10 & 0x1f));
|
||||
entries[e].green = Convert8To16(Convert5To8(texel >> 5 & 0x1f));
|
||||
entries[e].blue = Convert8To16(Convert5To8(texel & 0x1f));
|
||||
entries[e].alpha = Convert8To16(0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
entries[e].red = Convert4To8(texel >> 8 & 0xf);
|
||||
entries[e].green = Convert4To8(texel >> 4 & 0xf);
|
||||
entries[e].blue = Convert4To8(texel & 0xf);
|
||||
entries[e].alpha = Convert3To8(texel >> 12 & 0x7);
|
||||
entries[e].red = Convert8To16(Convert4To8(texel >> 8 & 0xf));
|
||||
entries[e].green = Convert8To16(Convert4To8(texel >> 4 & 0xf));
|
||||
entries[e].blue = Convert8To16(Convert4To8(texel & 0xf));
|
||||
entries[e].alpha = Convert8To16(Convert3To8(texel >> 12 & 0x7));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -603,6 +609,137 @@ bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
|||
return true;
|
||||
}
|
||||
|
||||
static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, size_t& szOut)
|
||||
{
|
||||
std::unique_ptr<uint8_t[]> ret;
|
||||
png_sPLT_tp palettes;
|
||||
int paletteCount = png_get_sPLT(png, info, &palettes);
|
||||
if (paletteCount)
|
||||
{
|
||||
for (int i=0 ; i<paletteCount ; ++i)
|
||||
{
|
||||
png_sPLT_tp palette = &palettes[i];
|
||||
if (!strcmp(palette->name, "GXPalette"))
|
||||
{
|
||||
if (palette->nentries > 16)
|
||||
{
|
||||
/* This is a C8 palette */
|
||||
ret.reset(new uint8_t[4 * 257]);
|
||||
szOut = 4 * 257;
|
||||
*reinterpret_cast<uint32_t*>(ret.get()) = hecl::SBig(256);
|
||||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j=0 ; j<256 ; ++j)
|
||||
{
|
||||
if (j < palette->nentries)
|
||||
{
|
||||
png_sPLT_entryp entry = &palette->entries[j];
|
||||
*cur++ = entry->red >> 8;
|
||||
*cur++ = entry->green >> 8;
|
||||
*cur++ = entry->blue >> 8;
|
||||
*cur++ = entry->alpha >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a C4 palette */
|
||||
ret.reset(new uint8_t[4 * 17]);
|
||||
szOut = 4 * 17;
|
||||
*reinterpret_cast<uint32_t*>(ret.get()) = hecl::SBig(16);
|
||||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j=0 ; j<16 ; ++j)
|
||||
{
|
||||
if (j < palette->nentries)
|
||||
{
|
||||
png_sPLT_entryp entry = &palette->entries[j];
|
||||
*cur++ = entry->red >> 8;
|
||||
*cur++ = entry->green >> 8;
|
||||
*cur++ = entry->blue >> 8;
|
||||
*cur++ = entry->alpha >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
png_colorp palettes;
|
||||
int colorCount;
|
||||
if (png_get_PLTE(png, info, &palettes, &colorCount) == PNG_INFO_PLTE)
|
||||
{
|
||||
if (colorCount > 16)
|
||||
{
|
||||
/* This is a C8 palette */
|
||||
ret.reset(new uint8_t[4 * 257]);
|
||||
szOut = 4 * 257;
|
||||
*reinterpret_cast<uint32_t*>(ret.get()) = hecl::SBig(256);
|
||||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j=0 ; j<256 ; ++j)
|
||||
{
|
||||
if (j < colorCount)
|
||||
{
|
||||
png_colorp entry = &palettes[j];
|
||||
*cur++ = entry->red;
|
||||
*cur++ = entry->green;
|
||||
*cur++ = entry->blue;
|
||||
*cur++ = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a C4 palette */
|
||||
ret.reset(new uint8_t[4 * 17]);
|
||||
szOut = 4 * 17;
|
||||
*reinterpret_cast<uint32_t*>(ret.get()) = hecl::SBig(16);
|
||||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j=0 ; j<16 ; ++j)
|
||||
{
|
||||
if (j < colorCount)
|
||||
{
|
||||
png_colorp entry = &palettes[j];
|
||||
*cur++ = entry->red;
|
||||
*cur++ = entry->green;
|
||||
*cur++ = entry->blue;
|
||||
*cur++ = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
*cur++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
return false;
|
||||
|
@ -692,7 +829,11 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> paletteBuf;
|
||||
size_t paletteSize = 0;
|
||||
|
||||
size_t rowSize = 0;
|
||||
size_t nComps = 4;
|
||||
switch (colorType)
|
||||
{
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
|
@ -707,6 +848,11 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
rowSize = width * 4;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
rowSize = width;
|
||||
nComps = 1;
|
||||
paletteBuf = ReadPalette(pngRead, info, paletteSize);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Error, _S("unsupported color type in '%s'"),
|
||||
inPath.getAbsolutePath().c_str());
|
||||
|
@ -722,9 +868,9 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
std::unique_ptr<uint8_t[]> bufOut;
|
||||
size_t bufLen = 0;
|
||||
if (numMips > 1)
|
||||
bufLen = ComputeMippedTexelCount(width, height) * 4;
|
||||
bufLen = ComputeMippedTexelCount(width, height) * nComps;
|
||||
else
|
||||
bufLen = width * height * 4;
|
||||
bufLen = width * height * nComps;
|
||||
bufOut.reset(new uint8_t[bufLen]);
|
||||
|
||||
if (setjmp(png_jmpbuf(pngRead)))
|
||||
|
@ -785,6 +931,10 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
bufOut[outbase+3] = rowBuf[inbase+3];
|
||||
}
|
||||
break;
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
for (unsigned i=0 ; i<width ; ++i)
|
||||
bufOut[r*width+i] = rowBuf[i];
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -796,16 +946,16 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
if (numMips > 1)
|
||||
{
|
||||
const uint8_t* filterIn = bufOut.get();
|
||||
uint8_t* filterOut = bufOut.get() + width * height * 4;
|
||||
uint8_t* filterOut = bufOut.get() + width * height * nComps;
|
||||
unsigned filterWidth = width;
|
||||
unsigned filterHeight = height;
|
||||
for (size_t i=1 ; i<numMips ; ++i)
|
||||
{
|
||||
BoxFilter(filterIn, 4, filterWidth, filterHeight, filterOut);
|
||||
filterIn += filterWidth * filterHeight * 4;
|
||||
BoxFilter(filterIn, nComps, filterWidth, filterHeight, filterOut);
|
||||
filterIn += filterWidth * filterHeight * nComps;
|
||||
filterWidth /= 2;
|
||||
filterHeight /= 2;
|
||||
filterOut += filterWidth * filterHeight * 4;
|
||||
filterOut += filterWidth * filterHeight * nComps;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -819,10 +969,12 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
return false;
|
||||
}
|
||||
|
||||
outf.writeInt32Big(16);
|
||||
outf.writeInt32Big((paletteBuf && paletteSize) ? 17 : 16);
|
||||
outf.writeInt16Big(width);
|
||||
outf.writeInt16Big(height);
|
||||
outf.writeInt32Big(numMips);
|
||||
if (paletteBuf && paletteSize)
|
||||
outf.writeUBytes(paletteBuf.get(), paletteSize);
|
||||
outf.writeUBytes(bufOut.get(), bufLen);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -20,6 +20,8 @@ using YAMLNode = athena::io::YAMLNode;
|
|||
namespace urde
|
||||
{
|
||||
|
||||
URDE_DECL_SPECIALIZE_SHADER(CThermalColdFilter)
|
||||
|
||||
void ViewManager::BuildTestPART(urde::IObjectStore& objStore)
|
||||
{
|
||||
m_modelTest = objStore.GetObj("gun_cmdl");
|
||||
|
|
|
@ -239,7 +239,7 @@ void CBooRenderer::GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx
|
|||
SPHERE_RAMP_RES * SPHERE_RAMP_RES);
|
||||
}
|
||||
|
||||
void CBooRenderer::LoadThermoPalette(boo::IGraphicsDataFactory::Context& ctx)
|
||||
void CBooRenderer::LoadThermoPalette()
|
||||
{
|
||||
m_thermoPaletteTex = xc_store.GetObj("TXTR_ThermoPalette");
|
||||
CTexture* thermoTexObj = m_thermoPaletteTex.GetObj();
|
||||
|
@ -257,9 +257,9 @@ CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac)
|
|||
GenerateMirrorRampTex(ctx);
|
||||
GenerateFogVolumeRampTex(ctx);
|
||||
GenerateSphereRampTex(ctx);
|
||||
LoadThermoPalette(ctx);
|
||||
return true;
|
||||
});
|
||||
LoadThermoPalette();
|
||||
|
||||
Buckets::Init();
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ class CBooRenderer : public IRenderer
|
|||
void GenerateMirrorRampTex(boo::IGraphicsDataFactory::Context& ctx);
|
||||
void GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx);
|
||||
void GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx);
|
||||
void LoadThermoPalette(boo::IGraphicsDataFactory::Context& ctx);
|
||||
void LoadThermoPalette();
|
||||
|
||||
void RenderBucketItems(const std::vector<CLight>& lights);
|
||||
|
||||
|
|
|
@ -148,7 +148,8 @@ enum class ETexelFormat
|
|||
RGB5A3 = 8,
|
||||
RGBA8 = 9,
|
||||
CMPR = 10,
|
||||
RGBA8PC = 16
|
||||
RGBA8PC = 16,
|
||||
C8PC = 17
|
||||
};
|
||||
|
||||
class CGraphics
|
||||
|
|
|
@ -20,6 +20,7 @@ class CTexture
|
|||
u32 x8_mips;
|
||||
boo::GraphicsDataToken m_booToken;
|
||||
boo::ITexture* m_booTex;
|
||||
boo::ITexture* m_paletteTex;
|
||||
|
||||
size_t ComputeMippedTexelCount();
|
||||
size_t ComputeMippedBlockCountDXT1();
|
||||
|
@ -35,6 +36,7 @@ class CTexture
|
|||
void BuildRGBA8FromGCN(CInputStream& in);
|
||||
void BuildDXT1FromGCN(CInputStream& in);
|
||||
void BuildRGBA8(const void* data);
|
||||
void BuildC8(const void* data);
|
||||
|
||||
public:
|
||||
CTexture(std::unique_ptr<u8[]>&& in, u32 length);
|
||||
|
|
|
@ -660,6 +660,23 @@ void CTexture::BuildRGBA8(const void* data)
|
|||
});
|
||||
}
|
||||
|
||||
void CTexture::BuildC8(const void* data)
|
||||
{
|
||||
size_t texelCount = ComputeMippedTexelCount();
|
||||
|
||||
m_booToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
uint32_t nentries = hecl::SBig(*reinterpret_cast<const uint32_t*>(data));
|
||||
const u8* paletteTexels = reinterpret_cast<const u8*>(data) + 4;
|
||||
const u8* texels = reinterpret_cast<const u8*>(data) + 4 + nentries * 4;
|
||||
m_paletteTex = ctx.newStaticTexture(nentries, 1, 1, boo::TextureFormat::RGBA8,
|
||||
paletteTexels, nentries * 4);
|
||||
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::I8,
|
||||
texels, texelCount);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
CTexture::CTexture(std::unique_ptr<u8[]>&& in, u32 length)
|
||||
{
|
||||
std::unique_ptr<u8[]> owned = std::move(in);
|
||||
|
@ -707,6 +724,9 @@ CTexture::CTexture(std::unique_ptr<u8[]>&& in, u32 length)
|
|||
case ETexelFormat::RGBA8PC:
|
||||
BuildRGBA8(owned.get() + 12);
|
||||
break;
|
||||
case ETexelFormat::C8PC:
|
||||
BuildC8(owned.get() + 12);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, "invalid texture type %d for boo", int(x0_fmt));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue