mirror of
https://github.com/overte-org/overte.git
synced 2025-07-15 20:56:37 +02:00
Add uncompressed KTX files to baked texture output
This commit is contained in:
parent
87e6df3cba
commit
faafd26d2a
10 changed files with 190 additions and 138 deletions
|
@ -291,18 +291,6 @@ AssetServer::AssetServer(ReceivedMessage& message) :
|
||||||
_bakingTaskPool(this),
|
_bakingTaskPool(this),
|
||||||
_filesizeLimit(AssetUtils::MAX_UPLOAD_SIZE)
|
_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();
|
BAKEABLE_TEXTURE_EXTENSIONS = image::getSupportedFormats();
|
||||||
qDebug() << "Supported baking texture formats:" << BAKEABLE_MODEL_EXTENSIONS;
|
qDebug() << "Supported baking texture formats:" << BAKEABLE_MODEL_EXTENSIONS;
|
||||||
|
|
||||||
|
@ -354,12 +342,6 @@ void AssetServer::aboutToFinish() {
|
||||||
while (_pendingBakes.size() > 0) {
|
while (_pendingBakes.size() > 0) {
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-set defaults in image library
|
|
||||||
image::setColorTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled);
|
|
||||||
image::setGrayscaleTexturesCompressionEnabled(_wasGrayscaleTextureCompressionEnabled);
|
|
||||||
image::setNormalTexturesCompressionEnabled(_wasNormalTextureCompressionEnabled);
|
|
||||||
image::setCubeTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetServer::run() {
|
void AssetServer::run() {
|
||||||
|
|
|
@ -167,11 +167,6 @@ private:
|
||||||
using RequestQueue = QVector<QPair<QSharedPointer<ReceivedMessage>, SharedNodePointer>>;
|
using RequestQueue = QVector<QPair<QSharedPointer<ReceivedMessage>, SharedNodePointer>>;
|
||||||
RequestQueue _queuedRequests;
|
RequestQueue _queuedRequests;
|
||||||
|
|
||||||
bool _wasColorTextureCompressionEnabled { false };
|
|
||||||
bool _wasGrayscaleTextureCompressionEnabled { false };
|
|
||||||
bool _wasNormalTextureCompressionEnabled { false };
|
|
||||||
bool _wasCubeTextureCompressionEnabled { false };
|
|
||||||
|
|
||||||
uint64_t _filesizeLimit;
|
uint64_t _filesizeLimit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <TextureMeta.h>
|
#include <TextureMeta.h>
|
||||||
|
|
||||||
|
#include <OwningBuffer.h>
|
||||||
|
|
||||||
#include "ModelBakingLoggingCategory.h"
|
#include "ModelBakingLoggingCategory.h"
|
||||||
|
|
||||||
const QString BAKED_TEXTURE_KTX_EXT = ".ktx";
|
const QString BAKED_TEXTURE_KTX_EXT = ".ktx";
|
||||||
|
@ -124,47 +126,51 @@ void TextureBaker::processTexture() {
|
||||||
|
|
||||||
TextureMeta meta;
|
TextureMeta meta;
|
||||||
|
|
||||||
|
auto originalCopyFilePath = _outputDirectory.absoluteFilePath(_textureURL.fileName());
|
||||||
{
|
{
|
||||||
auto filePath = _outputDirectory.absoluteFilePath(_textureURL.fileName());
|
QFile file { originalCopyFilePath };
|
||||||
QFile file { filePath };
|
|
||||||
if (!file.open(QIODevice::WriteOnly) || file.write(_originalTexture) == -1) {
|
if (!file.open(QIODevice::WriteOnly) || file.write(_originalTexture) == -1) {
|
||||||
handleError("Could not write original texture for " + _textureURL.toString());
|
handleError("Could not write original texture for " + _textureURL.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_outputFiles.push_back(filePath);
|
_originalTexture.clear();
|
||||||
|
_outputFiles.push_back(originalCopyFilePath);
|
||||||
meta.original = _metaTexturePathPrefix +_textureURL.fileName();
|
meta.original = _metaTexturePathPrefix +_textureURL.fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// IMPORTANT: _originalTexture is empty past this point
|
auto buffer = std::shared_ptr<QIODevice>((QIODevice*)new QFile(originalCopyFilePath));
|
||||||
auto processedTexture = image::processImage(std::move(_originalTexture), _textureURL.toString().toStdString(),
|
if (!buffer->open(QIODevice::ReadOnly)) {
|
||||||
ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, _abortProcessing);
|
handleError("Could not open original file at " + originalCopyFilePath);
|
||||||
processedTexture->setSourceHash(hash);
|
|
||||||
|
|
||||||
if (shouldStop()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!processedTexture) {
|
// Compressed KTX
|
||||||
handleError("Could not process texture " + _textureURL.toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto memKTX = gpu::Texture::serialize(*processedTexture);
|
|
||||||
|
|
||||||
if (!memKTX) {
|
|
||||||
handleError("Could not serialize " + _textureURL.toString() + " to KTX");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat());
|
|
||||||
if (name == nullptr) {
|
|
||||||
handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempt to write the baked texture to the destination file path
|
|
||||||
{
|
{
|
||||||
|
// IMPORTANT: _originalTexture is empty past this point
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (shouldStop()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto memKTX = gpu::Texture::serialize(*processedTexture);
|
||||||
|
if (!memKTX) {
|
||||||
|
handleError("Could not serialize " + _textureURL.toString() + " to KTX");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat());
|
||||||
|
if (name == nullptr) {
|
||||||
|
handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const char* data = reinterpret_cast<const char*>(memKTX->_storage->data());
|
const char* data = reinterpret_cast<const char*>(memKTX->_storage->data());
|
||||||
const size_t length = memKTX->_storage->size();
|
const size_t length = memKTX->_storage->size();
|
||||||
|
|
||||||
|
@ -179,6 +185,40 @@ void TextureBaker::processTexture() {
|
||||||
meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName;
|
meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uncompressed KTX
|
||||||
|
{
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto data = meta.serialize();
|
auto data = meta.serialize();
|
||||||
|
|
|
@ -126,63 +126,63 @@ TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, con
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
|
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::create2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::create2DTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return process2DTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
|
return process2DTextureNormalMapFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
|
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return process2DTextureGrayscaleFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createCubeTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createCubeTextureFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, true, abortProcessing);
|
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, compress, true, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(QImage&& srcImage, const std::string& srcImageName,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
bool compress, const std::atomic<bool>& abortProcessing) {
|
||||||
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, false, abortProcessing);
|
return processCubeTextureColorFromImage(std::move(srcImage), srcImageName, compress, false, abortProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,17 +253,11 @@ uint32 packR11G11B10F(const glm::vec3& color) {
|
||||||
return glm::packF2x11_1x10(ucolor);
|
return glm::packF2x11_1x10(ucolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage processRawImageData(QByteArray&& content, const std::string& filename) {
|
QImage processRawImageData(QIODevice& 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);
|
|
||||||
|
|
||||||
// Help the QImage loader by extracting the image file format from the url filename ext.
|
// Help the QImage loader by extracting the image file format from the url filename ext.
|
||||||
// Some tga are not created properly without it.
|
// Some tga are not created properly without it.
|
||||||
auto filenameExtension = filename.substr(filename.find_last_of('.') + 1);
|
auto filenameExtension = filename.substr(filename.find_last_of('.') + 1);
|
||||||
QBuffer buffer;
|
QImageReader imageReader(&content, filenameExtension.c_str());
|
||||||
buffer.setData(localCopy);
|
|
||||||
QImageReader imageReader(&buffer, filenameExtension.c_str());
|
|
||||||
|
|
||||||
if (imageReader.canRead()) {
|
if (imageReader.canRead()) {
|
||||||
return imageReader.read();
|
return imageReader.read();
|
||||||
|
@ -271,8 +265,8 @@ QImage processRawImageData(QByteArray&& content, const std::string& filename) {
|
||||||
// Extension could be incorrect, try to detect the format from the content
|
// Extension could be incorrect, try to detect the format from the content
|
||||||
QImageReader newImageReader;
|
QImageReader newImageReader;
|
||||||
newImageReader.setDecideFormatFromContent(true);
|
newImageReader.setDecideFormatFromContent(true);
|
||||||
buffer.setData(localCopy);
|
content.reset();
|
||||||
newImageReader.setDevice(&buffer);
|
newImageReader.setDevice(&content);
|
||||||
|
|
||||||
if (newImageReader.canRead()) {
|
if (newImageReader.canRead()) {
|
||||||
qCWarning(imagelogging) << "Image file" << filename.c_str() << "has extension" << filenameExtension.c_str()
|
qCWarning(imagelogging) << "Image file" << filename.c_str() << "has extension" << filenameExtension.c_str()
|
||||||
|
@ -284,11 +278,14 @@ QImage processRawImageData(QByteArray&& content, const std::string& filename) {
|
||||||
return QImage();
|
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,
|
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 imageWidth = image.width();
|
||||||
int imageHeight = image.height();
|
int imageHeight = image.height();
|
||||||
|
@ -314,7 +311,7 @@ gpu::TexturePointer processImage(QByteArray&& content, const std::string& filena
|
||||||
}
|
}
|
||||||
|
|
||||||
auto loader = TextureUsage::getTextureLoaderForType(textureType);
|
auto loader = TextureUsage::getTextureLoaderForType(textureType);
|
||||||
auto texture = loader(std::move(image), filename, abortProcessing);
|
auto texture = loader(std::move(image), filename, compress, abortProcessing);
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
@ -804,7 +801,7 @@ void processTextureAlpha(const QImage& srcImage, bool& validAlpha, bool& alphaAs
|
||||||
validAlpha = (numOpaques != NUM_PIXELS);
|
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) {
|
bool isStrict, const std::atomic<bool>& abortProcessing) {
|
||||||
PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage");
|
PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage");
|
||||||
QImage image = processSourceImage(std::move(srcImage), false);
|
QImage image = processSourceImage(std::move(srcImage), false);
|
||||||
|
@ -825,7 +822,7 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
|
||||||
if ((image.width() > 0) && (image.height() > 0)) {
|
if ((image.width() > 0) && (image.height() > 0)) {
|
||||||
gpu::Element formatMip;
|
gpu::Element formatMip;
|
||||||
gpu::Element formatGPU;
|
gpu::Element formatGPU;
|
||||||
if (isColorTexturesCompressionEnabled()) {
|
if (compress) {
|
||||||
if (validAlpha) {
|
if (validAlpha) {
|
||||||
// NOTE: This disables BC1a compression because it was producing odd artifacts on text textures
|
// 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).
|
// for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts).
|
||||||
|
@ -941,7 +938,8 @@ QImage processBumpMap(QImage&& image) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName,
|
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");
|
PROFILE_RANGE(resource_parse, "process2DTextureNormalMapFromImage");
|
||||||
QImage image = processSourceImage(std::move(srcImage), false);
|
QImage image = processSourceImage(std::move(srcImage), false);
|
||||||
|
|
||||||
|
@ -959,6 +957,7 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
|
||||||
gpu::Element formatMip;
|
gpu::Element formatMip;
|
||||||
gpu::Element formatGPU;
|
gpu::Element formatGPU;
|
||||||
if (isNormalTexturesCompressionEnabled()) {
|
if (isNormalTexturesCompressionEnabled()) {
|
||||||
|
if (compress) {
|
||||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY;
|
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY;
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_GLES
|
#ifdef USE_GLES
|
||||||
|
@ -980,7 +979,7 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
bool isInvertedPixels,
|
bool compress, bool isInvertedPixels,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
const std::atomic<bool>& abortProcessing) {
|
||||||
PROFILE_RANGE(resource_parse, "process2DTextureGrayscaleFromImage");
|
PROFILE_RANGE(resource_parse, "process2DTextureGrayscaleFromImage");
|
||||||
QImage image = processSourceImage(std::move(srcImage), false);
|
QImage image = processSourceImage(std::move(srcImage), false);
|
||||||
|
@ -999,6 +998,7 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr
|
||||||
gpu::Element formatMip;
|
gpu::Element formatMip;
|
||||||
gpu::Element formatGPU;
|
gpu::Element formatGPU;
|
||||||
if (isGrayscaleTexturesCompressionEnabled()) {
|
if (isGrayscaleTexturesCompressionEnabled()) {
|
||||||
|
if (compress) {
|
||||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED;
|
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED;
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_GLES
|
#ifdef USE_GLES
|
||||||
|
@ -1345,7 +1345,7 @@ QImage convertToHDRFormat(QImage&& srcImage, gpu::Element format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName,
|
gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName,
|
||||||
bool generateIrradiance,
|
bool compress, bool generateIrradiance,
|
||||||
const std::atomic<bool>& abortProcessing) {
|
const std::atomic<bool>& abortProcessing) {
|
||||||
PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage");
|
PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage");
|
||||||
|
|
||||||
|
@ -1373,7 +1373,7 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI
|
||||||
|
|
||||||
gpu::Element formatMip;
|
gpu::Element formatMip;
|
||||||
gpu::Element formatGPU;
|
gpu::Element formatGPU;
|
||||||
if (isCubeTexturesCompressionEnabled()) {
|
if (compress) {
|
||||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
|
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_GLES
|
#ifdef USE_GLES
|
||||||
|
|
|
@ -41,60 +41,50 @@ enum Type {
|
||||||
UNUSED_TEXTURE
|
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());
|
TextureLoader getTextureLoaderForType(Type type, const QVariantMap& options = QVariantMap());
|
||||||
|
|
||||||
gpu::TexturePointer create2DTextureFromImage(QImage&& image, const std::string& srcImageName,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
gpu::TexturePointer process2DTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
|
||||||
const std::atomic<bool>& abortProcessing);
|
bool isStrict, const std::atomic<bool>& abortProcessing);
|
||||||
gpu::TexturePointer process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName, bool isBumpMap,
|
gpu::TexturePointer process2DTextureNormalMapFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
|
||||||
const std::atomic<bool>& abortProcessing);
|
bool isBumpMap, const std::atomic<bool>& abortProcessing);
|
||||||
gpu::TexturePointer process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName, bool isInvertedPixels,
|
gpu::TexturePointer process2DTextureGrayscaleFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
|
||||||
const std::atomic<bool>& abortProcessing);
|
bool isInvertedPixels, const std::atomic<bool>& abortProcessing);
|
||||||
gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool generateIrradiance,
|
gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const std::string& srcImageName, bool compress,
|
||||||
const std::atomic<bool>& abortProcessing);
|
bool generateIrradiance, const std::atomic<bool>& abortProcessing);
|
||||||
|
|
||||||
} // namespace TextureUsage
|
} // namespace TextureUsage
|
||||||
|
|
||||||
const QStringList getSupportedFormats();
|
const QStringList getSupportedFormats();
|
||||||
|
|
||||||
bool isColorTexturesCompressionEnabled();
|
gpu::TexturePointer processImage(std::shared_ptr<QIODevice> content, const std::string& url,
|
||||||
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,
|
|
||||||
int maxNumPixels, TextureUsage::Type textureType,
|
int maxNumPixels, TextureUsage::Type textureType,
|
||||||
const std::atomic<bool>& abortProcessing = false);
|
bool compress = true, const std::atomic<bool>& abortProcessing = false);
|
||||||
|
|
||||||
} // namespace image
|
} // namespace image
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,9 @@ bool TextureMeta::deserialize(const QByteArray& data, TextureMeta* meta) {
|
||||||
if (root.contains("original")) {
|
if (root.contains("original")) {
|
||||||
meta->original = root["original"].toString();
|
meta->original = root["original"].toString();
|
||||||
}
|
}
|
||||||
|
if (root.contains("uncompressed")) {
|
||||||
|
meta->uncompressed = root["uncompressed"].toString();
|
||||||
|
}
|
||||||
if (root.contains("compressed")) {
|
if (root.contains("compressed")) {
|
||||||
auto compressed = root["compressed"].toObject();
|
auto compressed = root["compressed"].toObject();
|
||||||
for (auto it = compressed.constBegin(); it != compressed.constEnd(); it++) {
|
for (auto it = compressed.constBegin(); it != compressed.constEnd(); it++) {
|
||||||
|
@ -57,6 +60,7 @@ QByteArray TextureMeta::serialize() {
|
||||||
compressed[name] = kv.second.toString();
|
compressed[name] = kv.second.toString();
|
||||||
}
|
}
|
||||||
root["original"] = original.toString();
|
root["original"] = original.toString();
|
||||||
|
root["uncompressed"] = uncompressed.toString();
|
||||||
root["compressed"] = compressed;
|
root["compressed"] = compressed;
|
||||||
doc.setObject(root);
|
doc.setObject(root);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct TextureMeta {
|
||||||
QByteArray serialize();
|
QByteArray serialize();
|
||||||
|
|
||||||
QUrl original;
|
QUrl original;
|
||||||
|
QUrl uncompressed;
|
||||||
std::unordered_map<khronos::gl::texture::InternalFormat, QUrl> availableTextureTypes;
|
std::unordered_map<khronos::gl::texture::InternalFormat, QUrl> availableTextureTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,8 @@
|
||||||
|
|
||||||
#include <TextureMeta.h>
|
#include <TextureMeta.h>
|
||||||
|
|
||||||
|
#include <OwningBuffer.h>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(trace_resource_parse_image, "trace.resource.parse.image")
|
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_raw, "trace.resource.parse.image.raw")
|
||||||
Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx")
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto loader = image::TextureUsage::getTextureLoaderForType(type, options);
|
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,
|
QSharedPointer<Resource> TextureCache::createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
||||||
|
@ -964,7 +966,6 @@ void NetworkTexture::loadMetaContent(const QByteArray& content) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto& backend = DependencyManager::get<TextureCache>()->getGPUContext()->getBackend();
|
auto& backend = DependencyManager::get<TextureCache>()->getGPUContext()->getBackend();
|
||||||
for (auto pair : meta.availableTextureTypes) {
|
for (auto pair : meta.availableTextureTypes) {
|
||||||
gpu::Element elFormat;
|
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()) {
|
if (!meta.original.isEmpty()) {
|
||||||
_currentlyLoadingResourceType = ResourceType::ORIGINAL;
|
_currentlyLoadingResourceType = ResourceType::ORIGINAL;
|
||||||
_activeUrl = _activeUrl.resolved(meta.original);
|
_activeUrl = _activeUrl.resolved(meta.original);
|
||||||
|
@ -1143,7 +1159,8 @@ void ImageReader::read() {
|
||||||
PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0);
|
PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0);
|
||||||
|
|
||||||
// IMPORTANT: _content is empty past this point
|
// 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) {
|
if (!texture) {
|
||||||
qCWarning(modelnetworking) << "Could not process:" << _url;
|
qCWarning(modelnetworking) << "Could not process:" << _url;
|
||||||
|
|
29
libraries/shared/src/OwningBuffer.h
Normal file
29
libraries/shared/src/OwningBuffer.h
Normal 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
|
|
@ -25,12 +25,6 @@ Oven* Oven::_staticInstance { nullptr };
|
||||||
Oven::Oven() {
|
Oven::Oven() {
|
||||||
_staticInstance = this;
|
_staticInstance = this;
|
||||||
|
|
||||||
// enable compression in image library
|
|
||||||
image::setColorTexturesCompressionEnabled(true);
|
|
||||||
image::setGrayscaleTexturesCompressionEnabled(true);
|
|
||||||
image::setNormalTexturesCompressionEnabled(true);
|
|
||||||
image::setCubeTexturesCompressionEnabled(true);
|
|
||||||
|
|
||||||
// setup our worker threads
|
// setup our worker threads
|
||||||
setupWorkerThreads(QThread::idealThreadCount());
|
setupWorkerThreads(QThread::idealThreadCount());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue