Merge pull request #9711 from samcake/texmex

Smarter_textures branch: adding support for cube maps with KTX
This commit is contained in:
Brad Davis 2017-02-21 10:38:00 -08:00 committed by GitHub
commit 3633fb8f7c
8 changed files with 105 additions and 30 deletions

View file

@ -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;
} }

View file

@ -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;

View file

@ -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++;
} }

View file

@ -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);
} }

View file

@ -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>;

View file

@ -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;
} }

View file

@ -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;
} }
} }

View file

@ -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);
} }
} }