mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 20:36:38 +02:00
Merge pull request #9711 from samcake/texmex
Smarter_textures branch: adding support for cube maps with KTX
This commit is contained in:
commit
3633fb8f7c
8 changed files with 105 additions and 30 deletions
|
@ -436,6 +436,7 @@ void Texture::assignStoredMipFace(uint16 level, uint8 face, storage::StoragePoin
|
||||||
auto bytes = storage->data();
|
auto bytes = storage->data();
|
||||||
if (size == expectedSize) {
|
if (size == expectedSize) {
|
||||||
_storage->assignMipFaceData(level, face, storage);
|
_storage->assignMipFaceData(level, face, storage);
|
||||||
|
_maxMip = std::max(_maxMip, level);
|
||||||
_stamp++;
|
_stamp++;
|
||||||
} else if (size > expectedSize) {
|
} else if (size > expectedSize) {
|
||||||
// NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images
|
// NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images
|
||||||
|
@ -443,6 +444,7 @@ void Texture::assignStoredMipFace(uint16 level, uint8 face, storage::StoragePoin
|
||||||
// We should probably consider something a bit more smart to get the correct result but for now (UI elements)
|
// We should probably consider something a bit more smart to get the correct result but for now (UI elements)
|
||||||
// it seems to work...
|
// it seems to work...
|
||||||
_storage->assignMipFaceData(level, face, storage);
|
_storage->assignMipFaceData(level, face, storage);
|
||||||
|
_maxMip = std::max(_maxMip, level);
|
||||||
_stamp++;
|
_stamp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -960,3 +962,4 @@ Texture::ExternalUpdates Texture::getUpdates() const {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -506,7 +506,7 @@ public:
|
||||||
ExternalUpdates getUpdates() const;
|
ExternalUpdates getUpdates() const;
|
||||||
|
|
||||||
static ktx::KTXUniquePointer serialize(const Texture& texture);
|
static ktx::KTXUniquePointer serialize(const Texture& texture);
|
||||||
static Texture* unserialize(TextureUsageType usageType, const ktx::KTXUniquePointer& srcData);
|
static Texture* unserialize(Usage usage, TextureUsageType usageType, const ktx::KTXUniquePointer& srcData, const Sampler& sampler = Sampler());
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const TextureUsageType _usageType;
|
const TextureUsageType _usageType;
|
||||||
|
|
|
@ -28,6 +28,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
||||||
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 4, ktx::GLFormat::BGRA, ktx::GLInternalFormat_Uncompressed::RGBA8, ktx::GLBaseInternalFormat::RGBA);
|
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 4, ktx::GLFormat::BGRA, ktx::GLInternalFormat_Uncompressed::RGBA8, ktx::GLBaseInternalFormat::RGBA);
|
||||||
|
|
||||||
// Set Dimensions
|
// Set Dimensions
|
||||||
|
uint32_t numFaces = 1;
|
||||||
switch (texture.getType()) {
|
switch (texture.getType()) {
|
||||||
case TEX_1D: {
|
case TEX_1D: {
|
||||||
if (texture.isArray()) {
|
if (texture.isArray()) {
|
||||||
|
@ -59,6 +60,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
||||||
} else {
|
} else {
|
||||||
header.setCube(texture.getWidth(), texture.getHeight());
|
header.setCube(texture.getWidth(), texture.getHeight());
|
||||||
}
|
}
|
||||||
|
numFaces = 6;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -72,7 +74,16 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
||||||
for (uint32_t level = 0; level < header.numberOfMipmapLevels; level++) {
|
for (uint32_t level = 0; level < header.numberOfMipmapLevels; level++) {
|
||||||
auto mip = texture.accessStoredMipFace(level);
|
auto mip = texture.accessStoredMipFace(level);
|
||||||
if (mip) {
|
if (mip) {
|
||||||
images.emplace_back(ktx::Image((uint32_t)mip->getSize(), 0, mip->readData()));
|
if (numFaces == 1) {
|
||||||
|
images.emplace_back(ktx::Image((uint32_t)mip->getSize(), 0, mip->readData()));
|
||||||
|
} else {
|
||||||
|
ktx::Image::FaceBytes cubeFaces(6);
|
||||||
|
cubeFaces[0] = mip->readData();
|
||||||
|
for (int face = 1; face < 6; face++) {
|
||||||
|
cubeFaces[face] = texture.accessStoredMipFace(level, face)->readData();
|
||||||
|
}
|
||||||
|
images.emplace_back(ktx::Image((uint32_t)mip->getSize(), 0, cubeFaces));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +91,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
||||||
return ktxBuffer;
|
return ktxBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Texture::unserialize(TextureUsageType usageType, const ktx::KTXUniquePointer& srcData) {
|
Texture* Texture::unserialize(Usage usage, TextureUsageType usageType, const ktx::KTXUniquePointer& srcData, const Sampler& sampler) {
|
||||||
if (!srcData) {
|
if (!srcData) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -113,13 +124,17 @@ Texture* Texture::unserialize(TextureUsageType usageType, const ktx::KTXUniquePo
|
||||||
header.getPixelDepth(),
|
header.getPixelDepth(),
|
||||||
1, // num Samples
|
1, // num Samples
|
||||||
header.getNumberOfSlices(),
|
header.getNumberOfSlices(),
|
||||||
Sampler());
|
sampler);
|
||||||
|
|
||||||
|
tex->setUsage(usage);
|
||||||
|
|
||||||
// Assing the mips availables
|
// Assing the mips availables
|
||||||
tex->setStoredMipFormat(mipFormat);
|
tex->setStoredMipFormat(mipFormat);
|
||||||
uint16_t level = 0;
|
uint16_t level = 0;
|
||||||
for (auto& image : srcData->_images) {
|
for (auto& image : srcData->_images) {
|
||||||
tex->assignStoredMip(level, image._imageSize, image._bytes);
|
for (uint32_t face = 0; face < image._numFaces; face++) {
|
||||||
|
tex->assignStoredMipFace(level, face, image._faceSize, image._faceBytes[face]);
|
||||||
|
}
|
||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,9 @@
|
||||||
using namespace ktx;
|
using namespace ktx;
|
||||||
|
|
||||||
uint32_t Header::evalPadding(size_t byteSize) {
|
uint32_t Header::evalPadding(size_t byteSize) {
|
||||||
auto padding = byteSize % PACKING_SIZE;
|
//auto padding = byteSize % PACKING_SIZE;
|
||||||
return (uint32_t) (padding ? PACKING_SIZE - padding : 0);
|
// return (uint32_t) (padding ? PACKING_SIZE - padding : 0);
|
||||||
|
return (uint32_t) (3 - (byteSize + 3) % PACKING_SIZE);// padding ? PACKING_SIZE - padding : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -418,14 +418,32 @@ namespace ktx {
|
||||||
|
|
||||||
|
|
||||||
struct Image {
|
struct Image {
|
||||||
|
using FaceBytes = std::vector<const Byte*>;
|
||||||
|
|
||||||
|
uint32_t _numFaces{ 1 };
|
||||||
uint32_t _imageSize;
|
uint32_t _imageSize;
|
||||||
|
uint32_t _faceSize;
|
||||||
uint32_t _padding;
|
uint32_t _padding;
|
||||||
const Byte* _bytes;
|
FaceBytes _faceBytes;
|
||||||
|
|
||||||
|
|
||||||
Image(uint32_t imageSize, uint32_t padding, const Byte* bytes) :
|
Image(uint32_t imageSize, uint32_t padding, const Byte* bytes) :
|
||||||
|
_numFaces(1),
|
||||||
_imageSize(imageSize),
|
_imageSize(imageSize),
|
||||||
_padding(padding),
|
_padding(padding),
|
||||||
_bytes(bytes) {}
|
_faceSize(imageSize),
|
||||||
|
_faceBytes(1, bytes) {}
|
||||||
|
|
||||||
|
Image(uint32_t pageSize, uint32_t padding, const FaceBytes& cubeFaceBytes) :
|
||||||
|
_numFaces(NUM_CUBEMAPFACES),
|
||||||
|
_imageSize(pageSize * NUM_CUBEMAPFACES),
|
||||||
|
_padding(padding),
|
||||||
|
_faceSize(pageSize)
|
||||||
|
{
|
||||||
|
if (cubeFaceBytes.size() == NUM_CUBEMAPFACES) {
|
||||||
|
_faceBytes = cubeFaceBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
using Images = std::vector<Image>;
|
using Images = std::vector<Image>;
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,7 @@ namespace ktx {
|
||||||
Images images;
|
Images images;
|
||||||
auto currentPtr = srcBytes;
|
auto currentPtr = srcBytes;
|
||||||
auto numMips = header.getNumberOfLevels();
|
auto numMips = header.getNumberOfLevels();
|
||||||
|
auto numFaces = header.numberOfFaces;
|
||||||
|
|
||||||
// Keep identifying new mip as long as we can at list query the next imageSize
|
// Keep identifying new mip as long as we can at list query the next imageSize
|
||||||
while ((currentPtr - srcBytes) + sizeof(uint32_t) <= (srcSize)) {
|
while ((currentPtr - srcBytes) + sizeof(uint32_t) <= (srcSize)) {
|
||||||
|
@ -137,9 +138,19 @@ namespace ktx {
|
||||||
if ((currentPtr - srcBytes) + imageSize <= (srcSize)) {
|
if ((currentPtr - srcBytes) + imageSize <= (srcSize)) {
|
||||||
auto padding = Header::evalPadding(imageSize);
|
auto padding = Header::evalPadding(imageSize);
|
||||||
|
|
||||||
images.emplace_back(Image(imageSize, padding, currentPtr));
|
if (numFaces == 6) {
|
||||||
|
size_t faceSize = imageSize / 6;
|
||||||
currentPtr += imageSize + padding;
|
Image::FaceBytes faces(6);
|
||||||
|
for (uint32_t face = 0; face < 6; face++) {
|
||||||
|
faces[face] = currentPtr;
|
||||||
|
currentPtr += faceSize;
|
||||||
|
}
|
||||||
|
images.emplace_back(Image(faceSize, padding, faces));
|
||||||
|
currentPtr += padding;
|
||||||
|
} else {
|
||||||
|
images.emplace_back(Image(imageSize, padding, currentPtr));
|
||||||
|
currentPtr += imageSize + padding;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,14 +125,25 @@ namespace ktx {
|
||||||
|
|
||||||
// If enough data ahead then capture the copy source pointer
|
// If enough data ahead then capture the copy source pointer
|
||||||
if (currentDataSize + imageSize <= (allocatedImagesDataSize)) {
|
if (currentDataSize + imageSize <= (allocatedImagesDataSize)) {
|
||||||
|
|
||||||
auto copied = memcpy(currentPtr, srcImages[l]._bytes, imageSize);
|
|
||||||
|
|
||||||
auto padding = Header::evalPadding(imageSize);
|
auto padding = Header::evalPadding(imageSize);
|
||||||
|
|
||||||
destImages.emplace_back(Image(imageSize, padding, currentPtr));
|
// Single face vs cubes
|
||||||
|
if (srcImages[l]._numFaces == 1) {
|
||||||
|
auto copied = memcpy(currentPtr, srcImages[l]._faceBytes[0], imageSize);
|
||||||
|
destImages.emplace_back(Image(imageSize, padding, currentPtr));
|
||||||
|
currentPtr += imageSize;
|
||||||
|
} else {
|
||||||
|
Image::FaceBytes faceBytes(6);
|
||||||
|
auto faceSize = srcImages[l]._faceSize;
|
||||||
|
for (int face = 0; face < 6; face++) {
|
||||||
|
auto copied = memcpy(currentPtr, srcImages[l]._faceBytes[face], faceSize);
|
||||||
|
faceBytes[face] = currentPtr;
|
||||||
|
currentPtr += faceSize;
|
||||||
|
}
|
||||||
|
destImages.emplace_back(Image(faceSize, padding, faceBytes));
|
||||||
|
}
|
||||||
|
|
||||||
currentPtr += imageSize + padding;
|
currentPtr += padding;
|
||||||
currentDataSize += imageSize + padding;
|
currentDataSize += imageSize + padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,15 +103,25 @@ gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bo
|
||||||
QString originalRelativePath = originalFileInfo.path();
|
QString originalRelativePath = originalFileInfo.path();
|
||||||
QDir(docsLocation).mkpath(originalRelativePath);
|
QDir(docsLocation).mkpath(originalRelativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string cleanedName = name;
|
||||||
|
|
||||||
|
cleanedName = cleanedName.substr(cleanedName.find_last_of('//') + 1);
|
||||||
|
|
||||||
std::string filename(path.toStdString());
|
std::string filename(path.toStdString());
|
||||||
filename += name;
|
filename += cleanedName;
|
||||||
filename += ".ktx";
|
filename += ".ktx";
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
FILE* file = fopen (filename.c_str(),"wb");
|
/* FILE *file = fopen(name.c_str(), "r");
|
||||||
if (file != nullptr) {
|
if (file != nullptr) {
|
||||||
fwrite(theKTX->_storage->data(), 1, theKTX->_storage->size(), file);
|
fclose(file);
|
||||||
fclose (file);
|
} else*/ {
|
||||||
|
FILE *file = fopen (filename.c_str(),"wb");
|
||||||
|
if (file != nullptr) {
|
||||||
|
fwrite(theKTX->_storage->data(), 1, theKTX->_storage->size(), file);
|
||||||
|
fclose (file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +138,7 @@ gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bo
|
||||||
fclose (file);
|
fclose (file);
|
||||||
|
|
||||||
//then create a new texture out of the ktx
|
//then create a new texture out of the ktx
|
||||||
auto theNewTexure = Texture::unserialize(srcTexture->getUsageType(), ktx::KTX::create(storage));
|
auto theNewTexure = Texture::unserialize(srcTexture->getUsage(), srcTexture->getUsageType(), ktx::KTX::create(storage), srcTexture->getSampler());
|
||||||
|
|
||||||
if (theNewTexure) {
|
if (theNewTexure) {
|
||||||
returnedTexture = theNewTexure;
|
returnedTexture = theNewTexure;
|
||||||
|
@ -328,8 +338,8 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag
|
||||||
if (generateMips) {
|
if (generateMips) {
|
||||||
::generateMips(theTexture, image, false);
|
::generateMips(theTexture, image, false);
|
||||||
}
|
}
|
||||||
|
theTexture->setSource(srcImageName);
|
||||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
theTexture = cacheTexture(theTexture->source(), theTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
return theTexture;
|
return theTexture;
|
||||||
|
@ -377,7 +387,8 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src
|
||||||
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
||||||
generateMips(theTexture, image, true);
|
generateMips(theTexture, image, true);
|
||||||
|
|
||||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
theTexture->setSource(srcImageName);
|
||||||
|
theTexture = cacheTexture(theTexture->source(), theTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
return theTexture;
|
return theTexture;
|
||||||
|
@ -466,7 +477,8 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm
|
||||||
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
||||||
generateMips(theTexture, image, true);
|
generateMips(theTexture, image, true);
|
||||||
|
|
||||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
theTexture->setSource(srcImageName);
|
||||||
|
theTexture = cacheTexture(theTexture->source(), theTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
return theTexture;
|
return theTexture;
|
||||||
|
@ -502,7 +514,8 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma
|
||||||
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
||||||
generateMips(theTexture, image, true);
|
generateMips(theTexture, image, true);
|
||||||
|
|
||||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
theTexture->setSource(srcImageName);
|
||||||
|
theTexture = cacheTexture(theTexture->source(), theTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
return theTexture;
|
return theTexture;
|
||||||
|
@ -542,7 +555,8 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s
|
||||||
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
||||||
generateMips(theTexture, image, true);
|
generateMips(theTexture, image, true);
|
||||||
|
|
||||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
theTexture->setSource(srcImageName);
|
||||||
|
theTexture = cacheTexture(theTexture->source(), theTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
return theTexture;
|
return theTexture;
|
||||||
|
@ -579,7 +593,8 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag
|
||||||
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
||||||
generateMips(theTexture, image, true);
|
generateMips(theTexture, image, true);
|
||||||
|
|
||||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
theTexture->setSource(srcImageName);
|
||||||
|
theTexture = cacheTexture(theTexture->source(), theTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
return theTexture;
|
return theTexture;
|
||||||
|
@ -912,7 +927,8 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm
|
||||||
theTexture->generateIrradiance();
|
theTexture->generateIrradiance();
|
||||||
}
|
}
|
||||||
|
|
||||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
theTexture->setSource(srcImageName);
|
||||||
|
theTexture = cacheTexture(theTexture->source(), theTexture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue