diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index f65242c578..ba44bd6341 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -450,6 +450,7 @@ bool Texture::assignStoredMipFace(uint16 level, const Element& format, Size size Size expectedSize = evalStoredMipFaceSize(level, format); if (size == expectedSize) { _storage->assignMipFaceData(level, format, size, bytes, face); + _maxMip = std::max(_maxMip, level); _stamp++; return true; } else if (size > expectedSize) { @@ -458,6 +459,7 @@ bool Texture::assignStoredMipFace(uint16 level, const Element& format, Size size // We should probably consider something a bit more smart to get the correct result but for now (UI elements) // it seems to work... _storage->assignMipFaceData(level, format, size, bytes, face); + _maxMip = std::max(_maxMip, level); _stamp++; return true; } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 0a5afe78c3..b8537b07c2 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -488,7 +488,7 @@ public: ExternalUpdates getUpdates() const; 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: const TextureUsageType _usageType; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 404aca77a4..508467e79f 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -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); // Set Dimensions + uint32_t numFaces = 1; switch (texture.getType()) { case TEX_1D: { if (texture.isArray()) { @@ -59,6 +60,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { } else { header.setCube(texture.getWidth(), texture.getHeight()); } + numFaces = 6; break; } default: @@ -72,7 +74,16 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { for (uint32_t level = 0; level < header.numberOfMipmapLevels; level++) { auto mip = texture.accessStoredMipFace(level); 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; } -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) { return nullptr; } @@ -113,12 +124,16 @@ Texture* Texture::unserialize(TextureUsageType usageType, const ktx::KTXUniquePo header.getPixelDepth(), 1, // num Samples header.getNumberOfSlices(), - Sampler()); + sampler); + + tex->setUsage(usage); // Assing the mips availables uint16_t level = 0; for (auto& image : srcData->_images) { - tex->assignStoredMip(level, mipFormat, image._imageSize, image._bytes); + for (uint32_t face = 0; face < image._numFaces; face++) { + tex->assignStoredMipFace(level, mipFormat, image._faceSize, image._faceBytes[face], face); + } level++; } diff --git a/libraries/ktx/src/ktx/KTX.cpp b/libraries/ktx/src/ktx/KTX.cpp index f8f315d784..8635fbb684 100644 --- a/libraries/ktx/src/ktx/KTX.cpp +++ b/libraries/ktx/src/ktx/KTX.cpp @@ -16,8 +16,9 @@ using namespace ktx; uint32_t Header::evalPadding(size_t byteSize) { - auto padding = byteSize % PACKING_SIZE; - return (uint32_t) (padding ? PACKING_SIZE - padding : 0); + //auto padding = byteSize % PACKING_SIZE; + // return (uint32_t) (padding ? PACKING_SIZE - padding : 0); + return (uint32_t) (3 - (byteSize + 3) % PACKING_SIZE);// padding ? PACKING_SIZE - padding : 0); } diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index 8e79d90dc0..52c65c9cd4 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -418,14 +418,32 @@ namespace ktx { struct Image { + using FaceBytes = std::vector; + + uint32_t _numFaces{ 1 }; uint32_t _imageSize; + uint32_t _faceSize; uint32_t _padding; - const Byte* _bytes; + FaceBytes _faceBytes; + Image(uint32_t imageSize, uint32_t padding, const Byte* bytes) : + _numFaces(1), _imageSize(imageSize), _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; diff --git a/libraries/ktx/src/ktx/Reader.cpp b/libraries/ktx/src/ktx/Reader.cpp index 00c0c4e19a..dffe6cf828 100644 --- a/libraries/ktx/src/ktx/Reader.cpp +++ b/libraries/ktx/src/ktx/Reader.cpp @@ -125,6 +125,7 @@ namespace ktx { Images images; auto currentPtr = srcBytes; auto numMips = header.getNumberOfLevels(); + auto numFaces = header.numberOfFaces; // Keep identifying new mip as long as we can at list query the next imageSize while ((currentPtr - srcBytes) + sizeof(uint32_t) <= (srcSize)) { @@ -137,9 +138,19 @@ namespace ktx { if ((currentPtr - srcBytes) + imageSize <= (srcSize)) { auto padding = Header::evalPadding(imageSize); - images.emplace_back(Image(imageSize, padding, currentPtr)); - - currentPtr += imageSize + padding; + if (numFaces == 6) { + size_t faceSize = imageSize / 6; + 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 { break; } diff --git a/libraries/ktx/src/ktx/Writer.cpp b/libraries/ktx/src/ktx/Writer.cpp index 75836ad5b5..edd9a9ec97 100644 --- a/libraries/ktx/src/ktx/Writer.cpp +++ b/libraries/ktx/src/ktx/Writer.cpp @@ -125,14 +125,25 @@ namespace ktx { // If enough data ahead then capture the copy source pointer if (currentDataSize + imageSize <= (allocatedImagesDataSize)) { - - auto copied = memcpy(currentPtr, srcImages[l]._bytes, 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; } } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 5eb1b3982a..a95ed78be3 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -85,7 +85,7 @@ QImage processSourceImage(const QImage& srcImage, bool cubemap) { return srcImage; } -gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bool write = true, bool read = false) { +gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bool write = true, bool read = true) { if (!srcTexture) { return nullptr; } @@ -113,10 +113,15 @@ gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bo filename += ".ktx"; if (write) { - FILE* file = fopen (filename.c_str(),"wb"); + /* FILE *file = fopen(name.c_str(), "r"); 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); + } } } @@ -133,7 +138,7 @@ gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bo fclose (file); //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) { returnedTexture = theNewTexure;