Support more NiPixelData formats (feature #6945)

pull/3228/head
Alexei Kotov 2 years ago
parent dd055d6142
commit edbd05a3f7

@ -5,6 +5,7 @@
Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses
Bug #5129: Stuttering animation on Centurion Archer
Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load
Feature #6945: Support S3TC-compressed and BGR/BGRA NiPixelData
0.48.0
------

@ -115,10 +115,11 @@ struct NiPixelData : public Record
NIPXFMT_RGBA8,
NIPXFMT_PAL8,
NIPXFMT_PALA8,
NIPXFMT_BGR8,
NIPXFMT_BGRA8,
NIPXFMT_DXT1,
NIPXFMT_DXT3,
NIPXFMT_DXT5,
NIPXFMT_DXT5_ALT
NIPXFMT_DXT5
};
Format fmt{NIPXFMT_RGB8};

@ -1480,17 +1480,39 @@ namespace NifOsg
{
osg::ref_ptr<osg::Image> image (new osg::Image);
// Pixel row alignment, defining it to be consistent with OSG DDS plugin
int packing = 1;
GLenum pixelformat = 0;
switch (pixelData->fmt)
{
case Nif::NiPixelData::NIPXFMT_RGB8:
case Nif::NiPixelData::NIPXFMT_PAL8:
pixelformat = GL_RGB;
break;
case Nif::NiPixelData::NIPXFMT_RGBA8:
case Nif::NiPixelData::NIPXFMT_PALA8:
pixelformat = GL_RGBA;
break;
case Nif::NiPixelData::NIPXFMT_PAL8:
case Nif::NiPixelData::NIPXFMT_PALA8:
pixelformat = GL_RED; // Each color is defined by a byte.
break;
case Nif::NiPixelData::NIPXFMT_BGR8:
pixelformat = GL_BGR;
break;
case Nif::NiPixelData::NIPXFMT_BGRA8:
pixelformat = GL_BGRA;
break;
case Nif::NiPixelData::NIPXFMT_DXT1:
pixelformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
packing = 2;
break;
case Nif::NiPixelData::NIPXFMT_DXT3:
pixelformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
packing = 4;
break;
case Nif::NiPixelData::NIPXFMT_DXT5:
pixelformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
packing = 4;
break;
default:
Log(Debug::Info) << "Unhandled internal pixel format " << pixelData->fmt << " in " << mFilename;
return nullptr;
@ -1507,7 +1529,7 @@ namespace NifOsg
{
const Nif::NiPixelData::Mipmap& mip = pixelData->mipmaps[i];
size_t mipSize = mip.height * mip.width * pixelData->bpp / 8;
size_t mipSize = osg::Image::computeImageSizeInBytes(mip.width, mip.height, 1, pixelformat, GL_UNSIGNED_BYTE, packing);
if (mipSize + mip.dataOffset > pixelData->data.size())
{
Log(Debug::Info) << "Internal texture's mipmap data out of bounds, ignoring texture";
@ -1534,10 +1556,15 @@ namespace NifOsg
{
case Nif::NiPixelData::NIPXFMT_RGB8:
case Nif::NiPixelData::NIPXFMT_RGBA8:
case Nif::NiPixelData::NIPXFMT_BGR8:
case Nif::NiPixelData::NIPXFMT_BGRA8:
case Nif::NiPixelData::NIPXFMT_DXT1:
case Nif::NiPixelData::NIPXFMT_DXT3:
case Nif::NiPixelData::NIPXFMT_DXT5:
{
unsigned char* data = new unsigned char[pixels.size()];
memcpy(data, pixels.data(), pixels.size());
image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE);
image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, packing);
break;
}
case Nif::NiPixelData::NIPXFMT_PAL8:
@ -1548,6 +1575,7 @@ namespace NifOsg
Log(Debug::Info) << "Palettized texture in " << mFilename << " is invalid, ignoring";
return nullptr;
}
pixelformat = pixelData->fmt == Nif::NiPixelData::NIPXFMT_PAL8 ? GL_RGB : GL_RGBA;
// We're going to convert the indices that pixel data contains
// into real colors using the palette.
const auto& palette = pixelData->palette->colors;
@ -1559,7 +1587,9 @@ namespace NifOsg
memcpy(pixel, &palette[index], sizeof(unsigned char) * numChannels);
pixel += numChannels;
}
image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE);
for (unsigned int& offset : mipmapVector)
offset *= numChannels;
image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, packing);
break;
}
default:

Loading…
Cancel
Save