Merge pull request #13283 from huffman/feat/uncompressed-ktx-in-texmeta

Add uncompressed KTX files to baked texture output
This commit is contained in:
Clément Brisset 2018-06-13 11:49:41 -07:00 committed by GitHub
commit 11d84e780d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 185 additions and 196 deletions

View file

@ -291,18 +291,6 @@ AssetServer::AssetServer(ReceivedMessage& message) :
_bakingTaskPool(this),
_filesizeLimit(AssetUtils::MAX_UPLOAD_SIZE)
{
// store the current state of image compression so we can reset it when this assignment is complete
_wasColorTextureCompressionEnabled = image::isColorTexturesCompressionEnabled();
_wasGrayscaleTextureCompressionEnabled = image::isGrayscaleTexturesCompressionEnabled();
_wasNormalTextureCompressionEnabled = image::isNormalTexturesCompressionEnabled();
_wasCubeTextureCompressionEnabled = image::isCubeTexturesCompressionEnabled();
// enable compression in image library
image::setColorTexturesCompressionEnabled(true);
image::setGrayscaleTexturesCompressionEnabled(true);
image::setNormalTexturesCompressionEnabled(true);
image::setCubeTexturesCompressionEnabled(true);
BAKEABLE_TEXTURE_EXTENSIONS = image::getSupportedFormats();
qDebug() << "Supported baking texture formats:" << BAKEABLE_MODEL_EXTENSIONS;
@ -354,12 +342,6 @@ void AssetServer::aboutToFinish() {
while (_pendingBakes.size() > 0) {
QCoreApplication::processEvents();
}
// re-set defaults in image library
image::setColorTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled);
image::setGrayscaleTexturesCompressionEnabled(_wasGrayscaleTextureCompressionEnabled);
image::setNormalTexturesCompressionEnabled(_wasNormalTextureCompressionEnabled);
image::setCubeTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled);
}
void AssetServer::run() {

View file

@ -167,11 +167,6 @@ private:
using RequestQueue = QVector<QPair<QSharedPointer<ReceivedMessage>, SharedNodePointer>>;
RequestQueue _queuedRequests;
bool _wasColorTextureCompressionEnabled { false };
bool _wasGrayscaleTextureCompressionEnabled { false };
bool _wasNormalTextureCompressionEnabled { false };
bool _wasCubeTextureCompressionEnabled { false };
uint64_t _filesizeLimit;
};

View file

@ -22,12 +22,16 @@
#include <SharedUtil.h>
#include <TextureMeta.h>
#include <OwningBuffer.h>
#include "ModelBakingLoggingCategory.h"
const QString BAKED_TEXTURE_KTX_EXT = ".ktx";
const QString BAKED_TEXTURE_BCN_SUFFIX = "_bcn.ktx";
const QString BAKED_META_TEXTURE_SUFFIX = ".texmeta.json";
bool TextureBaker::_compressionEnabled = true;
TextureBaker::TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType,
const QDir& outputDirectory, const QString& metaTexturePathPrefix,
const QString& baseFilename, const QByteArray& textureContent) :
@ -124,42 +128,45 @@ void TextureBaker::processTexture() {
TextureMeta meta;
auto originalCopyFilePath = _outputDirectory.absoluteFilePath(_textureURL.fileName());
{
auto filePath = _outputDirectory.absoluteFilePath(_textureURL.fileName());
QFile file { filePath };
QFile file { originalCopyFilePath };
if (!file.open(QIODevice::WriteOnly) || file.write(_originalTexture) == -1) {
handleError("Could not write original texture for " + _textureURL.toString());
return;
}
_outputFiles.push_back(filePath);
// IMPORTANT: _originalTexture is empty past this point
_originalTexture.clear();
_outputFiles.push_back(originalCopyFilePath);
meta.original = _metaTexturePathPrefix +_textureURL.fileName();
}
// IMPORTANT: _originalTexture is empty past this point
auto processedTexture = image::processImage(std::move(_originalTexture), _textureURL.toString().toStdString(),
ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, _abortProcessing);
processedTexture->setSourceHash(hash);
if (shouldStop()) {
auto buffer = std::static_pointer_cast<QIODevice>(std::make_shared<QFile>(originalCopyFilePath));
if (!buffer->open(QIODevice::ReadOnly)) {
handleError("Could not open original file at " + originalCopyFilePath);
return;
}
if (!processedTexture) {
handleError("Could not process texture " + _textureURL.toString());
return;
}
// Compressed KTX
if (_compressionEnabled) {
auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(),
ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, _abortProcessing);
if (!processedTexture) {
handleError("Could not process texture " + _textureURL.toString());
return;
}
processedTexture->setSourceHash(hash);
auto memKTX = gpu::Texture::serialize(*processedTexture);
if (shouldStop()) {
return;
}
if (!memKTX) {
handleError("Could not serialize " + _textureURL.toString() + " to KTX");
return;
}
auto memKTX = gpu::Texture::serialize(*processedTexture);
if (!memKTX) {
handleError("Could not serialize " + _textureURL.toString() + " to KTX");
return;
}
// attempt to write the baked texture to the destination file path
if (memKTX->_header.isCompressed()) {
const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat());
if (name == nullptr) {
handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString());
@ -178,21 +185,45 @@ void TextureBaker::processTexture() {
}
_outputFiles.push_back(filePath);
meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName;
} else {
}
// Uncompressed KTX
if (_textureType == image::TextureUsage::Type::CUBE_TEXTURE) {
buffer->reset();
auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(),
ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, _abortProcessing);
if (!processedTexture) {
handleError("Could not process texture " + _textureURL.toString());
return;
}
processedTexture->setSourceHash(hash);
if (shouldStop()) {
return;
}
auto memKTX = gpu::Texture::serialize(*processedTexture);
if (!memKTX) {
handleError("Could not serialize " + _textureURL.toString() + " to KTX");
return;
}
const char* data = reinterpret_cast<const char*>(memKTX->_storage->data());
const size_t length = memKTX->_storage->size();
auto fileName = _baseFilename + ".ktx";
auto filePath = _outputDirectory.absoluteFilePath(fileName);
QFile ktxTextureFile { filePath };
if (!ktxTextureFile.open(QIODevice::WriteOnly) || ktxTextureFile.write(data, length) == -1) {
handleError("Could not write ktx texture for " + _textureURL.toString());
QFile bakedTextureFile { filePath };
if (!bakedTextureFile.open(QIODevice::WriteOnly) || bakedTextureFile.write(data, length) == -1) {
handleError("Could not write baked texture for " + _textureURL.toString());
return;
}
_outputFiles.push_back(filePath);
meta.uncompressed = _metaTexturePathPrefix + fileName;
} else {
buffer.reset();
}
{
auto data = meta.serialize();
_metaTextureFileName = _outputDirectory.absoluteFilePath(_baseFilename + BAKED_META_TEXTURE_SUFFIX);

View file

@ -41,6 +41,8 @@ public:
virtual void setWasAborted(bool wasAborted) override;
static void setCompressionEnabled(bool enabled) { _compressionEnabled = enabled; }
public slots:
virtual void bake() override;
virtual void abort() override;
@ -65,6 +67,8 @@ private:
QString _metaTexturePathPrefix;
std::atomic<bool> _abortProcessing { false };
static bool _compressionEnabled;
};
#endif // hifi_TextureBaker_h

View file

@ -50,11 +50,6 @@ std::atomic<size_t> RECTIFIED_TEXTURE_COUNT{ 0 };
// possibly causing the element not to be constructed yet
static const auto& HDR_FORMAT = gpu::Element::COLOR_R11G11B10;
static std::atomic<bool> compressColorTextures { false };
static std::atomic<bool> compressNormalTextures { false };
static std::atomic<bool> compressGrayscaleTextures { false };
static std::atomic<bool> compressCubeTextures { false };
uint rectifyDimension(const uint& dimension) {
if (dimension == 0) {
return 0;
@ -128,112 +123,63 @@ TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, con
}
gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
}
gpu::TexturePointer TextureUsage::create2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
}
gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
}
gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
gpu::TexturePointer TextureUsage::createCubeTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing) {
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
}
gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(QImage&& srcImage, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing) {
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
}
bool isColorTexturesCompressionEnabled() {
#if CPU_MIPMAPS
return compressColorTextures.load();
#else
return false;
#endif
}
bool isNormalTexturesCompressionEnabled() {
#if CPU_MIPMAPS
return compressNormalTextures.load();
#else
return false;
#endif
}
bool isGrayscaleTexturesCompressionEnabled() {
#if CPU_MIPMAPS
return compressGrayscaleTextures.load();
#else
return false;
#endif
}
bool isCubeTexturesCompressionEnabled() {
#if CPU_MIPMAPS
return compressCubeTextures.load();
#else
return false;
#endif
}
void setColorTexturesCompressionEnabled(bool enabled) {
compressColorTextures.store(enabled);
}
void setNormalTexturesCompressionEnabled(bool enabled) {
compressNormalTextures.store(enabled);
}
void setGrayscaleTexturesCompressionEnabled(bool enabled) {
compressGrayscaleTextures.store(enabled);
}
void setCubeTexturesCompressionEnabled(bool enabled) {
compressCubeTextures.store(enabled);
bool compress, const std::atomic<bool>& abortProcessing) {
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
}
static float denormalize(float value, const float minValue) {
@ -255,17 +201,11 @@ uint32 packR11G11B10F(const glm::vec3& color) {
return glm::packF2x11_1x10(ucolor);
}
QImage processRawImageData(QByteArray&& content, const std::string& filename) {
// Take a local copy to force move construction
// https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f18-for-consume-parameters-pass-by-x-and-stdmove-the-parameter
QByteArray localCopy = std::move(content);
QImage processRawImageData(QIODevice& content, const std::string& filename) {
// Help the QImage loader by extracting the image file format from the url filename ext.
// Some tga are not created properly without it.
auto filenameExtension = filename.substr(filename.find_last_of('.') + 1);
QBuffer buffer;
buffer.setData(localCopy);
QImageReader imageReader(&buffer, filenameExtension.c_str());
QImageReader imageReader(&content, filenameExtension.c_str());
if (imageReader.canRead()) {
return imageReader.read();
@ -273,8 +213,8 @@ QImage processRawImageData(QByteArray&& content, const std::string& filename) {
// Extension could be incorrect, try to detect the format from the content
QImageReader newImageReader;
newImageReader.setDecideFormatFromContent(true);
buffer.setData(localCopy);
newImageReader.setDevice(&buffer);
content.reset();
newImageReader.setDevice(&content);
if (newImageReader.canRead()) {
qCWarning(imagelogging) << "Image file" << filename.c_str() << "has extension" << filenameExtension.c_str()
@ -286,11 +226,14 @@ QImage processRawImageData(QByteArray&& content, const std::string& filename) {
return QImage();
}
gpu::TexturePointer processImage(QByteArray&& content, const std::string& filename,
gpu::TexturePointer processImage(std::shared_ptr<QIODevice> content, const std::string& filename,
int maxNumPixels, TextureUsage::Type textureType,
const std::atomic<bool>& abortProcessing) {
bool compress, const std::atomic<bool>& abortProcessing) {
QImage image = processRawImageData(std::move(content), filename);
QImage image = processRawImageData(*content.get(), filename);
// Texture content can take up a lot of memory. Here we release our ownership of that content
// in case it can be released.
content.reset();
int imageWidth = image.width();
int imageHeight = image.height();
@ -316,7 +259,7 @@ gpu::TexturePointer processImage(QByteArray&& content, const std::string& filena
}
auto loader = TextureUsage::getTextureLoaderForType(textureType);
auto texture = loader(std::move(image), filename, abortProcessing);
auto texture = loader(std::move(image), filename, compress, abortProcessing);
return texture;
}
@ -806,7 +749,7 @@ void processTextureAlpha(const QImage& srcImage, bool& validAlpha, bool& alphaAs
validAlpha = (numOpaques != NUM_PIXELS);
}
gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName,
gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
bool isStrict, const std::atomic<bool>& abortProcessing) {
PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage");
QImage image = processSourceImage(std::move(srcImage), false);
@ -827,7 +770,7 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
if ((image.width() > 0) && (image.height() > 0)) {
gpu::Element formatMip;
gpu::Element formatGPU;
if (isColorTexturesCompressionEnabled()) {
if (compress) {
if (validAlpha) {
// NOTE: This disables BC1a compression because it was producing odd artifacts on text textures
// for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts).
@ -944,7 +887,8 @@ QImage processBumpMap(QImage&& image) {
return result;
}
gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName,
bool isBumpMap, const std::atomic<bool>& abortProcessing) {
bool compress, bool isBumpMap,
const std::atomic<bool>& abortProcessing) {
PROFILE_RANGE(resource_parse, "process2DTextureNormalMapFromImage");
QImage image = processSourceImage(std::move(srcImage), false);
@ -961,7 +905,7 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
if ((image.width() > 0) && (image.height() > 0)) {
gpu::Element formatMip;
gpu::Element formatGPU;
if (isNormalTexturesCompressionEnabled()) {
if (compress) {
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY;
} else {
#ifdef USE_GLES
@ -983,7 +927,7 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
}
gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName,
bool isInvertedPixels,
bool compress, bool isInvertedPixels,
const std::atomic<bool>& abortProcessing) {
PROFILE_RANGE(resource_parse, "process2DTextureGrayscaleFromImage");
QImage image = processSourceImage(std::move(srcImage), false);
@ -1001,7 +945,7 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr
if ((image.width() > 0) && (image.height() > 0)) {
gpu::Element formatMip;
gpu::Element formatGPU;
if (isGrayscaleTexturesCompressionEnabled()) {
if (compress) {
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED;
} else {
#ifdef USE_GLES
@ -1348,7 +1292,7 @@ QImage convertToHDRFormat(QImage&& srcImage, gpu::Element format) {
}
gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName,
bool generateIrradiance,
bool compress, bool generateIrradiance,
const std::atomic<bool>& abortProcessing) {
PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage");
@ -1376,7 +1320,7 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI
gpu::Element formatMip;
gpu::Element formatGPU;
if (isCubeTexturesCompressionEnabled()) {
if (compress) {
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
} else {
#ifdef USE_GLES

View file

@ -41,60 +41,50 @@ enum Type {
UNUSED_TEXTURE
};
using TextureLoader = std::function<gpu::TexturePointer(QImage&&, const std::string&, const std::atomic<bool>&)>;
using TextureLoader = std::function<gpu::TexturePointer(QImage&&, const std::string&, bool, const std::atomic<bool>&)>;
TextureLoader getTextureLoaderForType(Type type, const QVariantMap& options = QVariantMap());
gpu::TexturePointer create2DTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createStrict2DTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createAlbedoTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createEmissiveTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createNormalTextureFromNormalImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createNormalTextureFromBumpImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createRoughnessTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createRoughnessTextureFromGlossImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createMetallicTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createCubeTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createCubeTextureFromImageWithoutIrradiance(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer createLightmapTextureFromImage(QImage&& image, const std::string& srcImageName,
const std::atomic<bool>& abortProcessing);
bool compress, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool isStrict,
const std::atomic<bool>& abortProcessing);
gpu::TexturePointer process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName, bool isBumpMap,
const std::atomic<bool>& abortProcessing);
gpu::TexturePointer process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName, bool isInvertedPixels,
const std::atomic<bool>& abortProcessing);
gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool generateIrradiance,
const std::atomic<bool>& abortProcessing);
gpu::TexturePointer process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
bool isStrict, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
bool isBumpMap, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
bool isInvertedPixels, const std::atomic<bool>& abortProcessing);
gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
bool generateIrradiance, const std::atomic<bool>& abortProcessing);
} // namespace TextureUsage
const QStringList getSupportedFormats();
bool isColorTexturesCompressionEnabled();
bool isNormalTexturesCompressionEnabled();
bool isGrayscaleTexturesCompressionEnabled();
bool isCubeTexturesCompressionEnabled();
void setColorTexturesCompressionEnabled(bool enabled);
void setNormalTexturesCompressionEnabled(bool enabled);
void setGrayscaleTexturesCompressionEnabled(bool enabled);
void setCubeTexturesCompressionEnabled(bool enabled);
gpu::TexturePointer processImage(QByteArray&& content, const std::string& url,
gpu::TexturePointer processImage(std::shared_ptr<QIODevice> content, const std::string& url,
int maxNumPixels, TextureUsage::Type textureType,
const std::atomic<bool>& abortProcessing = false);
bool compress = false, const std::atomic<bool>& abortProcessing = false);
} // namespace image

View file

@ -33,6 +33,9 @@ bool TextureMeta::deserialize(const QByteArray& data, TextureMeta* meta) {
if (root.contains("original")) {
meta->original = root["original"].toString();
}
if (root.contains("uncompressed")) {
meta->uncompressed = root["uncompressed"].toString();
}
if (root.contains("compressed")) {
auto compressed = root["compressed"].toObject();
for (auto it = compressed.constBegin(); it != compressed.constEnd(); it++) {
@ -57,6 +60,7 @@ QByteArray TextureMeta::serialize() {
compressed[name] = kv.second.toString();
}
root["original"] = original.toString();
root["uncompressed"] = uncompressed.toString();
root["compressed"] = compressed;
doc.setObject(root);

View file

@ -35,6 +35,7 @@ struct TextureMeta {
QByteArray serialize();
QUrl original;
QUrl uncompressed;
std::unordered_map<khronos::gl::texture::InternalFormat, QUrl> availableTextureTypes;
};

View file

@ -50,6 +50,8 @@
#include <TextureMeta.h>
#include <OwningBuffer.h>
Q_LOGGING_CATEGORY(trace_resource_parse_image, "trace.resource.parse.image")
Q_LOGGING_CATEGORY(trace_resource_parse_image_raw, "trace.resource.parse.image.raw")
Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx")
@ -277,7 +279,7 @@ gpu::TexturePointer TextureCache::getImageTexture(const QString& path, image::Te
return nullptr;
}
auto loader = image::TextureUsage::getTextureLoaderForType(type, options);
return gpu::TexturePointer(loader(std::move(image), path.toStdString(), false));
return gpu::TexturePointer(loader(std::move(image), path.toStdString(), false, false));
}
QSharedPointer<Resource> TextureCache::createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
@ -964,7 +966,6 @@ void NetworkTexture::loadMetaContent(const QByteArray& content) {
return;
}
auto& backend = DependencyManager::get<TextureCache>()->getGPUContext()->getBackend();
for (auto pair : meta.availableTextureTypes) {
gpu::Element elFormat;
@ -990,6 +991,21 @@ void NetworkTexture::loadMetaContent(const QByteArray& content) {
}
}
#ifndef Q_OS_ANDROID
if (!meta.uncompressed.isEmpty()) {
_currentlyLoadingResourceType = ResourceType::KTX;
_activeUrl = _activeUrl.resolved(meta.uncompressed);
auto textureCache = DependencyManager::get<TextureCache>();
auto self = _self.lock();
if (!self) {
return;
}
QMetaObject::invokeMethod(this, "attemptRequest", Qt::QueuedConnection);
return;
}
#endif
if (!meta.original.isEmpty()) {
_currentlyLoadingResourceType = ResourceType::ORIGINAL;
_activeUrl = _activeUrl.resolved(meta.original);
@ -1143,7 +1159,8 @@ void ImageReader::read() {
PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0);
// IMPORTANT: _content is empty past this point
texture = image::processImage(std::move(_content), _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType());
auto buffer = std::shared_ptr<QIODevice>((QIODevice*)new OwningBuffer(std::move(_content)));
texture = image::processImage(std::move(buffer), _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType());
if (!texture) {
qCWarning(modelnetworking) << "Could not process:" << _url;

View file

@ -0,0 +1,29 @@
//
// OwningBuffer.h
// shared/src
//
// Created by Ryan Huffman on 5/31/2018.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_OwningBuffer_h
#define hifi_OwningBuffer_h
#include <QBuffer>
class OwningBuffer : public QBuffer {
public:
OwningBuffer(const QByteArray& content) : _content(content) {
setData(_content);
}
OwningBuffer(QByteArray&& content) : _content(std::move(content)) {
setData(_content);
}
private:
QByteArray _content;
};
#endif // hifi_OwningBuffer_h

View file

@ -25,12 +25,6 @@ Oven* Oven::_staticInstance { nullptr };
Oven::Oven() {
_staticInstance = this;
// enable compression in image library
image::setColorTexturesCompressionEnabled(true);
image::setGrayscaleTexturesCompressionEnabled(true);
image::setNormalTexturesCompressionEnabled(true);
image::setCubeTexturesCompressionEnabled(true);
// setup our worker threads
setupWorkerThreads(QThread::idealThreadCount());

View file

@ -15,6 +15,7 @@
#include <QtCore/QUrl>
#include <image/Image.h>
#include <TextureBaker.h>
#include "BakerCLI.h"
@ -47,10 +48,7 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
if (parser.isSet(CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER)) {
qDebug() << "Disabling texture compression";
image::setColorTexturesCompressionEnabled(false);
image::setGrayscaleTexturesCompressionEnabled(false);
image::setNormalTexturesCompressionEnabled(false);
image::setCubeTexturesCompressionEnabled(false);
TextureBaker::setCompressionEnabled(false);
}
QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, inputUrl),