From 0428b22b6318993f876ef7970b4ae58f77cebdf7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 29 Mar 2017 14:53:58 -0700 Subject: [PATCH 01/32] Add nvtt external --- cmake/externals/nvtt/CMakeLists.txt | 36 ++++++++++++++++++++++++ libraries/model/CMakeLists.txt | 3 ++ libraries/model/src/model/TextureMap.cpp | 16 +++++++++++ 3 files changed, 55 insertions(+) create mode 100644 cmake/externals/nvtt/CMakeLists.txt diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt new file mode 100644 index 0000000000..4657c27bd2 --- /dev/null +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -0,0 +1,36 @@ +include(ExternalProject) +include(SelectLibraryConfigurations) + +set(EXTERNAL_NAME nvtt) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +if (NOT ANDROID) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL "C:/Users/Clement/dev/nvidia-texture-tools/project/vc12/package" + # URL_MD5 "e7f0a941c9a873f2c4334367454485da" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) + + # Hide this external target (for IDE users) + set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") + + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") + + if (WIN32) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT library") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/Release/x64 CACHE PATH "Location of NVTT DLL") + add_paths_to_fixup_libs(${${EXTERNAL_NAME_UPPER}_DLL_PATH}) + else (APPLE) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") + elseif () + set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${INSTALL_DIR}/lib/nvtt.so CACHE FILEPATH "Path to NVTT library") + endif () + +endif() diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt index 021aa3d027..b26d056bd4 100755 --- a/libraries/model/CMakeLists.txt +++ b/libraries/model/CMakeLists.txt @@ -3,3 +3,6 @@ AUTOSCRIBE_SHADER_LIB(gpu model) setup_hifi_library() link_hifi_libraries(shared ktx gpu) +add_dependency_external_projects(nvtt) +target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index e619a2d70f..d42549007b 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -10,6 +10,8 @@ // #include "TextureMap.h" +#include + #include #include @@ -222,6 +224,20 @@ void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { } } + int w = 0, h = 0; + void* data = 0; + nvtt::InputOptions inputOptions; + inputOptions.setTextureLayout(nvtt::TextureType_2D, w, h); + inputOptions.setMipmapData(data, w, h); + + nvtt::OutputOptions outputOptions; + outputOptions.setFileName("output.dds"); + + nvtt::CompressionOptions compressionOptions; + compressionOptions.setFormat(nvtt::Format_DXT1); + + nvtt::Compressor compressor; + //compressor.process(inputOptions, compressionOptions, outputOptions); #else texture->autoGenerateMips(-1); #endif From 2e1355618f7f658cb5b21d5c2c19d67e4ce62bdb Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 4 Apr 2017 16:10:07 -0700 Subject: [PATCH 02/32] Use NVTT to mipmap color textures --- libraries/model/src/model/TextureMap.cpp | 154 ++++++++++++++++++++--- 1 file changed, 138 insertions(+), 16 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index d42549007b..568b241c14 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -208,36 +208,39 @@ const QImage& image, bool isLinear, bool doCompress) { } #define CPU_MIPMAPS 1 +#define DEBUG_NVTT 0 void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); +#if DEBUG_NVTT + QDebug debug = qDebug(); + + debug << Q_FUNC_INFO << "\n"; + debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; +#endif // DEBUG_NVTT + auto numMips = texture->getNumMips(); for (uint16 level = 1; level < numMips; ++level) { QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); if (fastResize) { image = image.scaled(mipSize); + +#if DEBUG_NVTT + debug << "Begin fast { " << image.byteCount() << image.width() << image.height() << image.depth() << level << " } Ends\n"; +#endif // DEBUG_NVTT + texture->assignStoredMip(level, image.byteCount(), image.constBits()); } else { QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + +#if DEBUG_NVTT + debug << "Begin { " << mipImage.byteCount() << mipImage.width() << mipImage.height() << mipImage.depth() << level << " } Ends\n"; +#endif // DEBUG_NVTT + texture->assignStoredMip(level, mipImage.byteCount(), mipImage.constBits()); } } - - int w = 0, h = 0; - void* data = 0; - nvtt::InputOptions inputOptions; - inputOptions.setTextureLayout(nvtt::TextureType_2D, w, h); - inputOptions.setMipmapData(data, w, h); - - nvtt::OutputOptions outputOptions; - outputOptions.setFileName("output.dds"); - - nvtt::CompressionOptions compressionOptions; - compressionOptions.setFormat(nvtt::Format_DXT1); - - nvtt::Compressor compressor; - //compressor.process(inputOptions, compressionOptions, outputOptions); #else texture->autoGenerateMips(-1); #endif @@ -257,6 +260,125 @@ void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { #endif } +struct MyOutputHandler : public nvtt::OutputHandler { + MyOutputHandler(gpu::Texture* texture, QDebug* debug) : +#if DEBUG_NVTT + _debug(debug), +#endif // DEBUG_NVTT + _texture(texture) { + + } + + virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { +#if DEBUG_NVTT + auto list = QStringList() << QString::number(size) + << QString::number(width) + << QString::number(height) + << QString::number(depth) + << QString::number(face) + << QString::number(miplevel); + _count = 0; + _str = "Begin { " + list.join(", "); +#endif // DEBUG_NVTT + + _size = size; + _miplevel = miplevel; + + _data = static_cast(malloc(size)); + _current = _data; + } + virtual bool writeData(const void* data, int size) { +#if DEBUG_NVTT + ++_count; +#endif // DEBUG_NVTT + + assert(_current + size <= _data + _size); + memcpy(_current, data, size); + _current += size; + return true; + } + virtual void endImage() { +#if DEBUG_NVTT + _str += " } End " + QString::number(_count) + "\n"; + *_debug << qPrintable(_str); +#endif // DEBUG_NVTT + + _texture->assignStoredMip(_miplevel, _size, static_cast(_data)); + free(_data); + _data = nullptr; + } + +#if DEBUG_NVTT + int _count = 0; + QString _str; + QDebug* _debug{ nullptr }; +#endif // DEBUG_NVTT + gpu::Byte* _data{ nullptr }; + gpu::Byte* _current{ nullptr }; + gpu::Texture* _texture{ nullptr }; + int _miplevel = 0; + int _size = 0; +}; +struct MyErrorHandler : public nvtt::ErrorHandler { + virtual void error(nvtt::Error e) override { + qDebug() << "Texture compression error:" << nvtt::errorString(e); + } +}; + +void generateNVTTMips(gpu::Texture* texture, QImage& image, nvtt::InputFormat inputFormat, nvtt::Format compressionFormat) { +#if CPU_MIPMAPS + PROFILE_RANGE(resource_parse, "generateMips"); + + /*/ + generateMips(texture, image, false); + return; + /**/ + +#if DEBUG_NVTT + QDebug debug = qDebug(); + QDebug* debugPtr = &debug; + + debug << Q_FUNC_INFO << "\n"; + debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; +#else + QDebug* debugPtr = nullptr; +#endif // DEBUG_NVTT + + const int w = image.width(), h = image.height(); + const void* data = static_cast(image.constBits()); + + nvtt::InputOptions inputOptions; + inputOptions.setTextureLayout(nvtt::TextureType_2D, w, h); + inputOptions.setMipmapData(data, w, h); + + inputOptions.setFormat(inputFormat); + // inputOptions.setAlphaMode(AlphaMode alphaMode); + // inputOptions.setGamma(float inputGamma, float outputGamma); + // inputOptions.setWrapMode(WrapMode mode); + // inputOptions.setMaxExtents(int d); + // inputOptions.setRoundMode(RoundMode mode); + + inputOptions.setMipmapGeneration(true); + inputOptions.setMipmapFilter(nvtt::MipmapFilter_Box); + + nvtt::OutputOptions outputOptions; + outputOptions.setOutputHeader(false); + MyOutputHandler outputHandler(texture, debugPtr); + outputOptions.setOutputHandler(&outputHandler); + MyErrorHandler errorHandler; + outputOptions.setErrorHandler(&errorHandler); + + nvtt::CompressionOptions compressionOptions; + compressionOptions.setFormat(compressionFormat); + compressionOptions.setQuality(nvtt::Quality_Fastest); + + nvtt::Compressor compressor; + compressor.process(inputOptions, compressionOptions, outputOptions); +#else + texture->autoGenerateMips(-1); +#endif +} + gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool isStrict) { PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); bool validAlpha = false; @@ -288,7 +410,7 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); if (generateMips) { - ::generateMips(theTexture, image, false); + ::generateNVTTMips(theTexture, image, nvtt::InputFormat_BGRA_8UB, nvtt::Format_RGBA); } theTexture->setSource(srcImageName); } From a450f52427810f56f0b19cb280abf2202f3a488d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 7 Apr 2017 17:08:08 -0700 Subject: [PATCH 03/32] Start to setup image library --- interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 4 +- .../src/EntityTreeRenderer.cpp | 4 +- libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp | 23 +- libraries/gpu/src/gpu/Format.h | 5 +- libraries/gpu/src/gpu/Texture.h | 17 + libraries/image/CMakeLists.txt | 9 + libraries/image/src/image/Image.cpp | 1075 +++++++++++++++++ libraries/image/src/image/Image.h | 56 + libraries/image/src/image/ImageLogging.cpp | 14 + libraries/image/src/image/ImageLogging.h | 14 + libraries/model-networking/CMakeLists.txt | 2 +- .../src/model-networking/ModelCache.cpp | 40 +- .../src/model-networking/ModelCache.h | 6 +- .../src/model-networking/TextureCache.cpp | 349 ++---- .../src/model-networking/TextureCache.h | 36 +- libraries/model/CMakeLists.txt | 6 +- libraries/model/src/model/TextureMap.cpp | 965 --------------- libraries/model/src/model/TextureMap.h | 38 - .../render-utils/src/RenderDeferredTask.cpp | 2 +- tests/gpu-test/CMakeLists.txt | 2 +- tests/ktx/CMakeLists.txt | 2 +- tests/ktx/src/main.cpp | 3 +- 23 files changed, 1343 insertions(+), 1331 deletions(-) create mode 100644 libraries/image/CMakeLists.txt create mode 100644 libraries/image/src/image/Image.cpp create mode 100644 libraries/image/src/image/Image.h create mode 100644 libraries/image/src/image/ImageLogging.cpp create mode 100644 libraries/image/src/image/ImageLogging.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0006bdd778..4d58d70075 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -194,7 +194,7 @@ link_hifi_libraries( recording fbx networking model-networking entities avatars audio audio-client animation script-engine physics render-utils entities-renderer avatars-renderer ui auto-updater - controllers plugins + controllers plugins image ui-plugins display-plugins input-plugins ${NON_ANDROID_LIBRARIES} ) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2d3fbf0f93..325fa86838 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1445,8 +1445,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QString skyboxUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-cubemap.jpg" }; QString skyboxAmbientUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-ambient.jpg" }; - _defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, NetworkTexture::CUBE_TEXTURE, { { "generateIrradiance", false } }); - _defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, NetworkTexture::CUBE_TEXTURE, { { "generateIrradiance", true } }); + _defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, gpu::TextureType::CUBE_TEXTURE, { { "generateIrradiance", false } }); + _defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, gpu::TextureType::CUBE_TEXTURE, { { "generateIrradiance", true } }); _defaultSkybox->setCubemap(_defaultSkyboxTexture); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 63684dcf0f..6b06b7d389 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -495,7 +495,7 @@ bool EntityTreeRenderer::applySkyboxAndHasAmbient() { bool isAmbientSet = false; if (_pendingAmbientTexture && !_ambientTexture) { - _ambientTexture = textureCache->getTexture(_ambientTextureURL, NetworkTexture::CUBE_TEXTURE); + _ambientTexture = textureCache->getTexture(_ambientTextureURL, gpu::TextureType::CUBE_TEXTURE); } if (_ambientTexture && _ambientTexture->isLoaded()) { _pendingAmbientTexture = false; @@ -512,7 +512,7 @@ bool EntityTreeRenderer::applySkyboxAndHasAmbient() { if (_pendingSkyboxTexture && (!_skyboxTexture || (_skyboxTexture->getURL() != _skyboxTextureURL))) { - _skyboxTexture = textureCache->getTexture(_skyboxTextureURL, NetworkTexture::CUBE_TEXTURE); + _skyboxTexture = textureCache->getTexture(_skyboxTextureURL, gpu::TextureType::CUBE_TEXTURE); } if (_skyboxTexture && _skyboxTexture->isLoaded()) { _pendingSkyboxTexture = false; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index 7e26e65e02..6e918b2de1 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -224,22 +224,19 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { result = GL_COMPRESSED_SRGB_ALPHA; break; - // FIXME: WE will want to support this later - /* - case gpu::COMPRESSED_BC3_RGBA: + case gpu::COMPRESSED_BC3_RGBA: result = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; - case gpu::COMPRESSED_BC3_SRGBA: + case gpu::COMPRESSED_BC3_SRGBA: result = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; - case gpu::COMPRESSED_BC7_RGBA: + case gpu::COMPRESSED_BC7_RGBA: result = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; break; - case gpu::COMPRESSED_BC7_SRGBA: + case gpu::COMPRESSED_BC7_SRGBA: result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; break; - */ default: qCWarning(gpugllogging) << "Unknown combination of texel format"; @@ -364,25 +361,21 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E break; case gpu::COMPRESSED_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; - break; - // FIXME: WE will want to support this later - /* - case gpu::COMPRESSED_BC3_RGBA: + case gpu::COMPRESSED_BC3_RGBA: texel.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; - case gpu::COMPRESSED_BC3_SRGBA: + case gpu::COMPRESSED_BC3_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; - case gpu::COMPRESSED_BC7_RGBA: + case gpu::COMPRESSED_BC7_RGBA: texel.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; break; - case gpu::COMPRESSED_BC7_SRGBA: + case gpu::COMPRESSED_BC7_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; break; - */ default: qCWarning(gpugllogging) << "Unknown combination of texel format"; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 58115edca0..97fe76eebc 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -165,12 +165,11 @@ enum Semantic { COMPRESSED_SRGB, COMPRESSED_SRGBA, - // FIXME: Will have to be supported later: - /*COMPRESSED_BC3_RGBA, // RGBA_S3TC_DXT5_EXT, + COMPRESSED_BC3_RGBA, // RGBA_S3TC_DXT5_EXT, COMPRESSED_BC3_SRGBA, // SRGB_ALPHA_S3TC_DXT5_EXT COMPRESSED_BC7_RGBA, - COMPRESSED_BC7_SRGBA, */ + COMPRESSED_BC7_SRGBA, _LAST_COMPRESSED, diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index eab02141f0..f100b17b3b 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -157,6 +157,23 @@ enum class TextureUsageType { EXTERNAL, }; +enum TextureType { + DEFAULT_TEXTURE, + STRICT_TEXTURE, + ALBEDO_TEXTURE, + NORMAL_TEXTURE, + BUMP_TEXTURE, + SPECULAR_TEXTURE, + METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey + ROUGHNESS_TEXTURE, + GLOSS_TEXTURE, + EMISSIVE_TEXTURE, + CUBE_TEXTURE, + OCCLUSION_TEXTURE, + SCATTERING_TEXTURE = OCCLUSION_TEXTURE, + LIGHTMAP_TEXTURE +}; + class Texture : public Resource { static std::atomic _textureCPUCount; static std::atomic _textureCPUMemoryUsage; diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt new file mode 100644 index 0000000000..399d541b40 --- /dev/null +++ b/libraries/image/CMakeLists.txt @@ -0,0 +1,9 @@ +set(TARGET_NAME image) +setup_hifi_library() +link_hifi_libraries(shared gpu) + +target_glm() + +add_dependency_external_projects(nvtt) +target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp new file mode 100644 index 0000000000..f1a8e4e13b --- /dev/null +++ b/libraries/image/src/image/Image.cpp @@ -0,0 +1,1075 @@ +// +// Image.cpp +// image/src/image +// +// Created by Clement Brisset on 4/5/2017. +// Copyright 2017 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 +// + +#include "Image.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include "ImageLogging.h" + +using namespace gpu; + +// FIXME: Declare this to enable compression +//#define COMPRESS_TEXTURES +static const glm::uvec2 SPARSE_PAGE_SIZE(128); +static const glm::uvec2 MAX_TEXTURE_SIZE(4096); +bool DEV_DECIMATE_TEXTURES = false; +std::atomic DECIMATED_TEXTURE_COUNT{ 0 }; +std::atomic RECTIFIED_TEXTURE_COUNT{ 0 }; + +bool needsSparseRectification(const glm::uvec2& size) { + // Don't attempt to rectify small textures (textures less than the sparse page size in any dimension) + if (glm::any(glm::lessThan(size, SPARSE_PAGE_SIZE))) { + return false; + } + + // Don't rectify textures that are already an exact multiple of sparse page size + if (glm::uvec2(0) == (size % SPARSE_PAGE_SIZE)) { + return false; + } + + // Texture is not sparse compatible, but is bigger than the sparse page size in both dimensions, rectify! + return true; +} + +glm::uvec2 rectifyToSparseSize(const glm::uvec2& size) { + glm::uvec2 pages = ((size / SPARSE_PAGE_SIZE) + glm::clamp(size % SPARSE_PAGE_SIZE, glm::uvec2(0), glm::uvec2(1))); + glm::uvec2 result = pages * SPARSE_PAGE_SIZE; + return result; +} + + +namespace image { + +TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& options) { + switch (type) { + case gpu::ALBEDO_TEXTURE: { + return image::TextureUsage::createAlbedoTextureFromImage; + break; + } + case gpu::EMISSIVE_TEXTURE: { + return image::TextureUsage::createEmissiveTextureFromImage; + break; + } + case gpu::LIGHTMAP_TEXTURE: { + return image::TextureUsage::createLightmapTextureFromImage; + break; + } + case gpu::CUBE_TEXTURE: { + if (options.value("generateIrradiance", true).toBool()) { + return image::TextureUsage::createCubeTextureFromImage; + } else { + return image::TextureUsage::createCubeTextureFromImageWithoutIrradiance; + } + break; + } + case gpu::BUMP_TEXTURE: { + return image::TextureUsage::createNormalTextureFromBumpImage; + break; + } + case gpu::NORMAL_TEXTURE: { + return image::TextureUsage::createNormalTextureFromNormalImage; + break; + } + case gpu::ROUGHNESS_TEXTURE: { + return image::TextureUsage::createRoughnessTextureFromGlossImage; + break; + } + case gpu::GLOSS_TEXTURE: { + return image::TextureUsage::createRoughnessTextureFromGlossImage; + break; + } + case gpu::SPECULAR_TEXTURE: { + return image::TextureUsage::createMetallicTextureFromImage; + break; + } + case gpu::STRICT_TEXTURE: { + return image::TextureUsage::createStrict2DTextureFromImage; + break; + } + + case gpu::DEFAULT_TEXTURE: + default: { + return image::TextureUsage::create2DTextureFromImage; + break; + } + } +} + +gpu::Texture* processImage(const QByteArray& content, const QUrl& url, const std::string& hash, int maxNumPixels, const TextureLoader& loader) { + // Help the QImage loader by extracting the image file format from the url filename ext. + // Some tga are not created properly without it. + auto filename = url.fileName().toStdString(); + auto filenameExtension = filename.substr(filename.find_last_of('.') + 1); + QImage image = QImage::fromData(content, filenameExtension.c_str()); + int imageWidth = image.width(); + int imageHeight = image.height(); + + // Validate that the image loaded + if (imageWidth == 0 || imageHeight == 0 || image.format() == QImage::Format_Invalid) { + QString reason(filenameExtension.empty() ? "" : "(no file extension)"); + qCWarning(imagelogging) << "Failed to load" << url << reason; + return nullptr; + } + + // Validate the image is less than _maxNumPixels, and downscale if necessary + if (imageWidth * imageHeight > maxNumPixels) { + float scaleFactor = sqrtf(maxNumPixels / (float)(imageWidth * imageHeight)); + int originalWidth = imageWidth; + int originalHeight = imageHeight; + imageWidth = (int)(scaleFactor * (float)imageWidth + 0.5f); + imageHeight = (int)(scaleFactor * (float)imageHeight + 0.5f); + QImage newImage = image.scaled(QSize(imageWidth, imageHeight), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + image.swap(newImage); + qCDebug(imagelogging).nospace() << "Downscaled " << url << " (" << + QSize(originalWidth, originalHeight) << " to " << + QSize(imageWidth, imageHeight) << ")"; + } + + return loader(image, url.toString().toStdString()); +} + + + +QImage processSourceImage(const QImage& srcImage, bool cubemap) { + PROFILE_RANGE(resource_parse, "processSourceImage"); + const glm::uvec2 srcImageSize = toGlm(srcImage.size()); + glm::uvec2 targetSize = srcImageSize; + + while (glm::any(glm::greaterThan(targetSize, MAX_TEXTURE_SIZE))) { + targetSize /= 2; + } + if (targetSize != srcImageSize) { + ++DECIMATED_TEXTURE_COUNT; + } + + if (!cubemap && needsSparseRectification(targetSize)) { + ++RECTIFIED_TEXTURE_COUNT; + targetSize = rectifyToSparseSize(targetSize); + } + + if (DEV_DECIMATE_TEXTURES && glm::all(glm::greaterThanEqual(targetSize / SPARSE_PAGE_SIZE, glm::uvec2(2)))) { + targetSize /= 2; + } + + if (targetSize != srcImageSize) { + PROFILE_RANGE(resource_parse, "processSourceImage Rectify"); + qCDebug(imagelogging) << "Resizing texture from " << srcImageSize.x << "x" << srcImageSize.y << " to " << targetSize.x << "x" << targetSize.y; + return srcImage.scaled(fromGlm(targetSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + + return srcImage; +} + +const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask) { + PROFILE_RANGE(resource_parse, "process2DImageColor"); + QImage image = processSourceImage(srcImage, false); + validAlpha = false; + alphaAsMask = true; + const uint8 OPAQUE_ALPHA = 255; + const uint8 TRANSPARENT_ALPHA = 0; + if (image.hasAlphaChannel()) { + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + + // Figure out if we can use a mask for alpha or not + int numOpaques = 0; + int numTranslucents = 0; + const int NUM_PIXELS = image.width() * image.height(); + const int MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(NUM_PIXELS)); + const QRgb* data = reinterpret_cast(image.constBits()); + for (int i = 0; i < NUM_PIXELS; ++i) { + auto alpha = qAlpha(data[i]); + if (alpha == OPAQUE_ALPHA) { + numOpaques++; + } else if (alpha != TRANSPARENT_ALPHA) { + if (++numTranslucents > MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK) { + alphaAsMask = false; + break; + } + } + } + validAlpha = (numOpaques != NUM_PIXELS); + } + + // Force all the color images to be rgba32bits + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + + return image; +} + +void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, + const QImage& image, bool isLinear, bool doCompress) { + + if (image.hasAlphaChannel()) { + gpu::Semantic gpuSemantic; + gpu::Semantic mipSemantic; + if (isLinear) { + mipSemantic = gpu::BGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_BC3_RGBA; + } else { + gpuSemantic = gpu::RGBA; + } + } else { + mipSemantic = gpu::SBGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_BC3_SRGBA; + } else { + gpuSemantic = gpu::SRGBA; + } + } + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpuSemantic); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, mipSemantic); + } else { + gpu::Semantic gpuSemantic; + gpu::Semantic mipSemantic; + if (isLinear) { + mipSemantic = gpu::RGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_RGB; + } else { + gpuSemantic = gpu::RGB; + } + } else { + mipSemantic = gpu::SRGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_SRGB; + } else { + gpuSemantic = gpu::SRGB; + } + } + formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); + formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); + } +} + +#define CPU_MIPMAPS 1 +#define DEBUG_NVTT 0 + +void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { +#if CPU_MIPMAPS + PROFILE_RANGE(resource_parse, "generateMips"); +#if DEBUG_NVTT + QDebug debug = qDebug(); + + debug << Q_FUNC_INFO << "\n"; + debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; +#endif // DEBUG_NVTT + + auto numMips = texture->getNumMips(); + for (uint16 level = 1; level < numMips; ++level) { + QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); + if (fastResize) { + image = image.scaled(mipSize); + +#if DEBUG_NVTT + debug << "Begin fast { " << image.byteCount() << image.width() << image.height() << image.depth() << level << " } Ends\n"; +#endif // DEBUG_NVTT + + texture->assignStoredMip(level, image.byteCount(), image.constBits()); + } else { + QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + +#if DEBUG_NVTT + debug << "Begin { " << mipImage.byteCount() << mipImage.width() << mipImage.height() << mipImage.depth() << level << " } Ends\n"; +#endif // DEBUG_NVTT + + texture->assignStoredMip(level, mipImage.byteCount(), mipImage.constBits()); + } + } +#else + texture->autoGenerateMips(-1); +#endif +} + +void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { +#if CPU_MIPMAPS + PROFILE_RANGE(resource_parse, "generateFaceMips"); + auto numMips = texture->getNumMips(); + for (uint16 level = 1; level < numMips; ++level) { + QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); + QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + texture->assignStoredMipFace(level, face, mipImage.byteCount(), mipImage.constBits()); + } +#else + texture->autoGenerateMips(-1); +#endif +} + +struct MyOutputHandler : public nvtt::OutputHandler { + MyOutputHandler(gpu::Texture* texture, QDebug* debug) : +#if DEBUG_NVTT + _debug(debug), +#endif // DEBUG_NVTT + _texture(texture) { + + } + + virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { +#if DEBUG_NVTT + auto list = QStringList() << QString::number(size) + << QString::number(width) + << QString::number(height) + << QString::number(depth) + << QString::number(face) + << QString::number(miplevel); + _count = 0; + _str = "Begin { " + list.join(", "); +#endif // DEBUG_NVTT + + _size = size; + _miplevel = miplevel; + + _data = static_cast(malloc(size)); + _current = _data; + } + virtual bool writeData(const void* data, int size) { +#if DEBUG_NVTT + ++_count; +#endif // DEBUG_NVTT + + assert(_current + size <= _data + _size); + memcpy(_current, data, size); + _current += size; + return true; + } + virtual void endImage() { +#if DEBUG_NVTT + _str += " } End " + QString::number(_count) + "\n"; + *_debug << qPrintable(_str); +#endif // DEBUG_NVTT + + _texture->assignStoredMip(_miplevel, _size, static_cast(_data)); + free(_data); + _data = nullptr; + } + +#if DEBUG_NVTT + int _count = 0; + QString _str; + QDebug* _debug{ nullptr }; +#endif // DEBUG_NVTT + gpu::Byte* _data{ nullptr }; + gpu::Byte* _current{ nullptr }; + gpu::Texture* _texture{ nullptr }; + int _miplevel = 0; + int _size = 0; +}; +struct MyErrorHandler : public nvtt::ErrorHandler { + virtual void error(nvtt::Error e) override { + qDebug() << "Texture compression error:" << nvtt::errorString(e); + } +}; + +void generateNVTTMips(gpu::Texture* texture, QImage& image) { +#if CPU_MIPMAPS + PROFILE_RANGE(resource_parse, "generateMips"); + + /*/ + generateMips(texture, image, false); + return; + /**/ + +#if DEBUG_NVTT + QDebug debug = qDebug(); + QDebug* debugPtr = &debug; + + debug << Q_FUNC_INFO << "\n"; + debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; +#else + QDebug* debugPtr = nullptr; +#endif // DEBUG_NVTT + + Q_ASSERT(image.format() == QImage::Format_ARGB32); + + const int width = image.width(), height = image.height(); + const void* data = static_cast(image.constBits()); + + nvtt::TextureType textureType = nvtt::TextureType_2D; + nvtt::InputFormat inputFormat = nvtt::InputFormat_BGRA_8UB; + nvtt::AlphaMode alphaMode = image.hasAlphaChannel() ? nvtt::AlphaMode_Transparency : nvtt::AlphaMode_None; + nvtt::WrapMode wrapMode = nvtt::WrapMode_Repeat; + nvtt::Format compressionFormat = image.hasAlphaChannel() ? nvtt::Format_RGBA : nvtt::Format_RGB; + float inputGamma = 1.0f; + float outputGamma = 2.2f; + + nvtt::InputOptions inputOptions; + inputOptions.setTextureLayout(textureType, width, height); + inputOptions.setMipmapData(data, width, height); + + inputOptions.setFormat(inputFormat); + inputOptions.setGamma(inputGamma, outputGamma); + inputOptions.setAlphaMode(alphaMode); + inputOptions.setWrapMode(wrapMode); + // inputOptions.setMaxExtents(int d); + // inputOptions.setRoundMode(RoundMode mode); + + inputOptions.setMipmapGeneration(true); + inputOptions.setMipmapFilter(nvtt::MipmapFilter_Box); + + nvtt::OutputOptions outputOptions; + outputOptions.setOutputHeader(false); + MyOutputHandler outputHandler(texture, debugPtr); + outputOptions.setOutputHandler(&outputHandler); + MyErrorHandler errorHandler; + outputOptions.setErrorHandler(&errorHandler); + + nvtt::CompressionOptions compressionOptions; + compressionOptions.setFormat(compressionFormat); + compressionOptions.setQuality(nvtt::Quality_Production); + + nvtt::Compressor compressor; + compressor.process(inputOptions, compressionOptions, outputOptions); +#else + texture->autoGenerateMips(-1); +#endif +} + +gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool isStrict) { + PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); + bool validAlpha = false; + bool alphaAsMask = true; + QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); + + gpu::Texture* theTexture = nullptr; + + if ((image.width() > 0) && (image.height() > 0)) { + gpu::Element formatGPU; + gpu::Element formatMip; + defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); + + if (isStrict) { + theTexture = (gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + } else { + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + } + theTexture->setSource(srcImageName); + auto usage = gpu::Texture::Usage::Builder().withColor(); + if (validAlpha) { + usage.withAlpha(); + if (alphaAsMask) { + usage.withAlphaMask(); + } + } + theTexture->setUsage(usage.build()); + theTexture->setStoredMipFormat(formatMip); + + if (generateMips) { + generateNVTTMips(theTexture, image); + } + theTexture->setSource(srcImageName); + } + + return theTexture; +} + +gpu::Texture* TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true, true); +} + +gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); +} + +gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); +} + +gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); +} + +gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); +} + + +gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { + PROFILE_RANGE(resource_parse, "createNormalTextureFromNormalImage"); + QImage image = processSourceImage(srcImage, false); + + // Make sure the normal map source image is ARGB32 + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { + + gpu::Element formatMip = gpu::Element::COLOR_BGRA_32; + gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->setSource(srcImageName); + theTexture->setStoredMipFormat(formatMip); + theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + generateMips(theTexture, image, true); + + theTexture->setSource(srcImageName); + } + + return theTexture; +} + +int clampPixelCoordinate(int coordinate, int maxCoordinate) { + return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate)); +} + +const int RGBA_MAX = 255; + +// transform -1 - 1 to 0 - 255 (from sobel value to rgb) +double mapComponent(double sobelValue) { + const double factor = RGBA_MAX / 2.0; + return (sobelValue + 1.0) * factor; +} + +gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) { + PROFILE_RANGE(resource_parse, "createNormalTextureFromBumpImage"); + QImage image = processSourceImage(srcImage, false); + + if (image.format() != QImage::Format_Grayscale8) { + image = image.convertToFormat(QImage::Format_Grayscale8); + } + + // PR 5540 by AlessandroSigna integrated here as a specialized TextureLoader for bumpmaps + // The conversion is done using the Sobel Filter to calculate the derivatives from the grayscale image + const double pStrength = 2.0; + int width = image.width(); + int height = image.height(); + + QImage result(width, height, QImage::Format_ARGB32); + + for (int i = 0; i < width; i++) { + const int iNextClamped = clampPixelCoordinate(i + 1, width - 1); + const int iPrevClamped = clampPixelCoordinate(i - 1, width - 1); + + for (int j = 0; j < height; j++) { + const int jNextClamped = clampPixelCoordinate(j + 1, height - 1); + const int jPrevClamped = clampPixelCoordinate(j - 1, height - 1); + + // surrounding pixels + const QRgb topLeft = image.pixel(iPrevClamped, jPrevClamped); + const QRgb top = image.pixel(iPrevClamped, j); + const QRgb topRight = image.pixel(iPrevClamped, jNextClamped); + const QRgb right = image.pixel(i, jNextClamped); + const QRgb bottomRight = image.pixel(iNextClamped, jNextClamped); + const QRgb bottom = image.pixel(iNextClamped, j); + const QRgb bottomLeft = image.pixel(iNextClamped, jPrevClamped); + const QRgb left = image.pixel(i, jPrevClamped); + + // take their gray intensities + // since it's a grayscale image, the value of each component RGB is the same + const double tl = qRed(topLeft); + const double t = qRed(top); + const double tr = qRed(topRight); + const double r = qRed(right); + const double br = qRed(bottomRight); + const double b = qRed(bottom); + const double bl = qRed(bottomLeft); + const double l = qRed(left); + + // apply the sobel filter + const double dX = (tr + pStrength * r + br) - (tl + pStrength * l + bl); + const double dY = (bl + pStrength * b + br) - (tl + pStrength * t + tr); + const double dZ = RGBA_MAX / pStrength; + + glm::vec3 v(dX, dY, dZ); + glm::normalize(v); + + // convert to rgb from the value obtained computing the filter + QRgb qRgbValue = qRgba(mapComponent(v.z), mapComponent(v.y), mapComponent(v.x), 1.0); + result.setPixel(i, j, qRgbValue); + } + } + + gpu::Texture* theTexture = nullptr; + if ((result.width() > 0) && (result.height() > 0)) { + + gpu::Element formatMip = gpu::Element::COLOR_BGRA_32; + gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; + + + theTexture = (gpu::Texture::create2D(formatGPU, result.width(), result.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->setSource(srcImageName); + theTexture->setStoredMipFormat(formatMip); + theTexture->assignStoredMip(0, result.byteCount(), result.constBits()); + generateMips(theTexture, result, true); + + theTexture->setSource(srcImageName); + } + + return theTexture; +} + +gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + PROFILE_RANGE(resource_parse, "createRoughnessTextureFromImage"); + QImage image = processSourceImage(srcImage, false); + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + } else { + if (image.format() != QImage::Format_RGBA8888) { + image = image.convertToFormat(QImage::Format_RGBA8888); + } + } + + image = image.convertToFormat(QImage::Format_Grayscale8); + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { +#ifdef COMPRESS_TEXTURES + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); +#else + gpu::Element formatGPU = gpu::Element::COLOR_R_8; +#endif + gpu::Element formatMip = gpu::Element::COLOR_R_8; + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->setSource(srcImageName); + theTexture->setStoredMipFormat(formatMip); + theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + generateMips(theTexture, image, true); + + theTexture->setSource(srcImageName); + } + + return theTexture; +} + +gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) { + PROFILE_RANGE(resource_parse, "createRoughnessTextureFromGlossImage"); + QImage image = processSourceImage(srcImage, false); + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + } else { + if (image.format() != QImage::Format_RGBA8888) { + image = image.convertToFormat(QImage::Format_RGBA8888); + } + } + + // Gloss turned into Rough + image.invertPixels(QImage::InvertRgba); + + image = image.convertToFormat(QImage::Format_Grayscale8); + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { + +#ifdef COMPRESS_TEXTURES + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); +#else + gpu::Element formatGPU = gpu::Element::COLOR_R_8; +#endif + gpu::Element formatMip = gpu::Element::COLOR_R_8; + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->setSource(srcImageName); + theTexture->setStoredMipFormat(formatMip); + theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + generateMips(theTexture, image, true); + + theTexture->setSource(srcImageName); + } + + return theTexture; +} + +gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + PROFILE_RANGE(resource_parse, "createMetallicTextureFromImage"); + QImage image = processSourceImage(srcImage, false); + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + } else { + if (image.format() != QImage::Format_RGBA8888) { + image = image.convertToFormat(QImage::Format_RGBA8888); + } + } + + image = image.convertToFormat(QImage::Format_Grayscale8); + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { + +#ifdef COMPRESS_TEXTURES + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); +#else + gpu::Element formatGPU = gpu::Element::COLOR_R_8; +#endif + gpu::Element formatMip = gpu::Element::COLOR_R_8; + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->setSource(srcImageName); + theTexture->setStoredMipFormat(formatMip); + theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + generateMips(theTexture, image, true); + + theTexture->setSource(srcImageName); + } + + return theTexture; +} + +class CubeLayout { +public: + + enum SourceProjection { + FLAT = 0, + EQUIRECTANGULAR, + }; + int _type = FLAT; + int _widthRatio = 1; + int _heightRatio = 1; + + class Face { + public: + int _x = 0; + int _y = 0; + bool _horizontalMirror = false; + bool _verticalMirror = false; + + Face() {} + Face(int x, int y, bool horizontalMirror, bool verticalMirror) : _x(x), _y(y), _horizontalMirror(horizontalMirror), _verticalMirror(verticalMirror) {} + }; + + Face _faceXPos; + Face _faceXNeg; + Face _faceYPos; + Face _faceYNeg; + Face _faceZPos; + Face _faceZNeg; + + CubeLayout(int wr, int hr, Face fXP, Face fXN, Face fYP, Face fYN, Face fZP, Face fZN) : + _type(FLAT), + _widthRatio(wr), + _heightRatio(hr), + _faceXPos(fXP), + _faceXNeg(fXN), + _faceYPos(fYP), + _faceYNeg(fYN), + _faceZPos(fZP), + _faceZNeg(fZN) {} + + CubeLayout(int wr, int hr) : + _type(EQUIRECTANGULAR), + _widthRatio(wr), + _heightRatio(hr) {} + + + static const CubeLayout CUBEMAP_LAYOUTS[]; + static const int NUM_CUBEMAP_LAYOUTS; + + static int findLayout(int width, int height) { + // Find the layout of the cubemap in the 2D image + int foundLayout = -1; + for (int i = 0; i < NUM_CUBEMAP_LAYOUTS; i++) { + if ((height * CUBEMAP_LAYOUTS[i]._widthRatio) == (width * CUBEMAP_LAYOUTS[i]._heightRatio)) { + foundLayout = i; + break; + } + } + return foundLayout; + } + + static QImage extractEquirectangularFace(const QImage& source, gpu::Texture::CubeFace face, int faceWidth) { + QImage image(faceWidth, faceWidth, source.format()); + + glm::vec2 dstInvSize(1.0f / (float)image.width(), 1.0f / (float)image.height()); + + struct CubeToXYZ { + gpu::Texture::CubeFace _face; + CubeToXYZ(gpu::Texture::CubeFace face) : _face(face) {} + + glm::vec3 xyzFrom(const glm::vec2& uv) { + auto faceDir = glm::normalize(glm::vec3(-1.0f + 2.0f * uv.x, -1.0f + 2.0f * uv.y, 1.0f)); + + switch (_face) { + case gpu::Texture::CubeFace::CUBE_FACE_BACK_POS_Z: + return glm::vec3(-faceDir.x, faceDir.y, faceDir.z); + case gpu::Texture::CubeFace::CUBE_FACE_FRONT_NEG_Z: + return glm::vec3(faceDir.x, faceDir.y, -faceDir.z); + case gpu::Texture::CubeFace::CUBE_FACE_LEFT_NEG_X: + return glm::vec3(faceDir.z, faceDir.y, faceDir.x); + case gpu::Texture::CubeFace::CUBE_FACE_RIGHT_POS_X: + return glm::vec3(-faceDir.z, faceDir.y, -faceDir.x); + case gpu::Texture::CubeFace::CUBE_FACE_BOTTOM_NEG_Y: + return glm::vec3(-faceDir.x, -faceDir.z, faceDir.y); + case gpu::Texture::CubeFace::CUBE_FACE_TOP_POS_Y: + default: + return glm::vec3(-faceDir.x, faceDir.z, -faceDir.y); + } + } + }; + CubeToXYZ cubeToXYZ(face); + + struct RectToXYZ { + RectToXYZ() {} + + glm::vec2 uvFrom(const glm::vec3& xyz) { + auto flatDir = glm::normalize(glm::vec2(xyz.x, xyz.z)); + auto uvRad = glm::vec2(atan2(flatDir.x, flatDir.y), asin(xyz.y)); + + const float LON_TO_RECT_U = 1.0f / (glm::pi()); + const float LAT_TO_RECT_V = 2.0f / glm::pi(); + return glm::vec2(0.5f * uvRad.x * LON_TO_RECT_U + 0.5f, 0.5f * uvRad.y * LAT_TO_RECT_V + 0.5f); + } + }; + RectToXYZ rectToXYZ; + + int srcFaceHeight = source.height(); + int srcFaceWidth = source.width(); + + glm::vec2 dstCoord; + glm::ivec2 srcPixel; + for (int y = 0; y < faceWidth; ++y) { + dstCoord.y = 1.0f - (y + 0.5f) * dstInvSize.y; // Fill cube face images from top to bottom + for (int x = 0; x < faceWidth; ++x) { + dstCoord.x = (x + 0.5f) * dstInvSize.x; + + auto xyzDir = cubeToXYZ.xyzFrom(dstCoord); + auto srcCoord = rectToXYZ.uvFrom(xyzDir); + + srcPixel.x = floor(srcCoord.x * srcFaceWidth); + // Flip the vertical axis to QImage going top to bottom + srcPixel.y = floor((1.0f - srcCoord.y) * srcFaceHeight); + + if (((uint32)srcPixel.x < (uint32)source.width()) && ((uint32)srcPixel.y < (uint32)source.height())) { + image.setPixel(x, y, source.pixel(QPoint(srcPixel.x, srcPixel.y))); + + // Keep for debug, this is showing the dir as a color + // glm::u8vec4 rgba((xyzDir.x + 1.0)*0.5 * 256, (xyzDir.y + 1.0)*0.5 * 256, (xyzDir.z + 1.0)*0.5 * 256, 256); + // unsigned int val = 0xff000000 | (rgba.r) | (rgba.g << 8) | (rgba.b << 16); + // image.setPixel(x, y, val); + } + } + } + return image; + } +}; + +const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { + + // Here is the expected layout for the faces in an image with the 2/1 aspect ratio: + // THis is detected as an Equirectangular projection + // WIDTH + // <---------------------------> + // ^ +------+------+------+------+ + // H | | | | | + // E | | | | | + // I | | | | | + // G +------+------+------+------+ + // H | | | | | + // T | | | | | + // | | | | | | + // v +------+------+------+------+ + // + // FaceWidth = width = height / 6 + { 2, 1 }, + + // Here is the expected layout for the faces in an image with the 1/6 aspect ratio: + // + // WIDTH + // <------> + // ^ +------+ + // | | | + // | | +X | + // | | | + // H +------+ + // E | | + // I | -X | + // G | | + // H +------+ + // T | | + // | | +Y | + // | | | + // | +------+ + // | | | + // | | -Y | + // | | | + // H +------+ + // E | | + // I | +Z | + // G | | + // H +------+ + // T | | + // | | -Z | + // | | | + // V +------+ + // + // FaceWidth = width = height / 6 + { 1, 6, + { 0, 0, true, false }, + { 0, 1, true, false }, + { 0, 2, false, true }, + { 0, 3, false, true }, + { 0, 4, true, false }, + { 0, 5, true, false } + }, + + // Here is the expected layout for the faces in an image with the 3/4 aspect ratio: + // + // <-----------WIDTH-----------> + // ^ +------+------+------+------+ + // | | | | | | + // | | | +Y | | | + // | | | | | | + // H +------+------+------+------+ + // E | | | | | + // I | -X | -Z | +X | +Z | + // G | | | | | + // H +------+------+------+------+ + // T | | | | | + // | | | -Y | | | + // | | | | | | + // V +------+------+------+------+ + // + // FaceWidth = width / 4 = height / 3 + { 4, 3, + { 2, 1, true, false }, + { 0, 1, true, false }, + { 1, 0, false, true }, + { 1, 2, false, true }, + { 3, 1, true, false }, + { 1, 1, true, false } + }, + + // Here is the expected layout for the faces in an image with the 4/3 aspect ratio: + // + // <-------WIDTH--------> + // ^ +------+------+------+ + // | | | | | + // | | | +Y | | + // | | | | | + // H +------+------+------+ + // E | | | | + // I | -X | -Z | +X | + // G | | | | + // H +------+------+------+ + // T | | | | + // | | | -Y | | + // | | | | | + // | +------+------+------+ + // | | | | | + // | | | +Z! | | <+Z is upside down! + // | | | | | + // V +------+------+------+ + // + // FaceWidth = width / 3 = height / 4 + { 3, 4, + { 2, 1, true, false }, + { 0, 1, true, false }, + { 1, 0, false, true }, + { 1, 2, false, true }, + { 1, 3, false, true }, + { 1, 1, true, false } + } +}; +const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); + +gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance) { + PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage"); + + gpu::Texture* theTexture = nullptr; + if ((srcImage.width() > 0) && (srcImage.height() > 0)) { + QImage image = processSourceImage(srcImage, true); + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + + gpu::Element formatGPU; + gpu::Element formatMip; + defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); + + // Find the layout of the cubemap in the 2D image + // Use the original image size since processSourceImage may have altered the size / aspect ratio + int foundLayout = CubeLayout::findLayout(srcImage.width(), srcImage.height()); + + std::vector faces; + // If found, go extract the faces as separate images + if (foundLayout >= 0) { + auto& layout = CubeLayout::CUBEMAP_LAYOUTS[foundLayout]; + if (layout._type == CubeLayout::FLAT) { + int faceWidth = image.width() / layout._widthRatio; + + faces.push_back(image.copy(QRect(layout._faceXPos._x * faceWidth, layout._faceXPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXPos._horizontalMirror, layout._faceXPos._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceXNeg._x * faceWidth, layout._faceXNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXNeg._horizontalMirror, layout._faceXNeg._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceYPos._x * faceWidth, layout._faceYPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYPos._horizontalMirror, layout._faceYPos._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceYNeg._x * faceWidth, layout._faceYNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYNeg._horizontalMirror, layout._faceYNeg._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceZPos._x * faceWidth, layout._faceZPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZPos._horizontalMirror, layout._faceZPos._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceZNeg._x * faceWidth, layout._faceZNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZNeg._horizontalMirror, layout._faceZNeg._verticalMirror)); + } else if (layout._type == CubeLayout::EQUIRECTANGULAR) { + // THe face width is estimated from the input image + const int EQUIRECT_FACE_RATIO_TO_WIDTH = 4; + const int EQUIRECT_MAX_FACE_WIDTH = 2048; + int faceWidth = std::min(image.width() / EQUIRECT_FACE_RATIO_TO_WIDTH, EQUIRECT_MAX_FACE_WIDTH); + for (int face = gpu::Texture::CUBE_FACE_RIGHT_POS_X; face < gpu::Texture::NUM_CUBE_FACES; face++) { + QImage faceImage = CubeLayout::extractEquirectangularFace(image, (gpu::Texture::CubeFace) face, faceWidth); + faces.push_back(faceImage); + } + } + } else { + qCDebug(imagelogging) << "Failed to find a known cube map layout from this image:" << QString(srcImageName.c_str()); + return nullptr; + } + + // If the 6 faces have been created go on and define the true Texture + if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) { + theTexture = gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); + theTexture->setSource(srcImageName); + theTexture->setStoredMipFormat(formatMip); + int f = 0; + for (auto& face : faces) { + theTexture->assignStoredMipFace(0, f, face.byteCount(), face.constBits()); + if (generateMips) { + generateFaceMips(theTexture, face, f); + } + f++; + } + + // Generate irradiance while we are at it + if (generateIrradiance) { + PROFILE_RANGE(resource_parse, "generateIrradiance"); + theTexture->generateIrradiance(); + } + + theTexture->setSource(srcImageName); + } + } + + return theTexture; +} + +gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, true); +} + +gpu::Texture* TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { + return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, false); +} + +} // namespace image \ No newline at end of file diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h new file mode 100644 index 0000000000..a311514a66 --- /dev/null +++ b/libraries/image/src/image/Image.h @@ -0,0 +1,56 @@ +// +// Image.h +// image/src/image +// +// Created by Clement Brisset on 4/5/2017. +// Copyright 2017 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_image_Image_h +#define hifi_image_Image_h + +#include + +#include + +class QByteArray; +class QImage; +class QUrl; + +namespace image { + +using TextureLoader = std::function; + +TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& options = QVariantMap()); + +gpu::Texture* processImage(const QByteArray& content, const QUrl& url, const std::string& hash, int maxNumPixels, const TextureLoader& loader); + +namespace TextureUsage { + +gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createStrict2DTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createAlbedoTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createEmissiveTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createRoughnessTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createRoughnessTextureFromGlossImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createMetallicTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::Texture* createCubeTextureFromImageWithoutIrradiance(const QImage& image, const std::string& srcImageName); +gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); + +const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); +void defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, + const QImage& srcImage, bool isLinear, bool doCompress); +gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool isStrict = false); +gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance); + +} // namespace TextureUsage + +} // namespace image + +#endif // hifi_image_Image_h diff --git a/libraries/image/src/image/ImageLogging.cpp b/libraries/image/src/image/ImageLogging.cpp new file mode 100644 index 0000000000..ef78b44e02 --- /dev/null +++ b/libraries/image/src/image/ImageLogging.cpp @@ -0,0 +1,14 @@ +// +// ImageLogging.cpp +// image/src/image +// +// Created by Clement Brisset on 4/5/2017. +// Copyright 2017 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 +// + +#include "ImageLogging.h" + +Q_LOGGING_CATEGORY(imagelogging, "hifi.model") \ No newline at end of file diff --git a/libraries/image/src/image/ImageLogging.h b/libraries/image/src/image/ImageLogging.h new file mode 100644 index 0000000000..668d8b9ff9 --- /dev/null +++ b/libraries/image/src/image/ImageLogging.h @@ -0,0 +1,14 @@ +// +// ImageLogging.h +// image/src/image +// +// Created by Clement Brisset on 4/5/2017. +// Copyright 2017 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 +// + +#include + +Q_DECLARE_LOGGING_CATEGORY(imagelogging) diff --git a/libraries/model-networking/CMakeLists.txt b/libraries/model-networking/CMakeLists.txt index 00aa17ff57..f7175bc533 100644 --- a/libraries/model-networking/CMakeLists.txt +++ b/libraries/model-networking/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME model-networking) setup_hifi_library() -link_hifi_libraries(shared networking model fbx ktx) +link_hifi_libraries(shared networking model fbx ktx image) diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index a5df41e944..cd673cdf98 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -489,7 +489,7 @@ QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const FBXTexture& textu } model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture, - TextureType type, MapChannel channel) { + gpu::TextureType type, MapChannel channel) { const auto url = getTextureUrl(baseUrl, fbxTexture); const auto texture = DependencyManager::get()->getTexture(url, type, fbxTexture.content, fbxTexture.maxNumPixels); _textures[channel] = Texture { fbxTexture.name, texture }; @@ -503,7 +503,7 @@ model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, c return map; } -model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, TextureType type, MapChannel channel) { +model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, gpu::TextureType type, MapChannel channel) { const auto texture = DependencyManager::get()->getTexture(url, type); _textures[channel].texture = texture; @@ -518,7 +518,7 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur { _textures = Textures(MapChannel::NUM_MAP_CHANNELS); if (!material.albedoTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, NetworkTexture::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, gpu::TextureType::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); _albedoTransform = material.albedoTexture.transform; map->setTextureTransform(_albedoTransform); @@ -535,45 +535,45 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur if (!material.normalTexture.filename.isEmpty()) { - auto type = (material.normalTexture.isBumpmap ? NetworkTexture::BUMP_TEXTURE : NetworkTexture::NORMAL_TEXTURE); + auto type = (material.normalTexture.isBumpmap ? gpu::TextureType::BUMP_TEXTURE : gpu::TextureType::NORMAL_TEXTURE); auto map = fetchTextureMap(textureBaseUrl, material.normalTexture, type, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } if (!material.roughnessTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, NetworkTexture::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, gpu::TextureType::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } else if (!material.glossTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, NetworkTexture::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, gpu::TextureType::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } if (!material.metallicTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, NetworkTexture::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, gpu::TextureType::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } else if (!material.specularTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, NetworkTexture::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, gpu::TextureType::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } if (!material.occlusionTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, NetworkTexture::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, gpu::TextureType::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); map->setTextureTransform(material.occlusionTexture.transform); setTextureMap(MapChannel::OCCLUSION_MAP, map); } if (!material.emissiveTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, NetworkTexture::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, gpu::TextureType::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); setTextureMap(MapChannel::EMISSIVE_MAP, map); } if (!material.scatteringTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, NetworkTexture::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, gpu::TextureType::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); setTextureMap(MapChannel::SCATTERING_MAP, map); } if (!material.lightmapTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, NetworkTexture::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, gpu::TextureType::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); _lightmapTransform = material.lightmapTexture.transform; _lightmapParams = material.lightmapParams; map->setTextureTransform(_lightmapTransform); @@ -596,7 +596,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!albedoName.isEmpty()) { auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NetworkTexture::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); map->setTextureTransform(_albedoTransform); // when reassigning the albedo texture we also check for the alpha channel used as opacity map->setUseAlphaChannel(true); @@ -605,45 +605,45 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!normalName.isEmpty()) { auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NetworkTexture::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } if (!roughnessName.isEmpty()) { auto url = textureMap.contains(roughnessName) ? textureMap[roughnessName].toUrl() : QUrl(); // FIXME: If passing a gloss map instead of a roughmap how do we know? - auto map = fetchTextureMap(url, NetworkTexture::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } if (!metallicName.isEmpty()) { auto url = textureMap.contains(metallicName) ? textureMap[metallicName].toUrl() : QUrl(); // FIXME: If passing a specular map instead of a metallic how do we know? - auto map = fetchTextureMap(url, NetworkTexture::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } if (!occlusionName.isEmpty()) { auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NetworkTexture::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); setTextureMap(MapChannel::OCCLUSION_MAP, map); } if (!emissiveName.isEmpty()) { auto url = textureMap.contains(emissiveName) ? textureMap[emissiveName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NetworkTexture::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); setTextureMap(MapChannel::EMISSIVE_MAP, map); } if (!scatteringName.isEmpty()) { auto url = textureMap.contains(scatteringName) ? textureMap[scatteringName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NetworkTexture::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); setTextureMap(MapChannel::SCATTERING_MAP, map); } if (!lightmapName.isEmpty()) { auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NetworkTexture::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + auto map = fetchTextureMap(url, gpu::TextureType::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); map->setTextureTransform(_lightmapTransform); map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); setTextureMap(MapChannel::LIGHTMAP_MAP, map); diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 967897477d..ea86b819da 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -180,13 +180,11 @@ protected: const bool& isOriginal() const { return _isOriginal; } private: - using TextureType = NetworkTexture::Type; - // Helpers for the ctors QUrl getTextureUrl(const QUrl& baseUrl, const FBXTexture& fbxTexture); model::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture, - TextureType type, MapChannel channel); - model::TextureMapPointer fetchTextureMap(const QUrl& url, TextureType type, MapChannel channel); + gpu::TextureType type, MapChannel channel); + model::TextureMapPointer fetchTextureMap(const QUrl& url, gpu::TextureType type, MapChannel channel); Transform _albedoTransform; Transform _lightmapTransform; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 98b03eba1e..a9ddee01fb 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -13,11 +13,12 @@ #include -#include -#include +#include +#include #include #include -#include +#include +#include #if DEBUG_DUMP_TEXTURE_LOADS #include @@ -31,10 +32,13 @@ #include +#include + #include #include #include +#include #include "ModelNetworkingLogging.h" #include @@ -51,16 +55,6 @@ TextureCache::TextureCache() : _ktxCache(KTX_DIRNAME, KTX_EXT) { setUnusedResourceCacheSize(0); setObjectName("TextureCache"); - - // Expose enum Type to JS/QML via properties - // Despite being one-off, this should be fine, because TextureCache is a SINGLETON_DEPENDENCY - QObject* type = new QObject(this); - type->setObjectName("TextureType"); - setProperty("Type", QVariant::fromValue(type)); - auto metaEnum = QMetaEnum::fromType(); - for (int i = 0; i < metaEnum.keyCount(); ++i) { - type->setProperty(metaEnum.key(i), metaEnum.value(i)); - } } TextureCache::~TextureCache() { @@ -172,18 +166,18 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() { /// Extra data for creating textures. class TextureExtra { public: - NetworkTexture::Type type; + gpu::TextureType type; const QByteArray& content; int maxNumPixels; }; ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels) { auto byteArray = QByteArray(); - TextureExtra extra = { (Type)type, byteArray, maxNumPixels }; + TextureExtra extra = { (gpu::TextureType)type, byteArray, maxNumPixels }; return ResourceCache::prefetch(url, &extra); } -NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const QByteArray& content, int maxNumPixels) { +NetworkTexturePointer TextureCache::getTexture(const QUrl& url, gpu::TextureType type, const QByteArray& content, int maxNumPixels) { TextureExtra extra = { type, content, maxNumPixels }; return ResourceCache::getResource(url, QUrl(), &extra).staticCast(); } @@ -216,8 +210,7 @@ gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, co return result; } - -gpu::TexturePointer getFallbackTextureForType(NetworkTexture::Type type) { +gpu::TexturePointer getFallbackTextureForType(gpu::TextureType type) { gpu::TexturePointer result; auto textureCache = DependencyManager::get(); // Since this can be called on a background thread, there's a chance that the cache @@ -226,116 +219,51 @@ gpu::TexturePointer getFallbackTextureForType(NetworkTexture::Type type) { return result; } switch (type) { - case NetworkTexture::DEFAULT_TEXTURE: - case NetworkTexture::ALBEDO_TEXTURE: - case NetworkTexture::ROUGHNESS_TEXTURE: - case NetworkTexture::OCCLUSION_TEXTURE: + case gpu::DEFAULT_TEXTURE: + case gpu::ALBEDO_TEXTURE: + case gpu::ROUGHNESS_TEXTURE: + case gpu::OCCLUSION_TEXTURE: result = textureCache->getWhiteTexture(); break; - case NetworkTexture::NORMAL_TEXTURE: + case gpu::NORMAL_TEXTURE: result = textureCache->getBlueTexture(); break; - case NetworkTexture::EMISSIVE_TEXTURE: - case NetworkTexture::LIGHTMAP_TEXTURE: + case gpu::EMISSIVE_TEXTURE: + case gpu::LIGHTMAP_TEXTURE: result = textureCache->getBlackTexture(); break; - case NetworkTexture::BUMP_TEXTURE: - case NetworkTexture::SPECULAR_TEXTURE: - case NetworkTexture::GLOSS_TEXTURE: - case NetworkTexture::CUBE_TEXTURE: - case NetworkTexture::CUSTOM_TEXTURE: - case NetworkTexture::STRICT_TEXTURE: + case gpu::BUMP_TEXTURE: + case gpu::SPECULAR_TEXTURE: + case gpu::GLOSS_TEXTURE: + case gpu::CUBE_TEXTURE: + case gpu::STRICT_TEXTURE: default: break; } return result; } - -NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type, - const QVariantMap& options = QVariantMap()) { - using Type = NetworkTexture; - - switch (type) { - case Type::ALBEDO_TEXTURE: { - return model::TextureUsage::createAlbedoTextureFromImage; - break; - } - case Type::EMISSIVE_TEXTURE: { - return model::TextureUsage::createEmissiveTextureFromImage; - break; - } - case Type::LIGHTMAP_TEXTURE: { - return model::TextureUsage::createLightmapTextureFromImage; - break; - } - case Type::CUBE_TEXTURE: { - if (options.value("generateIrradiance", true).toBool()) { - return model::TextureUsage::createCubeTextureFromImage; - } else { - return model::TextureUsage::createCubeTextureFromImageWithoutIrradiance; - } - break; - } - case Type::BUMP_TEXTURE: { - return model::TextureUsage::createNormalTextureFromBumpImage; - break; - } - case Type::NORMAL_TEXTURE: { - return model::TextureUsage::createNormalTextureFromNormalImage; - break; - } - case Type::ROUGHNESS_TEXTURE: { - return model::TextureUsage::createRoughnessTextureFromImage; - break; - } - case Type::GLOSS_TEXTURE: { - return model::TextureUsage::createRoughnessTextureFromGlossImage; - break; - } - case Type::SPECULAR_TEXTURE: { - return model::TextureUsage::createMetallicTextureFromImage; - break; - } - case Type::STRICT_TEXTURE: { - return model::TextureUsage::createStrict2DTextureFromImage; - break; - } - case Type::CUSTOM_TEXTURE: { - Q_ASSERT(false); - return NetworkTexture::TextureLoaderFunc(); - break; - } - - case Type::DEFAULT_TEXTURE: - default: { - return model::TextureUsage::create2DTextureFromImage; - break; - } - } -} - /// Returns a texture version of an image file -gpu::TexturePointer TextureCache::getImageTexture(const QString& path, Type type, QVariantMap options) { +gpu::TexturePointer TextureCache::getImageTexture(const QString& path, gpu::TextureType type, QVariantMap options) { QImage image = QImage(path); - auto loader = getTextureLoaderForType(type, options); + auto loader = image::getTextureLoaderForType(type, options); return gpu::TexturePointer(loader(image, QUrl::fromLocalFile(path).fileName().toStdString())); } QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) { const TextureExtra* textureExtra = static_cast(extra); - auto type = textureExtra ? textureExtra->type : Type::DEFAULT_TEXTURE; + auto type = textureExtra ? textureExtra->type : gpu::DEFAULT_TEXTURE; auto content = textureExtra ? textureExtra->content : QByteArray(); auto maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; NetworkTexture* texture = new NetworkTexture(url, type, content, maxNumPixels); return QSharedPointer(texture, &Resource::deleter); } -NetworkTexture::NetworkTexture(const QUrl& url, Type type, const QByteArray& content, int maxNumPixels) : +NetworkTexture::NetworkTexture(const QUrl& url, gpu::TextureType type, const QByteArray& content, int maxNumPixels) : Resource(url), _type(type), _maxNumPixels(maxNumPixels) @@ -353,13 +281,6 @@ NetworkTexture::NetworkTexture(const QUrl& url, Type type, const QByteArray& con } } -NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { - if (_type == CUSTOM_TEXTURE) { - return _textureLoader; - } - return getTextureLoaderForType(_type); -} - void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight) { _originalWidth = originalWidth; @@ -384,34 +305,22 @@ void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth, } gpu::TexturePointer NetworkTexture::getFallbackTexture() const { - if (_type == CUSTOM_TEXTURE) { - return gpu::TexturePointer(); - } return getFallbackTextureForType(_type); } -class Reader : public QRunnable { -public: - Reader(const QWeakPointer& resource, const QUrl& url); - void run() override final; - virtual void read() = 0; - -protected: - QWeakPointer _resource; - QUrl _url; -}; - -class ImageReader : public Reader { +class ImageReader : public QRunnable { public: ImageReader(const QWeakPointer& resource, const QUrl& url, - const QByteArray& data, const std::string& hash, int maxNumPixels); - void read() override final; + const QByteArray& data, int maxNumPixels); + void run() override final; + void read(); private: static void listSupportedImageFormats(); + QWeakPointer _resource; + QUrl _url; QByteArray _content; - std::string _hash; int _maxNumPixels; }; @@ -420,71 +329,16 @@ void NetworkTexture::downloadFinished(const QByteArray& data) { } void NetworkTexture::loadContent(const QByteArray& content) { - // Hash the source image to for KTX caching - std::string hash; - { - QCryptographicHash hasher(QCryptographicHash::Md5); - hasher.addData(content); - hash = hasher.result().toHex().toStdString(); - } - - auto textureCache = static_cast(_cache.data()); - - if (textureCache != nullptr) { - // If we already have a live texture with the same hash, use it - auto texture = textureCache->getTextureByHash(hash); - - // If there is no live texture, check if there's an existing KTX file - if (!texture) { - KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash); - if (ktxFile) { - texture.reset(gpu::Texture::unserialize(ktxFile->getFilepath())); - if (texture) { - texture = textureCache->cacheTextureByHash(hash, texture); - } - } - } - - // If we found the texture either because it's in use or via KTX deserialization, - // set the image and return immediately. - if (texture) { - setImage(texture, texture->getWidth(), texture->getHeight()); - return; - } - } - - // We failed to find an existing live or KTX texture, so trigger an image reader - QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, hash, _maxNumPixels)); + QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, _maxNumPixels)); } -Reader::Reader(const QWeakPointer& resource, const QUrl& url) : - _resource(resource), _url(url) { +ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, int maxNumPixels) : + _resource(resource), + _url(url), + _content(data), + _maxNumPixels(maxNumPixels) +{ DependencyManager::get()->incrementStat("PendingProcessing"); -} - -void Reader::run() { - PROFILE_RANGE_EX(resource_parse_image, __FUNCTION__, 0xffff0000, 0, { { "url", _url.toString() } }); - DependencyManager::get()->decrementStat("PendingProcessing"); - CounterStat counter("Processing"); - - auto originalPriority = QThread::currentThread()->priority(); - if (originalPriority == QThread::InheritPriority) { - originalPriority = QThread::NormalPriority; - } - QThread::currentThread()->setPriority(QThread::LowPriority); - Finally restorePriority([originalPriority]{ QThread::currentThread()->setPriority(originalPriority); }); - - if (!_resource.data()) { - qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref"; - return; - } - - read(); -} - -ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, - const QByteArray& data, const std::string& hash, int maxNumPixels) : - Reader(resource, url), _content(data), _hash(hash), _maxNumPixels(maxNumPixels) { listSupportedImageFormats(); #if DEBUG_DUMP_TEXTURE_LOADS @@ -515,89 +369,104 @@ void ImageReader::listSupportedImageFormats() { }); } -void ImageReader::read() { - // Help the QImage loader by extracting the image file format from the url filename ext. - // Some tga are not created properly without it. - auto filename = _url.fileName().toStdString(); - auto filenameExtension = filename.substr(filename.find_last_of('.') + 1); - QImage image = QImage::fromData(_content, filenameExtension.c_str()); - int imageWidth = image.width(); - int imageHeight = image.height(); +void ImageReader::run() { + PROFILE_RANGE_EX(resource_parse_image, __FUNCTION__, 0xffff0000, 0, { { "url", _url.toString() } }); + DependencyManager::get()->decrementStat("PendingProcessing"); + CounterStat counter("Processing"); - // Validate that the image loaded - if (imageWidth == 0 || imageHeight == 0 || image.format() == QImage::Format_Invalid) { - QString reason(filenameExtension.empty() ? "" : "(no file extension)"); - qCWarning(modelnetworking) << "Failed to load" << _url << reason; + auto originalPriority = QThread::currentThread()->priority(); + if (originalPriority == QThread::InheritPriority) { + originalPriority = QThread::NormalPriority; + } + QThread::currentThread()->setPriority(QThread::LowPriority); + Finally restorePriority([originalPriority] { QThread::currentThread()->setPriority(originalPriority); }); + + read(); +} + +void ImageReader::read() { + auto resource = _resource.lock(); // to ensure the resource is still needed + if (!resource) { + qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref"; return; } + auto networkTexture = resource.staticCast(); - // Validate the image is less than _maxNumPixels, and downscale if necessary - if (imageWidth * imageHeight > _maxNumPixels) { - float scaleFactor = sqrtf(_maxNumPixels / (float)(imageWidth * imageHeight)); - int originalWidth = imageWidth; - int originalHeight = imageHeight; - imageWidth = (int)(scaleFactor * (float)imageWidth + 0.5f); - imageHeight = (int)(scaleFactor * (float)imageHeight + 0.5f); - QImage newImage = image.scaled(QSize(imageWidth, imageHeight), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - image.swap(newImage); - qCDebug(modelnetworking).nospace() << "Downscaled " << _url << " (" << - QSize(originalWidth, originalHeight) << " to " << - QSize(imageWidth, imageHeight) << ")"; + // Hash the source image to for KTX caching + std::string hash; + { + QCryptographicHash hasher(QCryptographicHash::Md5); + hasher.addData(_content); + hash = hasher.result().toHex().toStdString(); } - gpu::TexturePointer texture = nullptr; - { - auto resource = _resource.lock(); // to ensure the resource is still needed - if (!resource) { - qCDebug(modelnetworking) << _url << "loading stopped; resource out of scope"; - return; + // Maybe load from cache + auto textureCache = DependencyManager::get(); + if (textureCache) { + // If we already have a live texture with the same hash, use it + auto texture = textureCache->getTextureByHash(hash); + + // If there is no live texture, check if there's an existing KTX file + if (!texture) { + KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash); + if (ktxFile) { + texture.reset(gpu::Texture::unserialize(ktxFile->getFilepath())); + if (texture) { + texture = textureCache->cacheTextureByHash(hash, texture); + } + } } - auto url = _url.toString().toStdString(); + // If we found the texture either because it's in use or via KTX deserialization, + // set the image and return immediately. + if (texture) { + QMetaObject::invokeMethod(resource.data(), "setImage", + Q_ARG(gpu::TexturePointer, texture), + Q_ARG(int, texture->getWidth()), + Q_ARG(int, texture->getHeight())); + return; + } + } + // Proccess new texture + gpu::TexturePointer texture; + { PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0); - // Load the image into a gpu::Texture - auto networkTexture = resource.staticCast(); - texture.reset(networkTexture->getTextureLoader()(image, url)); - texture->setSource(url); + auto loader = image::getTextureLoaderForType(networkTexture->getTextureType()); + texture.reset(image::processImage(_content, _url, hash, _maxNumPixels, loader)); + texture->setSource(_url.toString().toStdString()); if (texture) { texture->setFallbackTexture(networkTexture->getFallbackTexture()); } + } - auto textureCache = DependencyManager::get(); - // Save the image into a KTXFile + // Save the image into a KTXFile + if (textureCache) { auto memKtx = gpu::Texture::serialize(*texture); - if (!memKtx) { - qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url; - } - if (memKtx && textureCache) { + if (memKtx) { const char* data = reinterpret_cast(memKtx->_storage->data()); size_t length = memKtx->_storage->size(); KTXFilePointer file; auto& ktxCache = textureCache->_ktxCache; - if (!memKtx || !(file = ktxCache.writeFile(data, KTXCache::Metadata(_hash, length)))) { + if (!memKtx || !(file = ktxCache.writeFile(data, KTXCache::Metadata(hash, length)))) { qCWarning(modelnetworking) << _url << "file cache failed"; } else { - resource.staticCast()->_file = file; + networkTexture->_file = file; texture->setKtxBacking(file->getFilepath()); } + } else { + qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url; } // We replace the texture with the one stored in the cache. This deals with the possible race condition of two different // images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will // be the winner - if (textureCache) { - texture = textureCache->cacheTextureByHash(_hash, texture); - } + texture = textureCache->cacheTextureByHash(hash, texture); } - auto resource = _resource.lock(); // to ensure the resource is still needed - if (resource) { - QMetaObject::invokeMethod(resource.data(), "setImage", - Q_ARG(gpu::TexturePointer, texture), - Q_ARG(int, imageWidth), Q_ARG(int, imageHeight)); - } else { - qCDebug(modelnetworking) << _url << "loading stopped; resource out of scope"; - } + QMetaObject::invokeMethod(resource.data(), "setImage", + Q_ARG(gpu::TexturePointer, texture), + Q_ARG(int, texture->getWidth()), + Q_ARG(int, texture->getHeight())); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 6005cc1226..95b77bc330 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -43,29 +43,7 @@ class NetworkTexture : public Resource, public Texture { Q_OBJECT public: - enum Type { - DEFAULT_TEXTURE, - STRICT_TEXTURE, - ALBEDO_TEXTURE, - NORMAL_TEXTURE, - BUMP_TEXTURE, - SPECULAR_TEXTURE, - METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey - ROUGHNESS_TEXTURE, - GLOSS_TEXTURE, - EMISSIVE_TEXTURE, - CUBE_TEXTURE, - OCCLUSION_TEXTURE, - SCATTERING_TEXTURE = OCCLUSION_TEXTURE, - LIGHTMAP_TEXTURE, - CUSTOM_TEXTURE - }; - Q_ENUM(Type) - - typedef gpu::Texture* TextureLoader(const QImage& image, const std::string& srcImageName); - using TextureLoaderFunc = std::function; - - NetworkTexture(const QUrl& url, Type type, const QByteArray& content, int maxNumPixels); + NetworkTexture(const QUrl& url, gpu::TextureType type, const QByteArray& content, int maxNumPixels); QString getType() const override { return "NetworkTexture"; } @@ -73,9 +51,8 @@ public: int getOriginalHeight() const { return _originalHeight; } int getWidth() const { return _width; } int getHeight() const { return _height; } - Type getTextureType() const { return _type; } + gpu::TextureType getTextureType() const { return _type; } - TextureLoaderFunc getTextureLoader() const; gpu::TexturePointer getFallbackTexture() const; signals: @@ -93,8 +70,7 @@ private: friend class KTXReader; friend class ImageReader; - Type _type; - TextureLoaderFunc _textureLoader { [](const QImage&, const std::string&){ return nullptr; } }; + gpu::TextureType _type; KTXFilePointer _file; int _originalWidth { 0 }; int _originalHeight { 0 }; @@ -110,8 +86,6 @@ class TextureCache : public ResourceCache, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY - using Type = NetworkTexture::Type; - public: /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture /// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and @@ -131,10 +105,10 @@ public: const gpu::TexturePointer& getBlackTexture(); /// Returns a texture version of an image file - static gpu::TexturePointer getImageTexture(const QString& path, Type type = Type::DEFAULT_TEXTURE, QVariantMap options = QVariantMap()); + static gpu::TexturePointer getImageTexture(const QString& path, gpu::TextureType type = gpu::DEFAULT_TEXTURE, QVariantMap options = QVariantMap()); /// Loads a texture from the specified URL. - NetworkTexturePointer getTexture(const QUrl& url, Type type = Type::DEFAULT_TEXTURE, + NetworkTexturePointer getTexture(const QUrl& url, gpu::TextureType type = gpu::DEFAULT_TEXTURE, const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt index b26d056bd4..da85b6aa3d 100755 --- a/libraries/model/CMakeLists.txt +++ b/libraries/model/CMakeLists.txt @@ -1,8 +1,4 @@ set(TARGET_NAME model) AUTOSCRIBE_SHADER_LIB(gpu model) setup_hifi_library() -link_hifi_libraries(shared ktx gpu) - -add_dependency_external_projects(nvtt) -target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) +link_hifi_libraries(shared ktx gpu image) \ No newline at end of file diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 568b241c14..b308dd72f8 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -10,83 +10,9 @@ // #include "TextureMap.h" -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ModelLogging.h" using namespace model; using namespace gpu; -// FIXME: Declare this to enable compression -//#define COMPRESS_TEXTURES -static const uvec2 SPARSE_PAGE_SIZE(128); -static const uvec2 MAX_TEXTURE_SIZE(4096); -bool DEV_DECIMATE_TEXTURES = false; - -bool needsSparseRectification(const uvec2& size) { - // Don't attempt to rectify small textures (textures less than the sparse page size in any dimension) - if (glm::any(glm::lessThan(size, SPARSE_PAGE_SIZE))) { - return false; - } - - // Don't rectify textures that are already an exact multiple of sparse page size - if (uvec2(0) == (size % SPARSE_PAGE_SIZE)) { - return false; - } - - // Texture is not sparse compatible, but is bigger than the sparse page size in both dimensions, rectify! - return true; -} - -uvec2 rectifyToSparseSize(const uvec2& size) { - uvec2 pages = ((size / SPARSE_PAGE_SIZE) + glm::clamp(size % SPARSE_PAGE_SIZE, uvec2(0), uvec2(1))); - uvec2 result = pages * SPARSE_PAGE_SIZE; - return result; -} - -std::atomic DECIMATED_TEXTURE_COUNT { 0 }; -std::atomic RECTIFIED_TEXTURE_COUNT { 0 }; - -QImage processSourceImage(const QImage& srcImage, bool cubemap) { - PROFILE_RANGE(resource_parse, "processSourceImage"); - const uvec2 srcImageSize = toGlm(srcImage.size()); - uvec2 targetSize = srcImageSize; - - while (glm::any(glm::greaterThan(targetSize, MAX_TEXTURE_SIZE))) { - targetSize /= 2; - } - if (targetSize != srcImageSize) { - ++DECIMATED_TEXTURE_COUNT; - } - - if (!cubemap && needsSparseRectification(targetSize)) { - ++RECTIFIED_TEXTURE_COUNT; - targetSize = rectifyToSparseSize(targetSize); - } - - if (DEV_DECIMATE_TEXTURES && glm::all(glm::greaterThanEqual(targetSize / SPARSE_PAGE_SIZE, uvec2(2)))) { - targetSize /= 2; - } - - if (targetSize != srcImageSize) { - PROFILE_RANGE(resource_parse, "processSourceImage Rectify"); - qCDebug(modelLog) << "Resizing texture from " << srcImageSize.x << "x" << srcImageSize.y << " to " << targetSize.x << "x" << targetSize.y; - return srcImage.scaled(fromGlm(targetSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - } - - return srcImage; -} - void TextureMap::setTextureSource(TextureSourcePointer& textureSource) { _textureSource = textureSource; } @@ -115,894 +41,3 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) { _lightmapOffsetScale.x = offset; _lightmapOffsetScale.y = scale; } - -const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask) { - PROFILE_RANGE(resource_parse, "process2DImageColor"); - QImage image = processSourceImage(srcImage, false); - validAlpha = false; - alphaAsMask = true; - const uint8 OPAQUE_ALPHA = 255; - const uint8 TRANSPARENT_ALPHA = 0; - if (image.hasAlphaChannel()) { - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - // Figure out if we can use a mask for alpha or not - int numOpaques = 0; - int numTranslucents = 0; - const int NUM_PIXELS = image.width() * image.height(); - const int MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(NUM_PIXELS)); - const QRgb* data = reinterpret_cast(image.constBits()); - for (int i = 0; i < NUM_PIXELS; ++i) { - auto alpha = qAlpha(data[i]); - if (alpha == OPAQUE_ALPHA) { - numOpaques++; - } else if (alpha != TRANSPARENT_ALPHA) { - if (++numTranslucents > MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK) { - alphaAsMask = false; - break; - } - } - } - validAlpha = (numOpaques != NUM_PIXELS); - } - - // Force all the color images to be rgba32bits - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - return image; -} - -void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, -const QImage& image, bool isLinear, bool doCompress) { - -#ifdef COMPRESS_TEXTURES -#else - doCompress = false; -#endif - - if (image.hasAlphaChannel()) { - gpu::Semantic gpuSemantic; - gpu::Semantic mipSemantic; - if (isLinear) { - mipSemantic = gpu::BGRA; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_RGBA; - } else { - gpuSemantic = gpu::RGBA; - } - } else { - mipSemantic = gpu::SBGRA; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_SRGBA; - } else { - gpuSemantic = gpu::SRGBA; - } - } - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpuSemantic); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, mipSemantic); - } else { - gpu::Semantic gpuSemantic; - gpu::Semantic mipSemantic; - if (isLinear) { - mipSemantic = gpu::RGB; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_RGB; - } else { - gpuSemantic = gpu::RGB; - } - } else { - mipSemantic = gpu::SRGB; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_SRGB; - } else { - gpuSemantic = gpu::SRGB; - } - } - formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); - formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); - } -} - -#define CPU_MIPMAPS 1 -#define DEBUG_NVTT 0 - -void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { -#if CPU_MIPMAPS - PROFILE_RANGE(resource_parse, "generateMips"); -#if DEBUG_NVTT - QDebug debug = qDebug(); - - debug << Q_FUNC_INFO << "\n"; - debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; -#endif // DEBUG_NVTT - - auto numMips = texture->getNumMips(); - for (uint16 level = 1; level < numMips; ++level) { - QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); - if (fastResize) { - image = image.scaled(mipSize); - -#if DEBUG_NVTT - debug << "Begin fast { " << image.byteCount() << image.width() << image.height() << image.depth() << level << " } Ends\n"; -#endif // DEBUG_NVTT - - texture->assignStoredMip(level, image.byteCount(), image.constBits()); - } else { - QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - -#if DEBUG_NVTT - debug << "Begin { " << mipImage.byteCount() << mipImage.width() << mipImage.height() << mipImage.depth() << level << " } Ends\n"; -#endif // DEBUG_NVTT - - texture->assignStoredMip(level, mipImage.byteCount(), mipImage.constBits()); - } - } -#else - texture->autoGenerateMips(-1); -#endif -} - -void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { -#if CPU_MIPMAPS - PROFILE_RANGE(resource_parse, "generateFaceMips"); - auto numMips = texture->getNumMips(); - for (uint16 level = 1; level < numMips; ++level) { - QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); - QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - texture->assignStoredMipFace(level, face, mipImage.byteCount(), mipImage.constBits()); - } -#else - texture->autoGenerateMips(-1); -#endif -} - -struct MyOutputHandler : public nvtt::OutputHandler { - MyOutputHandler(gpu::Texture* texture, QDebug* debug) : -#if DEBUG_NVTT - _debug(debug), -#endif // DEBUG_NVTT - _texture(texture) { - - } - - virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { -#if DEBUG_NVTT - auto list = QStringList() << QString::number(size) - << QString::number(width) - << QString::number(height) - << QString::number(depth) - << QString::number(face) - << QString::number(miplevel); - _count = 0; - _str = "Begin { " + list.join(", "); -#endif // DEBUG_NVTT - - _size = size; - _miplevel = miplevel; - - _data = static_cast(malloc(size)); - _current = _data; - } - virtual bool writeData(const void* data, int size) { -#if DEBUG_NVTT - ++_count; -#endif // DEBUG_NVTT - - assert(_current + size <= _data + _size); - memcpy(_current, data, size); - _current += size; - return true; - } - virtual void endImage() { -#if DEBUG_NVTT - _str += " } End " + QString::number(_count) + "\n"; - *_debug << qPrintable(_str); -#endif // DEBUG_NVTT - - _texture->assignStoredMip(_miplevel, _size, static_cast(_data)); - free(_data); - _data = nullptr; - } - -#if DEBUG_NVTT - int _count = 0; - QString _str; - QDebug* _debug{ nullptr }; -#endif // DEBUG_NVTT - gpu::Byte* _data{ nullptr }; - gpu::Byte* _current{ nullptr }; - gpu::Texture* _texture{ nullptr }; - int _miplevel = 0; - int _size = 0; -}; -struct MyErrorHandler : public nvtt::ErrorHandler { - virtual void error(nvtt::Error e) override { - qDebug() << "Texture compression error:" << nvtt::errorString(e); - } -}; - -void generateNVTTMips(gpu::Texture* texture, QImage& image, nvtt::InputFormat inputFormat, nvtt::Format compressionFormat) { -#if CPU_MIPMAPS - PROFILE_RANGE(resource_parse, "generateMips"); - - /*/ - generateMips(texture, image, false); - return; - /**/ - -#if DEBUG_NVTT - QDebug debug = qDebug(); - QDebug* debugPtr = &debug; - - debug << Q_FUNC_INFO << "\n"; - debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; -#else - QDebug* debugPtr = nullptr; -#endif // DEBUG_NVTT - - const int w = image.width(), h = image.height(); - const void* data = static_cast(image.constBits()); - - nvtt::InputOptions inputOptions; - inputOptions.setTextureLayout(nvtt::TextureType_2D, w, h); - inputOptions.setMipmapData(data, w, h); - - inputOptions.setFormat(inputFormat); - // inputOptions.setAlphaMode(AlphaMode alphaMode); - // inputOptions.setGamma(float inputGamma, float outputGamma); - // inputOptions.setWrapMode(WrapMode mode); - // inputOptions.setMaxExtents(int d); - // inputOptions.setRoundMode(RoundMode mode); - - inputOptions.setMipmapGeneration(true); - inputOptions.setMipmapFilter(nvtt::MipmapFilter_Box); - - nvtt::OutputOptions outputOptions; - outputOptions.setOutputHeader(false); - MyOutputHandler outputHandler(texture, debugPtr); - outputOptions.setOutputHandler(&outputHandler); - MyErrorHandler errorHandler; - outputOptions.setErrorHandler(&errorHandler); - - nvtt::CompressionOptions compressionOptions; - compressionOptions.setFormat(compressionFormat); - compressionOptions.setQuality(nvtt::Quality_Fastest); - - nvtt::Compressor compressor; - compressor.process(inputOptions, compressionOptions, outputOptions); -#else - texture->autoGenerateMips(-1); -#endif -} - -gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool isStrict) { - PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); - bool validAlpha = false; - bool alphaAsMask = true; - QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); - - gpu::Texture* theTexture = nullptr; - - if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatGPU; - gpu::Element formatMip; - defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); - - if (isStrict) { - theTexture = (gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - } else { - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - } - theTexture->setSource(srcImageName); - auto usage = gpu::Texture::Usage::Builder().withColor(); - if (validAlpha) { - usage.withAlpha(); - if (alphaAsMask) { - usage.withAlphaMask(); - } - } - theTexture->setUsage(usage.build()); - theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - - if (generateMips) { - ::generateNVTTMips(theTexture, image, nvtt::InputFormat_BGRA_8UB, nvtt::Format_RGBA); - } - theTexture->setSource(srcImageName); - } - - return theTexture; -} - -gpu::Texture* TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true, true); -} - -gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true); -} - -gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); -} - -gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); -} - -gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); -} - - -gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createNormalTextureFromNormalImage"); - QImage image = processSourceImage(srcImage, false); - - // Make sure the normal map source image is ARGB32 - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - - gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - - gpu::Element formatMip = gpu::Element::COLOR_BGRA_32; - gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; - - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); - - theTexture->setSource(srcImageName); - } - - return theTexture; -} - -int clampPixelCoordinate(int coordinate, int maxCoordinate) { - return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate)); -} - -const int RGBA_MAX = 255; - -// transform -1 - 1 to 0 - 255 (from sobel value to rgb) -double mapComponent(double sobelValue) { - const double factor = RGBA_MAX / 2.0; - return (sobelValue + 1.0) * factor; -} - -gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createNormalTextureFromBumpImage"); - QImage image = processSourceImage(srcImage, false); - - if (image.format() != QImage::Format_Grayscale8) { - image = image.convertToFormat(QImage::Format_Grayscale8); - } - - // PR 5540 by AlessandroSigna integrated here as a specialized TextureLoader for bumpmaps - // The conversion is done using the Sobel Filter to calculate the derivatives from the grayscale image - const double pStrength = 2.0; - int width = image.width(); - int height = image.height(); - - QImage result(width, height, QImage::Format_ARGB32); - - for (int i = 0; i < width; i++) { - const int iNextClamped = clampPixelCoordinate(i + 1, width - 1); - const int iPrevClamped = clampPixelCoordinate(i - 1, width - 1); - - for (int j = 0; j < height; j++) { - const int jNextClamped = clampPixelCoordinate(j + 1, height - 1); - const int jPrevClamped = clampPixelCoordinate(j - 1, height - 1); - - // surrounding pixels - const QRgb topLeft = image.pixel(iPrevClamped, jPrevClamped); - const QRgb top = image.pixel(iPrevClamped, j); - const QRgb topRight = image.pixel(iPrevClamped, jNextClamped); - const QRgb right = image.pixel(i, jNextClamped); - const QRgb bottomRight = image.pixel(iNextClamped, jNextClamped); - const QRgb bottom = image.pixel(iNextClamped, j); - const QRgb bottomLeft = image.pixel(iNextClamped, jPrevClamped); - const QRgb left = image.pixel(i, jPrevClamped); - - // take their gray intensities - // since it's a grayscale image, the value of each component RGB is the same - const double tl = qRed(topLeft); - const double t = qRed(top); - const double tr = qRed(topRight); - const double r = qRed(right); - const double br = qRed(bottomRight); - const double b = qRed(bottom); - const double bl = qRed(bottomLeft); - const double l = qRed(left); - - // apply the sobel filter - const double dX = (tr + pStrength * r + br) - (tl + pStrength * l + bl); - const double dY = (bl + pStrength * b + br) - (tl + pStrength * t + tr); - const double dZ = RGBA_MAX / pStrength; - - glm::vec3 v(dX, dY, dZ); - glm::normalize(v); - - // convert to rgb from the value obtained computing the filter - QRgb qRgbValue = qRgba(mapComponent(v.z), mapComponent(v.y), mapComponent(v.x), 1.0); - result.setPixel(i, j, qRgbValue); - } - } - - gpu::Texture* theTexture = nullptr; - if ((result.width() > 0) && (result.height() > 0)) { - - gpu::Element formatMip = gpu::Element::COLOR_BGRA_32; - gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; - - - theTexture = (gpu::Texture::create2D(formatGPU, result.width(), result.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, result.byteCount(), result.constBits()); - generateMips(theTexture, result, true); - - theTexture->setSource(srcImageName); - } - - return theTexture; -} - -gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createRoughnessTextureFromImage"); - QImage image = processSourceImage(srcImage, false); - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } - } - - image = image.convertToFormat(QImage::Format_Grayscale8); - - gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESS_TEXTURES - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); -#else - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - gpu::Element formatMip = gpu::Element::COLOR_R_8; - - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); - - theTexture->setSource(srcImageName); - } - - return theTexture; -} - -gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createRoughnessTextureFromGlossImage"); - QImage image = processSourceImage(srcImage, false); - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } - } - - // Gloss turned into Rough - image.invertPixels(QImage::InvertRgba); - - image = image.convertToFormat(QImage::Format_Grayscale8); - - gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - -#ifdef COMPRESS_TEXTURES - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); -#else - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - gpu::Element formatMip = gpu::Element::COLOR_R_8; - - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); - - theTexture->setSource(srcImageName); - } - - return theTexture; -} - -gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createMetallicTextureFromImage"); - QImage image = processSourceImage(srcImage, false); - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } - } - - image = image.convertToFormat(QImage::Format_Grayscale8); - - gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - -#ifdef COMPRESS_TEXTURES - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); -#else - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - gpu::Element formatMip = gpu::Element::COLOR_R_8; - - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); - - theTexture->setSource(srcImageName); - } - - return theTexture; -} - -class CubeLayout { -public: - - enum SourceProjection { - FLAT = 0, - EQUIRECTANGULAR, - }; - int _type = FLAT; - int _widthRatio = 1; - int _heightRatio = 1; - - class Face { - public: - int _x = 0; - int _y = 0; - bool _horizontalMirror = false; - bool _verticalMirror = false; - - Face() {} - Face(int x, int y, bool horizontalMirror, bool verticalMirror) : _x(x), _y(y), _horizontalMirror(horizontalMirror), _verticalMirror(verticalMirror) {} - }; - - Face _faceXPos; - Face _faceXNeg; - Face _faceYPos; - Face _faceYNeg; - Face _faceZPos; - Face _faceZNeg; - - CubeLayout(int wr, int hr, Face fXP, Face fXN, Face fYP, Face fYN, Face fZP, Face fZN) : - _type(FLAT), - _widthRatio(wr), - _heightRatio(hr), - _faceXPos(fXP), - _faceXNeg(fXN), - _faceYPos(fYP), - _faceYNeg(fYN), - _faceZPos(fZP), - _faceZNeg(fZN) {} - - CubeLayout(int wr, int hr) : - _type(EQUIRECTANGULAR), - _widthRatio(wr), - _heightRatio(hr) {} - - - static const CubeLayout CUBEMAP_LAYOUTS[]; - static const int NUM_CUBEMAP_LAYOUTS; - - static int findLayout(int width, int height) { - // Find the layout of the cubemap in the 2D image - int foundLayout = -1; - for (int i = 0; i < NUM_CUBEMAP_LAYOUTS; i++) { - if ((height * CUBEMAP_LAYOUTS[i]._widthRatio) == (width * CUBEMAP_LAYOUTS[i]._heightRatio)) { - foundLayout = i; - break; - } - } - return foundLayout; - } - - static QImage extractEquirectangularFace(const QImage& source, gpu::Texture::CubeFace face, int faceWidth) { - QImage image(faceWidth, faceWidth, source.format()); - - glm::vec2 dstInvSize(1.0f / (float)image.width(), 1.0f / (float)image.height()); - - struct CubeToXYZ { - gpu::Texture::CubeFace _face; - CubeToXYZ(gpu::Texture::CubeFace face) : _face(face) {} - - glm::vec3 xyzFrom(const glm::vec2& uv) { - auto faceDir = glm::normalize(glm::vec3(-1.0f + 2.0f * uv.x, -1.0f + 2.0f * uv.y, 1.0f)); - - switch (_face) { - case gpu::Texture::CubeFace::CUBE_FACE_BACK_POS_Z: - return glm::vec3(-faceDir.x, faceDir.y, faceDir.z); - case gpu::Texture::CubeFace::CUBE_FACE_FRONT_NEG_Z: - return glm::vec3(faceDir.x, faceDir.y, -faceDir.z); - case gpu::Texture::CubeFace::CUBE_FACE_LEFT_NEG_X: - return glm::vec3(faceDir.z, faceDir.y, faceDir.x); - case gpu::Texture::CubeFace::CUBE_FACE_RIGHT_POS_X: - return glm::vec3(-faceDir.z, faceDir.y, -faceDir.x); - case gpu::Texture::CubeFace::CUBE_FACE_BOTTOM_NEG_Y: - return glm::vec3(-faceDir.x, -faceDir.z, faceDir.y); - case gpu::Texture::CubeFace::CUBE_FACE_TOP_POS_Y: - default: - return glm::vec3(-faceDir.x, faceDir.z, -faceDir.y); - } - } - }; - CubeToXYZ cubeToXYZ(face); - - struct RectToXYZ { - RectToXYZ() {} - - glm::vec2 uvFrom(const glm::vec3& xyz) { - auto flatDir = glm::normalize(glm::vec2(xyz.x, xyz.z)); - auto uvRad = glm::vec2(atan2(flatDir.x, flatDir.y), asin(xyz.y)); - - const float LON_TO_RECT_U = 1.0f / (glm::pi()); - const float LAT_TO_RECT_V = 2.0f / glm::pi(); - return glm::vec2(0.5f * uvRad.x * LON_TO_RECT_U + 0.5f, 0.5f * uvRad.y * LAT_TO_RECT_V + 0.5f); - } - }; - RectToXYZ rectToXYZ; - - int srcFaceHeight = source.height(); - int srcFaceWidth = source.width(); - - glm::vec2 dstCoord; - glm::ivec2 srcPixel; - for (int y = 0; y < faceWidth; ++y) { - dstCoord.y = 1.0f - (y + 0.5f) * dstInvSize.y; // Fill cube face images from top to bottom - for (int x = 0; x < faceWidth; ++x) { - dstCoord.x = (x + 0.5f) * dstInvSize.x; - - auto xyzDir = cubeToXYZ.xyzFrom(dstCoord); - auto srcCoord = rectToXYZ.uvFrom(xyzDir); - - srcPixel.x = floor(srcCoord.x * srcFaceWidth); - // Flip the vertical axis to QImage going top to bottom - srcPixel.y = floor((1.0f - srcCoord.y) * srcFaceHeight); - - if (((uint32) srcPixel.x < (uint32) source.width()) && ((uint32) srcPixel.y < (uint32) source.height())) { - image.setPixel(x, y, source.pixel(QPoint(srcPixel.x, srcPixel.y))); - - // Keep for debug, this is showing the dir as a color - // glm::u8vec4 rgba((xyzDir.x + 1.0)*0.5 * 256, (xyzDir.y + 1.0)*0.5 * 256, (xyzDir.z + 1.0)*0.5 * 256, 256); - // unsigned int val = 0xff000000 | (rgba.r) | (rgba.g << 8) | (rgba.b << 16); - // image.setPixel(x, y, val); - } - } - } - return image; - } -}; - -const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { - - // Here is the expected layout for the faces in an image with the 2/1 aspect ratio: - // THis is detected as an Equirectangular projection - // WIDTH - // <---------------------------> - // ^ +------+------+------+------+ - // H | | | | | - // E | | | | | - // I | | | | | - // G +------+------+------+------+ - // H | | | | | - // T | | | | | - // | | | | | | - // v +------+------+------+------+ - // - // FaceWidth = width = height / 6 - { 2, 1 }, - - // Here is the expected layout for the faces in an image with the 1/6 aspect ratio: - // - // WIDTH - // <------> - // ^ +------+ - // | | | - // | | +X | - // | | | - // H +------+ - // E | | - // I | -X | - // G | | - // H +------+ - // T | | - // | | +Y | - // | | | - // | +------+ - // | | | - // | | -Y | - // | | | - // H +------+ - // E | | - // I | +Z | - // G | | - // H +------+ - // T | | - // | | -Z | - // | | | - // V +------+ - // - // FaceWidth = width = height / 6 - { 1, 6, - { 0, 0, true, false }, - { 0, 1, true, false }, - { 0, 2, false, true }, - { 0, 3, false, true }, - { 0, 4, true, false }, - { 0, 5, true, false } - }, - - // Here is the expected layout for the faces in an image with the 3/4 aspect ratio: - // - // <-----------WIDTH-----------> - // ^ +------+------+------+------+ - // | | | | | | - // | | | +Y | | | - // | | | | | | - // H +------+------+------+------+ - // E | | | | | - // I | -X | -Z | +X | +Z | - // G | | | | | - // H +------+------+------+------+ - // T | | | | | - // | | | -Y | | | - // | | | | | | - // V +------+------+------+------+ - // - // FaceWidth = width / 4 = height / 3 - { 4, 3, - { 2, 1, true, false }, - { 0, 1, true, false }, - { 1, 0, false, true }, - { 1, 2, false, true }, - { 3, 1, true, false }, - { 1, 1, true, false } - }, - - // Here is the expected layout for the faces in an image with the 4/3 aspect ratio: - // - // <-------WIDTH--------> - // ^ +------+------+------+ - // | | | | | - // | | | +Y | | - // | | | | | - // H +------+------+------+ - // E | | | | - // I | -X | -Z | +X | - // G | | | | - // H +------+------+------+ - // T | | | | - // | | | -Y | | - // | | | | | - // | +------+------+------+ - // | | | | | - // | | | +Z! | | <+Z is upside down! - // | | | | | - // V +------+------+------+ - // - // FaceWidth = width / 3 = height / 4 - { 3, 4, - { 2, 1, true, false }, - { 0, 1, true, false }, - { 1, 0, false, true }, - { 1, 2, false, true }, - { 1, 3, false, true }, - { 1, 1, true, false } - } -}; -const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); - -gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance) { - PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage"); - - gpu::Texture* theTexture = nullptr; - if ((srcImage.width() > 0) && (srcImage.height() > 0)) { - QImage image = processSourceImage(srcImage, true); - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - gpu::Element formatGPU; - gpu::Element formatMip; - defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); - - // Find the layout of the cubemap in the 2D image - // Use the original image size since processSourceImage may have altered the size / aspect ratio - int foundLayout = CubeLayout::findLayout(srcImage.width(), srcImage.height()); - - std::vector faces; - // If found, go extract the faces as separate images - if (foundLayout >= 0) { - auto& layout = CubeLayout::CUBEMAP_LAYOUTS[foundLayout]; - if (layout._type == CubeLayout::FLAT) { - int faceWidth = image.width() / layout._widthRatio; - - faces.push_back(image.copy(QRect(layout._faceXPos._x * faceWidth, layout._faceXPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXPos._horizontalMirror, layout._faceXPos._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceXNeg._x * faceWidth, layout._faceXNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXNeg._horizontalMirror, layout._faceXNeg._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceYPos._x * faceWidth, layout._faceYPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYPos._horizontalMirror, layout._faceYPos._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceYNeg._x * faceWidth, layout._faceYNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYNeg._horizontalMirror, layout._faceYNeg._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceZPos._x * faceWidth, layout._faceZPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZPos._horizontalMirror, layout._faceZPos._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceZNeg._x * faceWidth, layout._faceZNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZNeg._horizontalMirror, layout._faceZNeg._verticalMirror)); - } else if (layout._type == CubeLayout::EQUIRECTANGULAR) { - // THe face width is estimated from the input image - const int EQUIRECT_FACE_RATIO_TO_WIDTH = 4; - const int EQUIRECT_MAX_FACE_WIDTH = 2048; - int faceWidth = std::min(image.width() / EQUIRECT_FACE_RATIO_TO_WIDTH, EQUIRECT_MAX_FACE_WIDTH); - for (int face = gpu::Texture::CUBE_FACE_RIGHT_POS_X; face < gpu::Texture::NUM_CUBE_FACES; face++) { - QImage faceImage = CubeLayout::extractEquirectangularFace(image, (gpu::Texture::CubeFace) face, faceWidth); - faces.push_back(faceImage); - } - } - } else { - qCDebug(modelLog) << "Failed to find a known cube map layout from this image:" << QString(srcImageName.c_str()); - return nullptr; - } - - // If the 6 faces have been created go on and define the true Texture - if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) { - theTexture = gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - int f = 0; - for (auto& face : faces) { - theTexture->assignStoredMipFace(0, f, face.byteCount(), face.constBits()); - if (generateMips) { - generateFaceMips(theTexture, face, f); - } - f++; - } - - // Generate irradiance while we are at it - if (generateIrradiance) { - PROFILE_RANGE(resource_parse, "generateIrradiance"); - theTexture->generateIrradiance(); - } - - theTexture->setSource(srcImageName); - } - } - - return theTexture; -} - -gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, true); -} - -gpu::Texture* TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, false); -} diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index a4bb861502..1785d44730 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -13,48 +13,10 @@ #include "gpu/Texture.h" -#include "Material.h" #include "Transform.h" -#include - -class QImage; - namespace model { -typedef glm::vec3 Color; - -class TextureUsage { -public: - gpu::Texture::Type _type{ gpu::Texture::TEX_2D }; - Material::MapFlags _materialUsage{ MaterialKey::ALBEDO_MAP }; - - int _environmentUsage = 0; - - static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createStrict2DTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createAlbedoTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createEmissiveTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createRoughnessTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createRoughnessTextureFromGlossImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createMetallicTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createCubeTextureFromImageWithoutIrradiance(const QImage& image, const std::string& srcImageName); - static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); - - - static const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); - static void defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, - const QImage& srcImage, bool isLinear, bool doCompress); - static gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool isStrict = false); - static gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance); - -}; - - - class TextureMap { public: TextureMap() {} diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 08d4f0fc68..66c436d1d6 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -199,7 +199,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren { // Grab a texture map representing the different status icons and assign that to the drawStatsuJob auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; - auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath, NetworkTexture::STRICT_TEXTURE); + auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath, gpu::TextureType::STRICT_TEXTURE); task.addJob("DrawStatus", opaques, DrawStatus(statusIconMap)); } } diff --git a/tests/gpu-test/CMakeLists.txt b/tests/gpu-test/CMakeLists.txt index 7da4a1a925..1712a5a3e1 100644 --- a/tests/gpu-test/CMakeLists.txt +++ b/tests/gpu-test/CMakeLists.txt @@ -3,7 +3,7 @@ AUTOSCRIBE_SHADER_LIB(gpu model render-utils) # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Quick Gui OpenGL Script Widgets) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") -link_hifi_libraries(networking gl gpu gpu-gl procedural shared fbx model model-networking animation script-engine render render-utils octree ) +link_hifi_libraries(networking gl gpu gpu-gl procedural shared fbx model model-networking animation script-engine render render-utils octree image) package_libraries_for_deployment() target_nsight() diff --git a/tests/ktx/CMakeLists.txt b/tests/ktx/CMakeLists.txt index d72379efd6..7133c30898 100644 --- a/tests/ktx/CMakeLists.txt +++ b/tests/ktx/CMakeLists.txt @@ -10,6 +10,6 @@ setup_hifi_project(Quick Gui OpenGL) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries -link_hifi_libraries(shared octree ktx gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics) +link_hifi_libraries(shared octree ktx gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics image) package_libraries_for_deployment() diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index 3a6fcabf43..bd560a20f9 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -43,6 +43,7 @@ #include #include #include +#include QSharedPointer logger; @@ -94,7 +95,7 @@ int main(int argc, char** argv) { QLoggingCategory::setFilterRules(LOG_FILTER_RULES); QImage image(TEST_IMAGE); - gpu::Texture* testTexture = model::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, false, true); + gpu::Texture* testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, false, true); auto ktxMemory = gpu::Texture::serialize(*testTexture); { From 5ceb30b69cbbace772d14c833d8cef5df534d725 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Apr 2017 14:28:16 -0700 Subject: [PATCH 04/32] Make sure mips are copied to memory --- libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp | 12 ++++++++ libraries/gpu-gl/src/gpu/gl/GLTexture.cpp | 9 ++++-- libraries/gpu-gl/src/gpu/gl/GLTexture.h | 2 +- libraries/gpu-gl/src/gpu/gl41/GL41Backend.h | 2 +- .../src/gpu/gl41/GL41BackendTexture.cpp | 10 +++++-- libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 2 +- .../src/gpu/gl45/GL45BackendTexture.cpp | 13 +++++++-- libraries/gpu/src/gpu/Format.cpp | 2 ++ libraries/gpu/src/gpu/Format.h | 1 + libraries/gpu/src/gpu/Texture.cpp | 4 +-- libraries/gpu/src/gpu/Texture_ktx.cpp | 10 +++++++ libraries/image/src/image/Image.cpp | 29 +++++++++++++------ libraries/ktx/src/ktx/KTX.h | 10 ------- 13 files changed, 75 insertions(+), 31 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index 6e918b2de1..a865a11135 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -645,6 +645,18 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::COMPRESSED_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; break; + case gpu::COMPRESSED_BC3_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + case gpu::COMPRESSED_BC3_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + break; + case gpu::COMPRESSED_BC7_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; + break; + case gpu::COMPRESSED_BC7_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp index 19891d3370..30d2bc8377 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp @@ -120,11 +120,12 @@ void GLTexture::copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip, u } auto size = _gpuObject.evalMipDimensions(sourceMip); auto mipData = _gpuObject.accessStoredMipFace(sourceMip, face); + auto mipSize = _gpuObject.getStoredMipFaceSize(sourceMip, face); if (mipData) { GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), _gpuObject.getStoredMipFormat()); - copyMipFaceLinesFromTexture(targetMip, face, size, 0, texelFormat.format, texelFormat.type, mipData->readData()); + copyMipFaceLinesFromTexture(targetMip, face, size, 0, texelFormat.format, texelFormat.internalFormat, texelFormat.type, mipSize, mipData->readData()); } else { - qCDebug(gpugllogging) << "Missing mipData level=" << sourceMip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Missing mipData level=" << sourceMip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); } } @@ -203,9 +204,11 @@ TransferJob::TransferJob(const GLTexture& parent, uint16_t sourceMip, uint16_t t auto transferDimensions = _parent._gpuObject.evalMipDimensions(sourceMip); GLenum format; + GLenum internalFormat; GLenum type; GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_parent._gpuObject.getTexelFormat(), _parent._gpuObject.getStoredMipFormat()); format = texelFormat.format; + internalFormat = texelFormat.internalFormat; type = texelFormat.type; auto mipSize = _parent._gpuObject.getStoredMipFaceSize(sourceMip, face); @@ -236,7 +239,7 @@ TransferJob::TransferJob(const GLTexture& parent, uint16_t sourceMip, uint16_t t Backend::updateTextureTransferPendingSize(0, _transferSize); _transferLambda = [=] { - _parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, format, type, _buffer.data()); + _parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, format, internalFormat, type, _buffer.size(), _buffer.data()); std::vector emptyVector; _buffer.swap(emptyVector); }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.h b/libraries/gpu-gl/src/gpu/gl/GLTexture.h index 960575827f..f12ac12df3 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.h @@ -163,7 +163,7 @@ public: protected: virtual Size size() const = 0; virtual void generateMips() const = 0; - virtual void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const = 0; + virtual void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const = 0; virtual void copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip, uint8_t face) const final; GLTexture(const std::weak_ptr& backend, const Texture& texture, GLuint id); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 545279627a..3f530e28b8 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -50,7 +50,7 @@ public: protected: GL41Texture(const std::weak_ptr& backend, const Texture& texture); void generateMips() const override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; virtual void syncSampler() const; void withPreservedTexture(std::function f) const; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index e2e1b164cf..2501f8b06b 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -92,9 +92,15 @@ void GL41Texture::generateMips() const { (void)CHECK_GL_ERROR(); } -void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const { +void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { - glTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + if (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT == internalFormat) { + qCDebug(gpugllogging) << "Compressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Compressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer; + glCompressedTexImage2D(_target, mip, internalFormat, size.x, size.y, 0, sourceSize, sourcePointer); + } else { + glTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + } } else if (GL_TEXTURE_CUBE_MAP == _target) { auto target = GLTexture::CUBE_FACE_LAYOUT[face]; glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index d80a70cfd1..c1bbfdd162 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -48,7 +48,7 @@ public: protected: GL45Texture(const std::weak_ptr& backend, const Texture& texture); void generateMips() const override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; virtual void syncSampler() const; }; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 73974addff..c530af535a 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -117,9 +117,18 @@ void GL45Texture::generateMips() const { (void)CHECK_GL_ERROR(); } -void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const { +void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { - glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + if (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT == internalFormat) { + qCDebug(gpugllogging) << "Compressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Compressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer << "4.5"; + glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + } + else { + qCDebug(gpugllogging) << "Uncompressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); + qCDebug(gpugllogging) << "Uncompressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer << "4.5"; + glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + } } else if (GL_TEXTURE_CUBE_MAP == _target) { // DSA ARB does not work on AMD, so use EXT // unless EXT is not available on the driver diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index de202911e3..cdf5c8345c 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -19,6 +19,8 @@ const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::COLOR_BGRA_32{ VEC4, NUINT8, BGRA }; const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; +const Element Element::COLOR_COMPRESSED_SRGBA{ VEC4, NUINT8, COMPRESSED_BC3_SRGBA }; + const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 }; const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; const Element Element::VEC2F_UV{ VEC2, FLOAT, UV }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 97fe76eebc..2b42683d56 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -236,6 +236,7 @@ public: static const Element COLOR_BGRA_32; static const Element COLOR_SBGRA_32; static const Element COLOR_R11G11B10; + static const Element COLOR_COMPRESSED_SRGBA; static const Element VEC4F_COLOR_RGBA; static const Element VEC2F_UV; static const Element VEC2F_XY; diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 1e65972114..6c92886864 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -434,7 +434,7 @@ void Texture::assignStoredMip(uint16 level, storage::StoragePointer& storage) { // THen check that the mem texture passed make sense with its format Size expectedSize = evalStoredMipSize(level, getStoredMipFormat()); auto size = storage->size(); - if (storage->size() == expectedSize) { + if (storage->size() <= expectedSize) { _storage->assignMipData(level, storage); _stamp++; } else if (size > expectedSize) { @@ -461,7 +461,7 @@ void Texture::assignStoredMipFace(uint16 level, uint8 face, storage::StoragePoin // THen check that the mem texture passed make sense with its format Size expectedSize = evalStoredMipFaceSize(level, getStoredMipFormat()); auto size = storage->size(); - if (size == expectedSize) { + if (size <= expectedSize) { _storage->assignMipFaceData(level, face, storage); _stamp++; } else if (size > expectedSize) { diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 28de0c70eb..d61788c7db 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -260,6 +260,9 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RGBA, ktx::GLInternalFormat_Uncompressed::SRGB8_ALPHA8, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_R_8 && mipFormat == Format::COLOR_R_8) { header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat_Uncompressed::R8, ktx::GLBaseInternalFormat::RED); + } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA && mipFormat == Format::COLOR_COMPRESSED_SRGBA) { + return false; + header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA); } else { return false; } @@ -295,6 +298,13 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E } else { return false; } + } else if (header.getGLFormat() == ktx::GLFormat::COMPRESSED_FORMAT && header.getGLType() == ktx::GLType::COMPRESSED_TYPE) { + if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { + mipFormat = Format::COLOR_COMPRESSED_SRGBA; + texelFormat = Format::COLOR_COMPRESSED_SRGBA; + } else { + return false; + } } else { return false; } diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index f1a8e4e13b..3a71d80e12 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -27,6 +27,9 @@ using namespace gpu; // FIXME: Declare this to enable compression //#define COMPRESS_TEXTURES +#define CPU_MIPMAPS 1 +#define DEBUG_NVTT 1 + static const glm::uvec2 SPARSE_PAGE_SIZE(128); static const glm::uvec2 MAX_TEXTURE_SIZE(4096); bool DEV_DECIMATE_TEXTURES = false; @@ -219,6 +222,10 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, const QImage& image, bool isLinear, bool doCompress) { +#ifdef COMPRESS_TEXTURES +#else + doCompress = false; +#endif if (image.hasAlphaChannel()) { gpu::Semantic gpuSemantic; @@ -226,14 +233,14 @@ void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element if (isLinear) { mipSemantic = gpu::BGRA; if (doCompress) { - gpuSemantic = gpu::COMPRESSED_BC3_RGBA; + gpuSemantic = gpu::COMPRESSED_RGBA; } else { gpuSemantic = gpu::RGBA; } } else { mipSemantic = gpu::SBGRA; if (doCompress) { - gpuSemantic = gpu::COMPRESSED_BC3_SRGBA; + gpuSemantic = gpu::COMPRESSED_SRGBA; } else { gpuSemantic = gpu::SRGBA; } @@ -263,9 +270,6 @@ void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element } } -#define CPU_MIPMAPS 1 -#define DEBUG_NVTT 0 - void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); @@ -276,6 +280,8 @@ void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; #endif // DEBUG_NVTT + texture->assignStoredMip(0, image.byteCount(), image.constBits()); + auto numMips = texture->getNumMips(); for (uint16 level = 1; level < numMips; ++level) { QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); @@ -305,6 +311,8 @@ void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateFaceMips"); + + auto numMips = texture->getNumMips(); for (uint16 level = 1; level < numMips; ++level) { QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); @@ -390,6 +398,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { return; /**/ + #if DEBUG_NVTT QDebug debug = qDebug(); QDebug* debugPtr = &debug; @@ -409,7 +418,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { nvtt::InputFormat inputFormat = nvtt::InputFormat_BGRA_8UB; nvtt::AlphaMode alphaMode = image.hasAlphaChannel() ? nvtt::AlphaMode_Transparency : nvtt::AlphaMode_None; nvtt::WrapMode wrapMode = nvtt::WrapMode_Repeat; - nvtt::Format compressionFormat = image.hasAlphaChannel() ? nvtt::Format_RGBA : nvtt::Format_RGB; + nvtt::Format compressionFormat = nvtt::Format_BC3; float inputGamma = 1.0f; float outputGamma = 2.2f; @@ -436,7 +445,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(compressionFormat); - compressionOptions.setQuality(nvtt::Quality_Production); + compressionOptions.setQuality(nvtt::Quality_Fastest); nvtt::Compressor compressor; compressor.process(inputOptions, compressionOptions, outputOptions); @@ -457,6 +466,8 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag gpu::Element formatGPU; gpu::Element formatMip; defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); + formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; + formatMip = gpu::Element::COLOR_COMPRESSED_SRGBA; if (isStrict) { theTexture = (gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -484,11 +495,11 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag } gpu::Texture* TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true, true); } gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true); } gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index f09986991a..23d60bd801 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -101,8 +101,6 @@ namespace ktx { UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B, UNSIGNED_INT_5_9_9_9_REV = 0x8C3E, FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD, - - NUM_GLTYPES = 25, }; enum class GLFormat : uint32_t { @@ -130,8 +128,6 @@ namespace ktx { RGBA_INTEGER = 0x8D99, BGR_INTEGER = 0x8D9A, BGRA_INTEGER = 0x8D9B, - - NUM_GLFORMATS = 20, }; enum class GLInternalFormat_Uncompressed : uint32_t { @@ -232,8 +228,6 @@ namespace ktx { STENCIL_INDEX4 = 0x8D47, STENCIL_INDEX8 = 0x8D48, STENCIL_INDEX16 = 0x8D49, - - NUM_UNCOMPRESSED_GLINTERNALFORMATS = 74, }; enum class GLInternalFormat_Compressed : uint32_t { @@ -267,8 +261,6 @@ namespace ktx { COMPRESSED_SIGNED_R11_EAC = 0x9271, COMPRESSED_RG11_EAC = 0x9272, COMPRESSED_SIGNED_RG11_EAC = 0x9273, - - NUM_COMPRESSED_GLINTERNALFORMATS = 24, }; enum class GLBaseInternalFormat : uint32_t { @@ -280,8 +272,6 @@ namespace ktx { RGB = 0x1907, RGBA = 0x1908, STENCIL_INDEX = 0x1901, - - NUM_GLBASEINTERNALFORMATS = 7, }; enum CubeMapFace { From 69a27d516fb5c5160ea38eec764a3ddf56e23937 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Apr 2017 20:07:00 -0700 Subject: [PATCH 05/32] Fix roughness --- libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp | 47 ++++++------------- .../src/gpu/gl41/GL41BackendTexture.cpp | 15 +++--- .../src/gpu/gl45/GL45BackendTexture.cpp | 18 +++---- libraries/gpu/src/gpu/Format.cpp | 2 + libraries/gpu/src/gpu/Format.h | 10 ++-- libraries/gpu/src/gpu/Texture_ktx.cpp | 15 ++++-- libraries/image/src/image/Image.cpp | 34 +++++++++----- libraries/ktx/src/ktx/KTX.h | 5 ++ 8 files changed, 79 insertions(+), 67 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index a865a11135..e3eb56a858 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -224,20 +224,16 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { result = GL_COMPRESSED_SRGB_ALPHA; break; - case gpu::COMPRESSED_BC3_RGBA: - result = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + case gpu::COMPRESSED_BC1_SRGB: + result = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + break; + case gpu::COMPRESSED_BC1_SRGBA: + result = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; break; case gpu::COMPRESSED_BC3_SRGBA: result = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; - case gpu::COMPRESSED_BC7_RGBA: - result = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; - break; - case gpu::COMPRESSED_BC7_SRGBA: - result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; - break; - default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } @@ -356,27 +352,16 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.internalFormat = GL_SRGB8_ALPHA8; break; - case gpu::COMPRESSED_RGBA: - texel.internalFormat = GL_COMPRESSED_RGBA; + case gpu::COMPRESSED_BC1_SRGB: + texel.internalFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; break; - case gpu::COMPRESSED_SRGBA: - texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; - break; - - case gpu::COMPRESSED_BC3_RGBA: - texel.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + case gpu::COMPRESSED_BC1_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; break; case gpu::COMPRESSED_BC3_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; - case gpu::COMPRESSED_BC7_RGBA: - texel.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; - break; - case gpu::COMPRESSED_BC7_SRGBA: - texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; - break; - default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } @@ -645,18 +630,16 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::COMPRESSED_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; break; - case gpu::COMPRESSED_BC3_RGBA: - texel.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + + case gpu::COMPRESSED_BC1_SRGB: + texel.internalFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + break; + case gpu::COMPRESSED_BC1_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; break; case gpu::COMPRESSED_BC3_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; - case gpu::COMPRESSED_BC7_RGBA: - texel.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; - break; - case gpu::COMPRESSED_BC7_SRGBA: - texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; - break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 2501f8b06b..6161fe719a 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -94,12 +94,15 @@ void GL41Texture::generateMips() const { void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { - if (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT == internalFormat) { - qCDebug(gpugllogging) << "Compressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); - qCDebug(gpugllogging) << "Compressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer; - glCompressedTexImage2D(_target, mip, internalFormat, size.x, size.y, 0, sourceSize, sourcePointer); - } else { - glTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + switch (internalFormat) { + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + glCompressedTexSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + break; + default: + glTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + break; } } else if (GL_TEXTURE_CUBE_MAP == _target) { auto target = GLTexture::CUBE_FACE_LAYOUT[face]; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index c530af535a..45d5b9b22e 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -119,15 +119,15 @@ void GL45Texture::generateMips() const { void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { - if (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT == internalFormat) { - qCDebug(gpugllogging) << "Compressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); - qCDebug(gpugllogging) << "Compressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer << "4.5"; - glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); - } - else { - qCDebug(gpugllogging) << "Uncompressed mipData level=" << mip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); - qCDebug(gpugllogging) << "Uncompressed mipData" << internalFormat << size.x << size.y << sourceSize << sourcePointer << "4.5"; - glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + switch (internalFormat) { + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + break; + default: + glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + break; } } else if (GL_TEXTURE_CUBE_MAP == _target) { // DSA ARB does not work on AMD, so use EXT diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index cdf5c8345c..7ffcee7a35 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -19,6 +19,8 @@ const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::COLOR_BGRA_32{ VEC4, NUINT8, BGRA }; const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; +const Element Element::COLOR_COMPRESSED_SRGB{ VEC4, NUINT8, COMPRESSED_BC1_SRGB }; +const Element Element::COLOR_COMPRESSED_SRGBA_MASK{ VEC4, NUINT8, COMPRESSED_BC1_SRGBA }; const Element Element::COLOR_COMPRESSED_SRGBA{ VEC4, NUINT8, COMPRESSED_BC3_SRGBA }; const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 2b42683d56..01efff0fcf 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -165,11 +165,9 @@ enum Semantic { COMPRESSED_SRGB, COMPRESSED_SRGBA, - COMPRESSED_BC3_RGBA, // RGBA_S3TC_DXT5_EXT, - COMPRESSED_BC3_SRGBA, // SRGB_ALPHA_S3TC_DXT5_EXT - - COMPRESSED_BC7_RGBA, - COMPRESSED_BC7_SRGBA, + COMPRESSED_BC1_SRGB, + COMPRESSED_BC1_SRGBA, + COMPRESSED_BC3_SRGBA, _LAST_COMPRESSED, @@ -236,6 +234,8 @@ public: static const Element COLOR_BGRA_32; static const Element COLOR_SBGRA_32; static const Element COLOR_R11G11B10; + static const Element COLOR_COMPRESSED_SRGB; + static const Element COLOR_COMPRESSED_SRGBA_MASK; static const Element COLOR_COMPRESSED_SRGBA; static const Element VEC4F_COLOR_RGBA; static const Element VEC2F_UV; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index d61788c7db..1e6ef53e85 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -260,9 +260,12 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RGBA, ktx::GLInternalFormat_Uncompressed::SRGB8_ALPHA8, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_R_8 && mipFormat == Format::COLOR_R_8) { header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat_Uncompressed::R8, ktx::GLBaseInternalFormat::RED); + } else if (texelFormat == Format::COLOR_COMPRESSED_SRGB && mipFormat == Format::COLOR_COMPRESSED_SRGB) { + header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGB); + } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_MASK && mipFormat == Format::COLOR_COMPRESSED_SRGBA_MASK) { + header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA && mipFormat == Format::COLOR_COMPRESSED_SRGBA) { - return false; - header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA); + header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, ktx::GLBaseInternalFormat::RGBA); } else { return false; } @@ -299,7 +302,13 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E return false; } } else if (header.getGLFormat() == ktx::GLFormat::COMPRESSED_FORMAT && header.getGLType() == ktx::GLType::COMPRESSED_TYPE) { - if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { + if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT) { + mipFormat = Format::COLOR_COMPRESSED_SRGB; + texelFormat = Format::COLOR_COMPRESSED_SRGB; + } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) { + mipFormat = Format::COLOR_COMPRESSED_SRGBA_MASK; + texelFormat = Format::COLOR_COMPRESSED_SRGBA_MASK; + } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { mipFormat = Format::COLOR_COMPRESSED_SRGBA; texelFormat = Format::COLOR_COMPRESSED_SRGBA; } else { diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 3a71d80e12..27c518c791 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -91,7 +91,7 @@ TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& break; } case gpu::ROUGHNESS_TEXTURE: { - return image::TextureUsage::createRoughnessTextureFromGlossImage; + return image::TextureUsage::createRoughnessTextureFromImage; break; } case gpu::GLOSS_TEXTURE: { @@ -389,7 +389,7 @@ struct MyErrorHandler : public nvtt::ErrorHandler { } }; -void generateNVTTMips(gpu::Texture* texture, QImage& image) { +void generateNVTTMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool alphaAsMask) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); @@ -416,10 +416,18 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { nvtt::TextureType textureType = nvtt::TextureType_2D; nvtt::InputFormat inputFormat = nvtt::InputFormat_BGRA_8UB; - nvtt::AlphaMode alphaMode = image.hasAlphaChannel() ? nvtt::AlphaMode_Transparency : nvtt::AlphaMode_None; + nvtt::AlphaMode alphaMode = validAlpha ? nvtt::AlphaMode_Transparency : nvtt::AlphaMode_None; nvtt::WrapMode wrapMode = nvtt::WrapMode_Repeat; - nvtt::Format compressionFormat = nvtt::Format_BC3; - float inputGamma = 1.0f; + nvtt::RoundMode roundMode = nvtt::RoundMode_None; + nvtt::Format compressionFormat = nvtt::Format_BC1; + if (validAlpha) { + if (alphaAsMask) { + compressionFormat = nvtt::Format_BC1a; + } else { + compressionFormat = nvtt::Format_BC3; + } + } + float inputGamma = 2.2f; float outputGamma = 2.2f; nvtt::InputOptions inputOptions; @@ -430,8 +438,8 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { inputOptions.setGamma(inputGamma, outputGamma); inputOptions.setAlphaMode(alphaMode); inputOptions.setWrapMode(wrapMode); + inputOptions.setRoundMode(roundMode); // inputOptions.setMaxExtents(int d); - // inputOptions.setRoundMode(RoundMode mode); inputOptions.setMipmapGeneration(true); inputOptions.setMipmapFilter(nvtt::MipmapFilter_Box); @@ -445,7 +453,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image) { nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(compressionFormat); - compressionOptions.setQuality(nvtt::Quality_Fastest); + compressionOptions.setQuality(nvtt::Quality_Production); nvtt::Compressor compressor; compressor.process(inputOptions, compressionOptions, outputOptions); @@ -464,10 +472,12 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatGPU; - gpu::Element formatMip; - defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); - formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; - formatMip = gpu::Element::COLOR_COMPRESSED_SRGBA; + if (validAlpha) { + formatGPU = alphaAsMask ? gpu::Element::COLOR_COMPRESSED_SRGBA_MASK : gpu::Element::COLOR_COMPRESSED_SRGBA; + } else { + formatGPU = gpu::Element::COLOR_COMPRESSED_SRGB; + } + gpu::Element formatMip = formatGPU; if (isStrict) { theTexture = (gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -486,7 +496,7 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag theTexture->setStoredMipFormat(formatMip); if (generateMips) { - generateNVTTMips(theTexture, image); + generateNVTTMips(theTexture, image, validAlpha, alphaAsMask); } theTexture->setSource(srcImageName); } diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index 23d60bd801..043de573ed 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -240,6 +240,11 @@ namespace ktx { COMPRESSED_SRGB = 0x8C48, COMPRESSED_SRGB_ALPHA = 0x8C49, + COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C, + COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D, + COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E, + COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F, + COMPRESSED_RED_RGTC1 = 0x8DBB, COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC, COMPRESSED_RG_RGTC2 = 0x8DBD, From 94e1cbbc954f2b46c9b6d1962e2a9f7cb3e1bf40 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Apr 2017 20:24:42 -0700 Subject: [PATCH 06/32] Upload nvtt archive to S3 --- cmake/externals/nvtt/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index 4657c27bd2..c92e420d40 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -8,8 +8,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (NOT ANDROID) ExternalProject_Add( ${EXTERNAL_NAME} - URL "C:/Users/Clement/dev/nvidia-texture-tools/project/vc12/package" - # URL_MD5 "e7f0a941c9a873f2c4334367454485da" + URL "https://s3-us-west-1.amazonaws.com/hifi-content/clement/dev/nvtt.zip" + URL_MD5 "3ea6eeadbcc69071acf9c49ba565760e" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From ee62e7dcb8ad40756496de0481046dde50c313f1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 11:29:19 -0700 Subject: [PATCH 07/32] update nvtt external to build from source --- cmake/externals/nvtt/CMakeLists.txt | 26 ++++++++++++------------- cmake/modules/FindNVTT.cmake | 30 +++++++++++++++++++++++++++++ libraries/image/CMakeLists.txt | 1 + 3 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 cmake/modules/FindNVTT.cmake diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index c92e420d40..a8ba0cb4c1 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -8,29 +8,29 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (NOT ANDROID) ExternalProject_Add( ${EXTERNAL_NAME} - URL "https://s3-us-west-1.amazonaws.com/hifi-content/clement/dev/nvtt.zip" - URL_MD5 "3ea6eeadbcc69071acf9c49ba565760e" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" + URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip + URL_MD5 79842ea185c8c95aaa70cee91e77f032 + CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=0 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 ) # Hide this external target (for IDE users) set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") - ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "Location of NVTT include directory") if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT library") - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/Release/x64 CACHE PATH "Location of NVTT DLL") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/Debug/x64/nvtt.lib CACHE FILEPATH "Path to NVTT Debug library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT Release library") + + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/Release/x64 CACHE PATH "Location of NVTT DLL") add_paths_to_fixup_libs(${${EXTERNAL_NAME_UPPER}_DLL_PATH}) - else (APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") - elseif () - set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${INSTALL_DIR}/lib/nvtt.so CACHE FILEPATH "Path to NVTT library") + else () + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") endif () endif() diff --git a/cmake/modules/FindNVTT.cmake b/cmake/modules/FindNVTT.cmake new file mode 100644 index 0000000000..7743610d5a --- /dev/null +++ b/cmake/modules/FindNVTT.cmake @@ -0,0 +1,30 @@ +# +# FindNVTT.cmake +# +# Try to find NVIDIA texture tools library and include path. +# Once done this will define +# +# NVTT_FOUND +# NVTT_INCLUDE_DIRS +# NVTT_LIBRARIES +# +# Created on 4/14/2017 by Stephen Birarda +# Copyright 2017 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 +# + +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("nvtt") + +find_path(NVTT_INCLUDE_DIRS nvtt/nvtt.h PATH_SUFFIXES include HINTS ${NVTT_SEARCH_DIRS}) + +find_library(NVTT_LIBRARY_RELEASE nvtt PATH_SUFFIXES "lib/static" "Release/x64" HINTS ${NVTT_SEARCH_DIRS}) +find_library(NVTT_LIBRARY_DEBUG nvtt PATH_SUFFIXES "Debug/x64" HINTS ${NVTT_SEARCH_DIRS}) + +include(SelectLibraryConfigurations) +select_library_configurations(NVTT) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARIES) diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt index 399d541b40..7b5c505d24 100644 --- a/libraries/image/CMakeLists.txt +++ b/libraries/image/CMakeLists.txt @@ -5,5 +5,6 @@ link_hifi_libraries(shared gpu) target_glm() add_dependency_external_projects(nvtt) +find_package(NVTT REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) From 27c6011e6e45b7d1f6273a01bd7962c2aad79918 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 11:34:52 -0700 Subject: [PATCH 08/32] change nvtt external to ignore release type --- cmake/externals/nvtt/CMakeLists.txt | 8 ++------ cmake/modules/FindNVTT.cmake | 10 +++------- libraries/image/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index a8ba0cb4c1..b2bb0c29fa 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -24,13 +24,9 @@ if (NOT ANDROID) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "Location of NVTT include directory") if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/Debug/x64/nvtt.lib CACHE FILEPATH "Path to NVTT Debug library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT Release library") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/Release/x64 CACHE PATH "Location of NVTT DLL") - add_paths_to_fixup_libs(${${EXTERNAL_NAME_UPPER}_DLL_PATH}) + set(${EXTERNAL_NAME_UPPER}_LIBRARY ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") endif () endif() diff --git a/cmake/modules/FindNVTT.cmake b/cmake/modules/FindNVTT.cmake index 7743610d5a..90a853ccb1 100644 --- a/cmake/modules/FindNVTT.cmake +++ b/cmake/modules/FindNVTT.cmake @@ -6,7 +6,7 @@ # # NVTT_FOUND # NVTT_INCLUDE_DIRS -# NVTT_LIBRARIES +# NVTT_LIBRARY # # Created on 4/14/2017 by Stephen Birarda # Copyright 2017 High Fidelity, Inc. @@ -20,11 +20,7 @@ hifi_library_search_hints("nvtt") find_path(NVTT_INCLUDE_DIRS nvtt/nvtt.h PATH_SUFFIXES include HINTS ${NVTT_SEARCH_DIRS}) -find_library(NVTT_LIBRARY_RELEASE nvtt PATH_SUFFIXES "lib/static" "Release/x64" HINTS ${NVTT_SEARCH_DIRS}) -find_library(NVTT_LIBRARY_DEBUG nvtt PATH_SUFFIXES "Debug/x64" HINTS ${NVTT_SEARCH_DIRS}) - -include(SelectLibraryConfigurations) -select_library_configurations(NVTT) +find_library(NVTT_LIBRARY nvtt PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARIES) +find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARY) diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt index 7b5c505d24..b30e67d9d4 100644 --- a/libraries/image/CMakeLists.txt +++ b/libraries/image/CMakeLists.txt @@ -7,4 +7,4 @@ target_glm() add_dependency_external_projects(nvtt) find_package(NVTT REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) +target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARY}) From ae73cf40384a4f02853cf20be5bee29fef6386ec Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 14 Apr 2017 12:59:46 -0700 Subject: [PATCH 09/32] Add support for Grayscale and NormalMap textures --- libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp | 61 ++---- .../src/gpu/gl41/GL41BackendTexture.cpp | 2 + .../src/gpu/gl45/GL45BackendTexture.cpp | 2 + libraries/gpu/src/gpu/Format.cpp | 6 +- libraries/gpu/src/gpu/Format.h | 11 +- libraries/gpu/src/gpu/Texture_ktx.cpp | 10 + libraries/image/src/image/Image.cpp | 204 ++++-------------- libraries/image/src/image/Image.h | 7 +- 8 files changed, 86 insertions(+), 217 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index e3eb56a858..b0c53caa1a 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -76,10 +76,6 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { } break; - case gpu::COMPRESSED_R: - result = GL_COMPRESSED_RED_RGTC1; - break; - case gpu::R11G11B10: // the type should be float result = GL_R11F_G11F_B10F; @@ -149,12 +145,6 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { case gpu::SRGBA: result = GL_SRGB8; // standard 2.2 gamma correction color break; - case gpu::COMPRESSED_RGB: - result = GL_COMPRESSED_RGB; - break; - case gpu::COMPRESSED_SRGB: - result = GL_COMPRESSED_SRGB; - break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } @@ -217,13 +207,10 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { case gpu::SRGBA: result = GL_SRGB8_ALPHA8; // standard 2.2 gamma correction color break; - case gpu::COMPRESSED_RGBA: - result = GL_COMPRESSED_RGBA; - break; - case gpu::COMPRESSED_SRGBA: - result = GL_COMPRESSED_SRGB_ALPHA; - break; + case gpu::COMPRESSED_BC4_RED: + result = GL_COMPRESSED_RED_RGTC1; + break; case gpu::COMPRESSED_BC1_SRGB: result = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; break; @@ -233,6 +220,9 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { case gpu::COMPRESSED_BC3_SRGBA: result = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; + case gpu::COMPRESSED_BC5_XY: + result = GL_COMPRESSED_RG_RGTC2; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; @@ -262,10 +252,6 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.internalFormat = GL_R8; break; - case gpu::COMPRESSED_R: - texel.internalFormat = GL_COMPRESSED_RED_RGTC1; - break; - case gpu::DEPTH: texel.format = GL_DEPTH_COMPONENT; texel.internalFormat = GL_DEPTH_COMPONENT32; @@ -308,12 +294,6 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::RGBA: texel.internalFormat = GL_RGB8; break; - case gpu::COMPRESSED_RGB: - texel.internalFormat = GL_COMPRESSED_RGB; - break; - case gpu::COMPRESSED_SRGB: - texel.internalFormat = GL_COMPRESSED_SRGB; - break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } @@ -352,6 +332,10 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.internalFormat = GL_SRGB8_ALPHA8; break; + + case gpu::COMPRESSED_BC4_RED: + texel.internalFormat = GL_COMPRESSED_RED_RGTC1; + break; case gpu::COMPRESSED_BC1_SRGB: texel.internalFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; break; @@ -361,6 +345,9 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::COMPRESSED_BC3_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; + case gpu::COMPRESSED_BC5_XY: + texel.internalFormat = GL_COMPRESSED_RG_RGTC2; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; @@ -381,10 +368,6 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.type = ELEMENT_TYPE_TO_GL[dstFormat.getType()]; switch (dstFormat.getSemantic()) { - case gpu::COMPRESSED_R: { - texel.internalFormat = GL_COMPRESSED_RED_RGTC1; - break; - } case gpu::RED: case gpu::RGB: case gpu::RGBA: @@ -542,12 +525,6 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::SRGBA: texel.internalFormat = GL_SRGB8; // standard 2.2 gamma correction color break; - case gpu::COMPRESSED_RGB: - texel.internalFormat = GL_COMPRESSED_RGB; - break; - case gpu::COMPRESSED_SRGB: - texel.internalFormat = GL_COMPRESSED_SRGB; - break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } @@ -624,13 +601,10 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::SRGBA: texel.internalFormat = GL_SRGB8_ALPHA8; // standard 2.2 gamma correction color break; - case gpu::COMPRESSED_RGBA: - texel.internalFormat = GL_COMPRESSED_RGBA; - break; - case gpu::COMPRESSED_SRGBA: - texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; - break; + case gpu::COMPRESSED_BC4_RED: + texel.internalFormat = GL_COMPRESSED_RED_RGTC1; + break; case gpu::COMPRESSED_BC1_SRGB: texel.internalFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; break; @@ -640,6 +614,9 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::COMPRESSED_BC3_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; + case gpu::COMPRESSED_BC5_XY: + texel.internalFormat = GL_COMPRESSED_RG_RGTC2; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 6161fe719a..6811ef7020 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -98,6 +98,8 @@ void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: glCompressedTexSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); break; default: diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 45d5b9b22e..893e6412ea 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -123,6 +123,8 @@ void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); break; default: diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index 7ffcee7a35..31de77b547 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -19,9 +19,11 @@ const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::COLOR_BGRA_32{ VEC4, NUINT8, BGRA }; const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; +const Element Element::COLOR_COMPRESSED_RED{VEC4, NUINT8, COMPRESSED_BC4_RED}; const Element Element::COLOR_COMPRESSED_SRGB{ VEC4, NUINT8, COMPRESSED_BC1_SRGB }; -const Element Element::COLOR_COMPRESSED_SRGBA_MASK{ VEC4, NUINT8, COMPRESSED_BC1_SRGBA }; -const Element Element::COLOR_COMPRESSED_SRGBA{ VEC4, NUINT8, COMPRESSED_BC3_SRGBA }; +const Element Element::COLOR_COMPRESSED_SRGBA_MASK{VEC4, NUINT8, COMPRESSED_BC1_SRGBA}; +const Element Element::COLOR_COMPRESSED_SRGBA{VEC4, NUINT8, COMPRESSED_BC3_SRGBA}; +const Element Element::COLOR_COMPRESSED_XY{VEC4, NUINT8, COMPRESSED_BC5_XY}; const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 }; const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 01efff0fcf..f69e8d9386 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -157,17 +157,12 @@ enum Semantic { // These are generic compression format smeantic for images _FIRST_COMPRESSED, - COMPRESSED_R, - - COMPRESSED_RGB, - COMPRESSED_RGBA, - - COMPRESSED_SRGB, - COMPRESSED_SRGBA, COMPRESSED_BC1_SRGB, COMPRESSED_BC1_SRGBA, COMPRESSED_BC3_SRGBA, + COMPRESSED_BC4_RED, + COMPRESSED_BC5_XY, _LAST_COMPRESSED, @@ -234,9 +229,11 @@ public: static const Element COLOR_BGRA_32; static const Element COLOR_SBGRA_32; static const Element COLOR_R11G11B10; + static const Element COLOR_COMPRESSED_RED; static const Element COLOR_COMPRESSED_SRGB; static const Element COLOR_COMPRESSED_SRGBA_MASK; static const Element COLOR_COMPRESSED_SRGBA; + static const Element COLOR_COMPRESSED_XY; static const Element VEC4F_COLOR_RGBA; static const Element VEC2F_UV; static const Element VEC2F_XY; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 1e6ef53e85..dc8e69d302 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -266,6 +266,10 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA && mipFormat == Format::COLOR_COMPRESSED_SRGBA) { header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, ktx::GLBaseInternalFormat::RGBA); + } else if (texelFormat == Format::COLOR_COMPRESSED_RED && mipFormat == Format::COLOR_COMPRESSED_RED) { + header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1, ktx::GLBaseInternalFormat::RED); + } else if (texelFormat == Format::COLOR_COMPRESSED_XY && mipFormat == Format::COLOR_COMPRESSED_XY) { + header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2, ktx::GLBaseInternalFormat::RG); } else { return false; } @@ -311,6 +315,12 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { mipFormat = Format::COLOR_COMPRESSED_SRGBA; texelFormat = Format::COLOR_COMPRESSED_SRGBA; + } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1) { + mipFormat = Format::COLOR_COMPRESSED_RED; + texelFormat = Format::COLOR_COMPRESSED_RED; + } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2) { + mipFormat = Format::COLOR_COMPRESSED_XY; + texelFormat = Format::COLOR_COMPRESSED_XY; } else { return false; } diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 27c518c791..18f549ebc7 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -28,7 +28,6 @@ using namespace gpu; // FIXME: Declare this to enable compression //#define COMPRESS_TEXTURES #define CPU_MIPMAPS 1 -#define DEBUG_NVTT 1 static const glm::uvec2 SPARSE_PAGE_SIZE(128); static const glm::uvec2 MAX_TEXTURE_SIZE(4096); @@ -221,29 +220,16 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val } void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, - const QImage& image, bool isLinear, bool doCompress) { -#ifdef COMPRESS_TEXTURES -#else - doCompress = false; -#endif - + const QImage& image, bool isLinear) { if (image.hasAlphaChannel()) { gpu::Semantic gpuSemantic; gpu::Semantic mipSemantic; if (isLinear) { mipSemantic = gpu::BGRA; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_RGBA; - } else { - gpuSemantic = gpu::RGBA; - } + gpuSemantic = gpu::RGBA; } else { mipSemantic = gpu::SBGRA; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_SRGBA; - } else { - gpuSemantic = gpu::SRGBA; - } + gpuSemantic = gpu::SRGBA; } formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpuSemantic); formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, mipSemantic); @@ -252,62 +238,16 @@ void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element gpu::Semantic mipSemantic; if (isLinear) { mipSemantic = gpu::RGB; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_RGB; - } else { - gpuSemantic = gpu::RGB; - } + gpuSemantic = gpu::RGB; } else { mipSemantic = gpu::SRGB; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_SRGB; - } else { - gpuSemantic = gpu::SRGB; - } + gpuSemantic = gpu::SRGB; } formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); } } -void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) { -#if CPU_MIPMAPS - PROFILE_RANGE(resource_parse, "generateMips"); -#if DEBUG_NVTT - QDebug debug = qDebug(); - - debug << Q_FUNC_INFO << "\n"; - debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; -#endif // DEBUG_NVTT - - texture->assignStoredMip(0, image.byteCount(), image.constBits()); - - auto numMips = texture->getNumMips(); - for (uint16 level = 1; level < numMips; ++level) { - QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); - if (fastResize) { - image = image.scaled(mipSize); - -#if DEBUG_NVTT - debug << "Begin fast { " << image.byteCount() << image.width() << image.height() << image.depth() << level << " } Ends\n"; -#endif // DEBUG_NVTT - - texture->assignStoredMip(level, image.byteCount(), image.constBits()); - } else { - QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - -#if DEBUG_NVTT - debug << "Begin { " << mipImage.byteCount() << mipImage.width() << mipImage.height() << mipImage.depth() << level << " } Ends\n"; -#endif // DEBUG_NVTT - - texture->assignStoredMip(level, mipImage.byteCount(), mipImage.constBits()); - } - } -#else - texture->autoGenerateMips(-1); -#endif -} - void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateFaceMips"); @@ -325,26 +265,9 @@ void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { } struct MyOutputHandler : public nvtt::OutputHandler { - MyOutputHandler(gpu::Texture* texture, QDebug* debug) : -#if DEBUG_NVTT - _debug(debug), -#endif // DEBUG_NVTT - _texture(texture) { - - } + MyOutputHandler(gpu::Texture* texture) : _texture(texture) {} virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { -#if DEBUG_NVTT - auto list = QStringList() << QString::number(size) - << QString::number(width) - << QString::number(height) - << QString::number(depth) - << QString::number(face) - << QString::number(miplevel); - _count = 0; - _str = "Begin { " + list.join(", "); -#endif // DEBUG_NVTT - _size = size; _miplevel = miplevel; @@ -352,31 +275,17 @@ struct MyOutputHandler : public nvtt::OutputHandler { _current = _data; } virtual bool writeData(const void* data, int size) { -#if DEBUG_NVTT - ++_count; -#endif // DEBUG_NVTT - assert(_current + size <= _data + _size); memcpy(_current, data, size); _current += size; return true; } virtual void endImage() { -#if DEBUG_NVTT - _str += " } End " + QString::number(_count) + "\n"; - *_debug << qPrintable(_str); -#endif // DEBUG_NVTT - _texture->assignStoredMip(_miplevel, _size, static_cast(_data)); free(_data); _data = nullptr; } -#if DEBUG_NVTT - int _count = 0; - QString _str; - QDebug* _debug{ nullptr }; -#endif // DEBUG_NVTT gpu::Byte* _data{ nullptr }; gpu::Byte* _current{ nullptr }; gpu::Texture* _texture{ nullptr }; @@ -389,26 +298,10 @@ struct MyErrorHandler : public nvtt::ErrorHandler { } }; -void generateNVTTMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool alphaAsMask) { +void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool alphaAsMask, bool grayscale, bool normalMap) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); - /*/ - generateMips(texture, image, false); - return; - /**/ - - -#if DEBUG_NVTT - QDebug debug = qDebug(); - QDebug* debugPtr = &debug; - - debug << Q_FUNC_INFO << "\n"; - debug << (QList() << image.byteCount() << image.width() << image.height() << image.depth()) << "\n"; -#else - QDebug* debugPtr = nullptr; -#endif // DEBUG_NVTT - Q_ASSERT(image.format() == QImage::Format_ARGB32); const int width = image.width(), height = image.height(); @@ -426,6 +319,10 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image, bool validAlpha, boo } else { compressionFormat = nvtt::Format_BC3; } + } else if (grayscale) { + compressionFormat = nvtt::Format_BC4; + } else if (normalMap) { + compressionFormat = nvtt::Format_BC5; } float inputGamma = 2.2f; float outputGamma = 2.2f; @@ -446,7 +343,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image, bool validAlpha, boo nvtt::OutputOptions outputOptions; outputOptions.setOutputHeader(false); - MyOutputHandler outputHandler(texture, debugPtr); + MyOutputHandler outputHandler(texture); outputOptions.setOutputHandler(&outputHandler); MyErrorHandler errorHandler; outputOptions.setErrorHandler(&errorHandler); @@ -462,7 +359,7 @@ void generateNVTTMips(gpu::Texture* texture, QImage& image, bool validAlpha, boo #endif } -gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool isStrict) { +gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doGenerateMips, bool isStrict) { PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); bool validAlpha = false; bool alphaAsMask = true; @@ -495,8 +392,8 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag theTexture->setUsage(usage.build()); theTexture->setStoredMipFormat(formatMip); - if (generateMips) { - generateNVTTMips(theTexture, image, validAlpha, alphaAsMask); + if (doGenerateMips) { + generateMips(theTexture, image, validAlpha, alphaAsMask, false, false); } theTexture->setSource(srcImageName); } @@ -505,23 +402,23 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag } gpu::Texture* TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); } gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, false, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, true); } gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, true); } gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, true); } gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, true); } @@ -538,14 +435,13 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatMip = gpu::Element::COLOR_BGRA_32; - gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; + gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); + generateMips(theTexture, image, false, false, false, true); theTexture->setSource(srcImageName); } @@ -627,15 +523,14 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm gpu::Texture* theTexture = nullptr; if ((result.width() > 0) && (result.height() > 0)) { - gpu::Element formatMip = gpu::Element::COLOR_BGRA_32; - gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; + gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; theTexture = (gpu::Texture::create2D(formatGPU, result.width(), result.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, result.byteCount(), result.constBits()); - generateMips(theTexture, result, true); + generateMips(theTexture, image, false, false, false, true); theTexture->setSource(srcImageName); } @@ -656,22 +551,17 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma } } - image = image.convertToFormat(QImage::Format_Grayscale8); + image = image.convertToFormat(QImage::Format_ARGB32); gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESS_TEXTURES - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); -#else - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - gpu::Element formatMip = gpu::Element::COLOR_R_8; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; + gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); + generateMips(theTexture, image, false, false, true, false); theTexture->setSource(srcImageName); } @@ -695,23 +585,18 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s // Gloss turned into Rough image.invertPixels(QImage::InvertRgba); - image = image.convertToFormat(QImage::Format_Grayscale8); + image = image.convertToFormat(QImage::Format_ARGB32); gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESS_TEXTURES - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); -#else - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - gpu::Element formatMip = gpu::Element::COLOR_R_8; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; + gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); + generateMips(theTexture, image, false, false, true, false); theTexture->setSource(srcImageName); } @@ -732,23 +617,18 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag } } - image = image.convertToFormat(QImage::Format_Grayscale8); + image = image.convertToFormat(QImage::Format_ARGB32); gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESS_TEXTURES - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); -#else - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - gpu::Element formatMip = gpu::Element::COLOR_R_8; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; + gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - theTexture->assignStoredMip(0, image.byteCount(), image.constBits()); - generateMips(theTexture, image, true); + generateMips(theTexture, image, false, false, true, false); theTexture->setSource(srcImageName); } @@ -1012,7 +892,7 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { }; const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); -gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance) { +gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateMips, bool generateIrradiance) { PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage"); gpu::Texture* theTexture = nullptr; @@ -1024,7 +904,7 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm gpu::Element formatGPU; gpu::Element formatMip; - defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); + defineColorTexelFormats(formatGPU, formatMip, image, isLinear); // Find the layout of the cubemap in the 2D image // Use the original image size since processSourceImage may have altered the size / aspect ratio @@ -1086,11 +966,11 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm } gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, true); + return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true); } gpu::Texture* TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, false); + return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, false); } } // namespace image \ No newline at end of file diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index a311514a66..5c3becf2af 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -44,10 +44,9 @@ gpu::Texture* createCubeTextureFromImageWithoutIrradiance(const QImage& image, c gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); -void defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, - const QImage& srcImage, bool isLinear, bool doCompress); -gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool isStrict = false); -gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance); +void defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, const QImage& srcImage, bool isLinear); +gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateMips, bool isStrict = false); +gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateMips, bool generateIrradiance); } // namespace TextureUsage From 5c12180b58ea4535c85b522431fa050771bd639b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 14:24:47 -0700 Subject: [PATCH 10/32] use pre-built NVTT on windows --- cmake/externals/nvtt/CMakeLists.txt | 55 ++++++++++++++++++----------- cmake/modules/FindNVTT.cmake | 30 +++++++++++++--- libraries/image/CMakeLists.txt | 3 +- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index b2bb0c29fa..262c72a0d2 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -6,27 +6,42 @@ set(EXTERNAL_NAME nvtt) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (NOT ANDROID) - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip - URL_MD5 79842ea185c8c95aaa70cee91e77f032 - CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=0 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 - ) + if (WIN32) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip + URL_MD5 3ea6eeadbcc69071acf9c49ba565760e + LOG_DOWNLOAD 1 + ) + + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/Debug/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static debug library") + + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/$<$:Debug>$<$>:Release>/x64" CACHE PATH "Location of NVTT DLL") + else () + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip + URL_MD5 79842ea185c8c95aaa70cee91e77f032 + CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=0 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + ) + + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "Location of NVTT include directory") + + set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT base static library") + set(${EXTERNAL_NAME_UPPER}_CORE_LIBRARY ${INSTALL_DIR}/lib/static/libnvcore.a CACHE FILEPATH "Path to NVTT core static library") + set(${EXTERNAL_NAME_UPPER}_IMAGE_LIBRARY ${INSTALL_DIR}/lib/static/libnvimage.a CACHE FILEPATH "Path to NVTT image static library") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY ${INSTALL_DIR}/lib/static/libnvmath.a CACHE FILEPATH "Path to NVTT math static library") + set(${EXTERNAL_NAME_UPPER}_THREAD_LIBRARY ${INSTALL_DIR}/lib/static/libnvthread.a CACHE FILEPATH "Path to NVTT thread static library") + endif () # Hide this external target (for IDE users) set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") - - ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "Location of NVTT include directory") - - if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARY ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") - else () - set(${EXTERNAL_NAME_UPPER}_LIBRARY ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT static library") - endif () - endif() diff --git a/cmake/modules/FindNVTT.cmake b/cmake/modules/FindNVTT.cmake index 90a853ccb1..dd50e34d31 100644 --- a/cmake/modules/FindNVTT.cmake +++ b/cmake/modules/FindNVTT.cmake @@ -6,7 +6,8 @@ # # NVTT_FOUND # NVTT_INCLUDE_DIRS -# NVTT_LIBRARY +# NVTT_LIBRARIES +# NVTT_DLL_PATH # # Created on 4/14/2017 by Stephen Birarda # Copyright 2017 High Fidelity, Inc. @@ -20,7 +21,28 @@ hifi_library_search_hints("nvtt") find_path(NVTT_INCLUDE_DIRS nvtt/nvtt.h PATH_SUFFIXES include HINTS ${NVTT_SEARCH_DIRS}) -find_library(NVTT_LIBRARY nvtt PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) - include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARY) + +if (WIN32) + find_library(NVTT_LIBRARY_RELEASE nvtt PATH_SUFFIXES "Release.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) + find_library(NVTT_LIBRARY_DEBUG nvtt PATH_SUFFIXES "Debug.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) + + find_path(NVTT_RELEASE_DLL_PATH nvtt.dll PATH_SUFFIXES "Release.x64/bin" HINTS ${NVTT_SEARCH_DIRS}) + find_path(NVTT_DEBUG_DLL_PATH nvtt.dll PATH_SUFFIXES "Debug.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) + + include(SelectLibraryConfigurations) + select_library_configurations(NVTT) + + find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARIES NVTT_RELEASE_DLL_PATH NVTT_DEBUG_DLL_PATH) + + set(NVTT_DLL_PATH "$<$>:${NVTT_RELEASE_DLL_PATH}>$<$:${NVTT_DEBUG_DLL_PATH}>") +else () + find_library(NVTT_BASE_LIBRARY nvtt PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) + find_library(NVTT_CORE_LIBRARY nvcore PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) + find_library(NVTT_IMAGE_LIBRARY nvimage PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) + find_library(NVTT_MATH_LIBRARY nvmath PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) + find_library(NVTT_THREAD_LIBRARY nvthread PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) + + find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_BASE_LIBRARY NVTT_CORE_LIBRARY NVTT_IMAGE_LIBRARY NVTT_MATH_LIBRARY NVTT_THREAD_LIBRARY) + set(NVTT_LIBRARIES ${NVTT_BASE_LIBRARY} ${NVTT_CORE_LIBRARY} ${NVTT_IMAGE_LIBRARY} ${NVTT_MATH_LIBRARY} ${NVTT_THREAD_LIBRARY}) +endif () diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt index b30e67d9d4..85d3d8f1ae 100644 --- a/libraries/image/CMakeLists.txt +++ b/libraries/image/CMakeLists.txt @@ -7,4 +7,5 @@ target_glm() add_dependency_external_projects(nvtt) find_package(NVTT REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARY}) +target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) +add_paths_to_fixup_libs(${NVTT_DLL_PATH}) From 3a217f75f4915b04d18a35a3762780d4e30c83bb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 15:03:08 -0700 Subject: [PATCH 11/32] force release for NVTT on Win32 --- cmake/externals/nvtt/CMakeLists.txt | 10 +++++++--- cmake/modules/FindNVTT.cmake | 7 ++----- libraries/image/CMakeLists.txt | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index 262c72a0d2..48873f956d 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -11,15 +11,19 @@ if (NOT ANDROID) ${EXTERNAL_NAME} URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip URL_MD5 3ea6eeadbcc69071acf9c49ba565760e + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" LOG_DOWNLOAD 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static release library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/Debug/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static debug library") + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") - set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/$<$:Debug>$<$>:Release>/x64" CACHE PATH "Location of NVTT DLL") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT release library") + + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/Release/x64" CACHE PATH "Location of NVTT release DLL") else () ExternalProject_Add( ${EXTERNAL_NAME} diff --git a/cmake/modules/FindNVTT.cmake b/cmake/modules/FindNVTT.cmake index dd50e34d31..9881c130b7 100644 --- a/cmake/modules/FindNVTT.cmake +++ b/cmake/modules/FindNVTT.cmake @@ -27,15 +27,12 @@ if (WIN32) find_library(NVTT_LIBRARY_RELEASE nvtt PATH_SUFFIXES "Release.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) find_library(NVTT_LIBRARY_DEBUG nvtt PATH_SUFFIXES "Debug.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) - find_path(NVTT_RELEASE_DLL_PATH nvtt.dll PATH_SUFFIXES "Release.x64/bin" HINTS ${NVTT_SEARCH_DIRS}) - find_path(NVTT_DEBUG_DLL_PATH nvtt.dll PATH_SUFFIXES "Debug.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) + find_path(NVTT_DLL_PATH nvtt.dll PATH_SUFFIXES "Release.x64/bin" HINTS ${NVTT_SEARCH_DIRS}) include(SelectLibraryConfigurations) select_library_configurations(NVTT) - find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARIES NVTT_RELEASE_DLL_PATH NVTT_DEBUG_DLL_PATH) - - set(NVTT_DLL_PATH "$<$>:${NVTT_RELEASE_DLL_PATH}>$<$:${NVTT_DEBUG_DLL_PATH}>") + find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARIES NVTT_DLL_PATH) else () find_library(NVTT_BASE_LIBRARY nvtt PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) find_library(NVTT_CORE_LIBRARY nvcore PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt index 85d3d8f1ae..cc1e3f4df2 100644 --- a/libraries/image/CMakeLists.txt +++ b/libraries/image/CMakeLists.txt @@ -8,4 +8,5 @@ add_dependency_external_projects(nvtt) find_package(NVTT REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) +message(${NVTT_DLL_PATH}) add_paths_to_fixup_libs(${NVTT_DLL_PATH}) From d72e5e5b24e83e9a701e14365203ad89d5c9598e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 15:38:44 -0700 Subject: [PATCH 12/32] add handling for install_name_tool calls on OS X --- cmake/externals/nvtt/CMakeLists.txt | 57 ++++++++++++++++++++++------- cmake/modules/FindNVTT.cmake | 22 ++++------- libraries/image/CMakeLists.txt | 1 - 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index 48873f956d..0f45bc45c6 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -11,25 +11,21 @@ if (NOT ANDROID) ${EXTERNAL_NAME} URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip URL_MD5 3ea6eeadbcc69071acf9c49ba565760e - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" LOG_DOWNLOAD 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/Debug/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static debug library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT release library") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/Release/x64" CACHE PATH "Location of NVTT release DLL") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/$<$:Debug>$<$>:Release>/x64" CACHE PATH "Location of NVTT DLL") else () ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip URL_MD5 79842ea185c8c95aaa70cee91e77f032 - CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=0 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= + CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 @@ -39,11 +35,46 @@ if (NOT ANDROID) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "Location of NVTT include directory") - set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY ${INSTALL_DIR}/lib/static/libnvtt.a CACHE FILEPATH "Path to NVTT base static library") - set(${EXTERNAL_NAME_UPPER}_CORE_LIBRARY ${INSTALL_DIR}/lib/static/libnvcore.a CACHE FILEPATH "Path to NVTT core static library") - set(${EXTERNAL_NAME_UPPER}_IMAGE_LIBRARY ${INSTALL_DIR}/lib/static/libnvimage.a CACHE FILEPATH "Path to NVTT image static library") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY ${INSTALL_DIR}/lib/static/libnvmath.a CACHE FILEPATH "Path to NVTT math static library") - set(${EXTERNAL_NAME_UPPER}_THREAD_LIBRARY ${INSTALL_DIR}/lib/static/libnvthread.a CACHE FILEPATH "Path to NVTT thread static library") + if (APPLE) + set(_LIB_EXT "dylib") + else () + set(_LIB_EXT "so") + endif () + + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libnvtt.${_LIB_EXT} CACHE FILEPATH "Path to NVTT library") + + if (APPLE) + # on OS X we have to use install_name_tool to fix the paths found in the NVTT shared libraries + # so that they can be found and linked during the linking phase + set(_NVTT_LIB_DIR "${INSTALL_DIR}/lib") + + # first fix the install names of all present libraries + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-install-name + COMMENT "Calling install_name_tool on NVTT libraries to fix install name for dylib linking" + COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_NVTT_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake + DEPENDEES install + WORKING_DIRECTORY + LOG 1 + ) + + # then, for the main library (libnvtt) fix the paths to the dependency libraries (core, image, math) + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-dependency-paths + COMMENT "Calling install_name_tool on NVTT libraries to fix paths for dependency libraries" + COMMAND install_name_tool -change libnvimage.dylib ${INSTALL_DIR}/lib/libnvimage.dylib libnvtt.dylib + COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvtt.dylib + COMMAND install_name_tool -change libnvmath.dylib ${INSTALL_DIR}/lib/libnvmath.dylib libnvtt.dylib + COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvimage.dylib + COMMAND install_name_tool -change libnvmath.dylib ${INSTALL_DIR}/lib/libnvmath.dylib libnvimage.dylib + COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvmath.dylib + DEPENDEES install + WORKING_DIRECTORY /lib + LOG 1 + ) + endif () endif () # Hide this external target (for IDE users) diff --git a/cmake/modules/FindNVTT.cmake b/cmake/modules/FindNVTT.cmake index 9881c130b7..8fae621d81 100644 --- a/cmake/modules/FindNVTT.cmake +++ b/cmake/modules/FindNVTT.cmake @@ -23,23 +23,15 @@ find_path(NVTT_INCLUDE_DIRS nvtt/nvtt.h PATH_SUFFIXES include HINTS ${NVTT_SEARC include(FindPackageHandleStandardArgs) +find_library(NVTT_LIBRARY_RELEASE nvtt PATH_SUFFIXES "lib" "Release.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) +find_library(NVTT_LIBRARY_DEBUG nvtt PATH_SUFFIXES "lib" "Debug.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) + +include(SelectLibraryConfigurations) +select_library_configurations(NVTT) + if (WIN32) - find_library(NVTT_LIBRARY_RELEASE nvtt PATH_SUFFIXES "Release.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) - find_library(NVTT_LIBRARY_DEBUG nvtt PATH_SUFFIXES "Debug.x64/lib" HINTS ${NVTT_SEARCH_DIRS}) - find_path(NVTT_DLL_PATH nvtt.dll PATH_SUFFIXES "Release.x64/bin" HINTS ${NVTT_SEARCH_DIRS}) - - include(SelectLibraryConfigurations) - select_library_configurations(NVTT) - find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARIES NVTT_DLL_PATH) else () - find_library(NVTT_BASE_LIBRARY nvtt PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) - find_library(NVTT_CORE_LIBRARY nvcore PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) - find_library(NVTT_IMAGE_LIBRARY nvimage PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) - find_library(NVTT_MATH_LIBRARY nvmath PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) - find_library(NVTT_THREAD_LIBRARY nvthread PATH_SUFFIXES "lib/static" HINTS ${NVTT_SEARCH_DIRS}) - - find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_BASE_LIBRARY NVTT_CORE_LIBRARY NVTT_IMAGE_LIBRARY NVTT_MATH_LIBRARY NVTT_THREAD_LIBRARY) - set(NVTT_LIBRARIES ${NVTT_BASE_LIBRARY} ${NVTT_CORE_LIBRARY} ${NVTT_IMAGE_LIBRARY} ${NVTT_MATH_LIBRARY} ${NVTT_THREAD_LIBRARY}) + find_package_handle_standard_args(NVTT DEFAULT_MSG NVTT_INCLUDE_DIRS NVTT_LIBRARIES) endif () diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt index cc1e3f4df2..85d3d8f1ae 100644 --- a/libraries/image/CMakeLists.txt +++ b/libraries/image/CMakeLists.txt @@ -8,5 +8,4 @@ add_dependency_external_projects(nvtt) find_package(NVTT REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) -message(${NVTT_DLL_PATH}) add_paths_to_fixup_libs(${NVTT_DLL_PATH}) From 06b3b3d5f47ca3f9472f7bd50e6c9f6cd3f48699 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 16:05:26 -0700 Subject: [PATCH 13/32] ad missing include dir for NVTT on win --- cmake/externals/nvtt/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index 0f45bc45c6..e8fd6e36db 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -16,6 +16,8 @@ if (NOT ANDROID) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static release library") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/Debug/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static debug library") From 202e933d8bfda31fe3183c1da18942eb3a5eb14f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 16:49:36 -0700 Subject: [PATCH 14/32] don't build, install, or configure nvtt on windows --- cmake/externals/nvtt/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index e8fd6e36db..b272fcf62d 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -11,6 +11,9 @@ if (NOT ANDROID) ${EXTERNAL_NAME} URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip URL_MD5 3ea6eeadbcc69071acf9c49ba565760e + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" LOG_DOWNLOAD 1 ) From 11fa2797b7d318ef03c0c26566d1dfcddabf1e70 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 17:07:47 -0700 Subject: [PATCH 15/32] force the release DLL path for NVTT on windows --- cmake/externals/nvtt/CMakeLists.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index b272fcf62d..4efd2a4fc0 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -20,11 +20,8 @@ if (NOT ANDROID) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") - - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static release library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/Debug/x64/nvtt.lib CACHE FILEPATH "Path to NVTT static debug library") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/$<$:Debug>$<$>:Release>/x64" CACHE PATH "Location of NVTT DLL") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT release library") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/Release>/x64" CACHE PATH "Location of NVTT release DLL") else () ExternalProject_Add( ${EXTERNAL_NAME} From 796804562616ce12821d9cc69042708ddaf46ece Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Apr 2017 17:29:57 -0700 Subject: [PATCH 16/32] update md5 for patched external nvtt --- cmake/externals/nvtt/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index 4efd2a4fc0..fcaf10330c 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -26,7 +26,7 @@ if (NOT ANDROID) ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip - URL_MD5 79842ea185c8c95aaa70cee91e77f032 + URL_MD5 81b8fa6a9ee3f986088eb6e2215d6a57 CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD 1 LOG_CONFIGURE 1 From d9a7615cc89ef9e16f0392a7a119361d7cf3c394 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 14 Apr 2017 17:52:44 -0700 Subject: [PATCH 17/32] Add compression support for skyboxes --- .../src/gpu/gl41/GL41BackendTexture.cpp | 14 ++- .../src/gpu/gl45/GL45BackendTexture.cpp | 30 +++-- libraries/gpu/src/gpu/Texture.cpp | 2 +- libraries/gpu/src/gpu/Texture.h | 1 + libraries/image/src/image/Image.cpp | 112 ++++++------------ libraries/image/src/image/Image.h | 4 +- tests/ktx/src/main.cpp | 2 +- 7 files changed, 77 insertions(+), 88 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 6811ef7020..ac5eab4738 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -108,7 +108,19 @@ void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const } } else if (GL_TEXTURE_CUBE_MAP == _target) { auto target = GLTexture::CUBE_FACE_LAYOUT[face]; - glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + + switch (internalFormat) { + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: + glCompressedTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + break; + default: + glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + break; + } } else { assert(false); } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 893e6412ea..1814be08d7 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -132,13 +132,29 @@ void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const break; } } else if (GL_TEXTURE_CUBE_MAP == _target) { - // DSA ARB does not work on AMD, so use EXT - // unless EXT is not available on the driver - if (glTextureSubImage2DEXT) { - auto target = GLTexture::CUBE_FACE_LAYOUT[face]; - glTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); - } else { - glTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, format, type, sourcePointer); + switch (internalFormat) { + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: + if (glCompressedTextureSubImage2DEXT) { + auto target = GLTexture::CUBE_FACE_LAYOUT[face]; + glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + } else { + glCompressedTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, internalFormat, sourceSize, sourcePointer); + } + break; + default: + // DSA ARB does not work on AMD, so use EXT + // unless EXT is not available on the driver + if (glTextureSubImage2DEXT) { + auto target = GLTexture::CUBE_FACE_LAYOUT[face]; + glTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); + } else { + glTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, format, type, sourcePointer); + } + break; } } else { Q_ASSERT(false); diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 6c92886864..1e212c01c7 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -752,7 +752,7 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector< boffset = 0; } - auto data = cubeTexture.accessStoredMipFace(0,face)->readData(); + auto data = cubeTexture.accessStoredMipFace(0, face)->readData(); if (data == nullptr) { continue; } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index f100b17b3b..898b63c73c 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -499,6 +499,7 @@ public: // For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them availalbe with the texture bool generateIrradiance(); const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; } + void overrideIrradiance(SHPointer irradiance) { _irradiance = irradiance; } bool isIrradianceValid() const { return _isIrradianceValid; } // Own sampler diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 18f549ebc7..d64601d4ac 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -219,53 +219,8 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val return image; } -void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, - const QImage& image, bool isLinear) { - if (image.hasAlphaChannel()) { - gpu::Semantic gpuSemantic; - gpu::Semantic mipSemantic; - if (isLinear) { - mipSemantic = gpu::BGRA; - gpuSemantic = gpu::RGBA; - } else { - mipSemantic = gpu::SBGRA; - gpuSemantic = gpu::SRGBA; - } - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpuSemantic); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, mipSemantic); - } else { - gpu::Semantic gpuSemantic; - gpu::Semantic mipSemantic; - if (isLinear) { - mipSemantic = gpu::RGB; - gpuSemantic = gpu::RGB; - } else { - mipSemantic = gpu::SRGB; - gpuSemantic = gpu::SRGB; - } - formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); - formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); - } -} - -void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) { -#if CPU_MIPMAPS - PROFILE_RANGE(resource_parse, "generateFaceMips"); - - - auto numMips = texture->getNumMips(); - for (uint16 level = 1; level < numMips; ++level) { - QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); - QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - texture->assignStoredMipFace(level, face, mipImage.byteCount(), mipImage.constBits()); - } -#else - texture->autoGenerateMips(-1); -#endif -} - struct MyOutputHandler : public nvtt::OutputHandler { - MyOutputHandler(gpu::Texture* texture) : _texture(texture) {} + MyOutputHandler(gpu::Texture* texture, int face) : _texture(texture), _face(face) {} virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { _size = size; @@ -281,7 +236,11 @@ struct MyOutputHandler : public nvtt::OutputHandler { return true; } virtual void endImage() { - _texture->assignStoredMip(_miplevel, _size, static_cast(_data)); + if (_face >= 0) { + _texture->assignStoredMipFace(_miplevel, _face, _size, static_cast(_data)); + } else { + _texture->assignStoredMip(_miplevel, _size, static_cast(_data)); + } free(_data); _data = nullptr; } @@ -291,6 +250,7 @@ struct MyOutputHandler : public nvtt::OutputHandler { gpu::Texture* _texture{ nullptr }; int _miplevel = 0; int _size = 0; + int _face = -1; }; struct MyErrorHandler : public nvtt::ErrorHandler { virtual void error(nvtt::Error e) override { @@ -298,7 +258,7 @@ struct MyErrorHandler : public nvtt::ErrorHandler { } }; -void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool alphaAsMask, bool grayscale, bool normalMap) { +void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool alphaAsMask, bool grayscale = false, bool normalMap = false, int face = -1) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); @@ -343,7 +303,7 @@ void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool al nvtt::OutputOptions outputOptions; outputOptions.setOutputHeader(false); - MyOutputHandler outputHandler(texture); + MyOutputHandler outputHandler(texture, face); outputOptions.setOutputHandler(&outputHandler); MyErrorHandler errorHandler; outputOptions.setErrorHandler(&errorHandler); @@ -359,7 +319,7 @@ void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool al #endif } -gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doGenerateMips, bool isStrict) { +gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict) { PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); bool validAlpha = false; bool alphaAsMask = true; @@ -391,10 +351,7 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag } theTexture->setUsage(usage.build()); theTexture->setStoredMipFormat(formatMip); - - if (doGenerateMips) { - generateMips(theTexture, image, validAlpha, alphaAsMask, false, false); - } + generateMips(theTexture, image, validAlpha, alphaAsMask, false, false); theTexture->setSource(srcImageName); } @@ -402,23 +359,23 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag } gpu::Texture* TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false, true); } gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false); } gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false); } gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false); } gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true); + return process2DTextureColorFromImage(srcImage, srcImageName, false); } @@ -892,7 +849,7 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { }; const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); -gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateMips, bool generateIrradiance) { +gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance) { PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage"); gpu::Texture* theTexture = nullptr; @@ -902,9 +859,8 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm image = image.convertToFormat(QImage::Format_ARGB32); } - gpu::Element formatGPU; - gpu::Element formatMip; - defineColorTexelFormats(formatGPU, formatMip, image, isLinear); + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; + gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_SRGBA; // Find the layout of the cubemap in the 2D image // Use the original image size since processSourceImage may have altered the size / aspect ratio @@ -943,22 +899,26 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm theTexture = gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - int f = 0; - for (auto& face : faces) { - theTexture->assignStoredMipFace(0, f, face.byteCount(), face.constBits()); - if (generateMips) { - generateFaceMips(theTexture, face, f); - } - f++; + + for (int face = 0; face < faces.size(); ++face) { + generateMips(theTexture, faces[face], true, false, false, false, face); } // Generate irradiance while we are at it if (generateIrradiance) { - PROFILE_RANGE(resource_parse, "generateIrradiance"); - theTexture->generateIrradiance(); - } + auto irradianceTexture = gpu::Texture::createCube(gpu::Element::COLOR_SRGBA_32, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); + irradianceTexture->setSource(srcImageName); + irradianceTexture->setStoredMipFormat(gpu::Element::COLOR_SRGBA_32); + for (int face = 0; face < faces.size(); ++face) { + irradianceTexture->assignStoredMipFace(0, face, faces[face].byteCount(), faces[face].constBits()); + } - theTexture->setSource(srcImageName); + PROFILE_RANGE(resource_parse, "generateIrradiance"); + irradianceTexture->generateIrradiance(); + + auto irradiance = irradianceTexture->getIrradiance(); + theTexture->overrideIrradiance(irradiance); + } } } @@ -966,11 +926,11 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm } gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true); + return processCubeTextureColorFromImage(srcImage, srcImageName, false, true); } gpu::Texture* TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, false); + return processCubeTextureColorFromImage(srcImage, srcImageName, false, false); } } // namespace image \ No newline at end of file diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 5c3becf2af..391f871542 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -45,8 +45,8 @@ gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::str const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); void defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, const QImage& srcImage, bool isLinear); -gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateMips, bool isStrict = false); -gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateMips, bool generateIrradiance); +gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict = false); +gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance); } // namespace TextureUsage diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index bd560a20f9..2be22a00c6 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -95,7 +95,7 @@ int main(int argc, char** argv) { QLoggingCategory::setFilterRules(LOG_FILTER_RULES); QImage image(TEST_IMAGE); - gpu::Texture* testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, false, true); + gpu::Texture* testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, true); auto ktxMemory = gpu::Texture::serialize(*testTexture); { From 63e564c1780511ed2b61cad52962ef402347b3c3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 16 Apr 2017 13:39:23 -0700 Subject: [PATCH 18/32] Add source hash to KTX metadata --- libraries/gpu/src/gpu/Texture.h | 3 +++ libraries/gpu/src/gpu/Texture_ktx.cpp | 7 +++++- libraries/image/src/image/Image.cpp | 25 ++++++------------- libraries/image/src/image/Image.h | 4 +-- .../src/model-networking/TextureCache.cpp | 9 +++---- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 898b63c73c..34c4dd6f52 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -452,6 +452,8 @@ public: // For convenience assign a source name const std::string& source() const { return _source; } void setSource(const std::string& source) { _source = source; } + const std::string& sourceHash() const { return _sourceHash; } + void setSourceHash(const std::string& sourceHash) { _sourceHash = sourceHash; } // Potentially change the minimum mip (mostly for debugging purpose) bool setMinMip(uint16 newMinMip); @@ -536,6 +538,7 @@ protected: std::weak_ptr _fallback; // Not strictly necessary, but incredibly useful for debugging std::string _source; + std::string _sourceHash; std::unique_ptr< Storage > _storage; Stamp _stamp { 0 }; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index dc8e69d302..d8dd897101 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -23,6 +23,7 @@ struct GPUKTXPayload { Texture::Usage _usage; TextureUsageType _usageType; + static std::string KEY; static bool isGPUKTX(const ktx::KeyValue& val) { return (val._key.compare(KEY) == 0); @@ -161,7 +162,11 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { keyval._usage = texture.getUsage(); keyval._usageType = texture.getUsageType(); ktx::KeyValues keyValues; - keyValues.emplace_back(ktx::KeyValue(GPUKTXPayload::KEY, sizeof(GPUKTXPayload), (ktx::Byte*) &keyval)); + keyValues.emplace_back(ktx::KeyValue(GPUKTXPayload::KEY, sizeof(GPUKTXPayload), (ktx::Byte*) &keyval)); + + static const std::string SOURCE_HASH_KEY = "hifi.sourceHash"; + auto hash = texture.sourceHash(); + keyValues.emplace_back(ktx::KeyValue(SOURCE_HASH_KEY, hash.size(), (ktx::Byte*) hash.c_str())); auto ktxBuffer = ktx::KTX::create(header, images, keyValues); #if 0 diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index d64601d4ac..4c2d1b0857 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -25,8 +25,6 @@ using namespace gpu; -// FIXME: Declare this to enable compression -//#define COMPRESS_TEXTURES #define CPU_MIPMAPS 1 static const glm::uvec2 SPARSE_PAGE_SIZE(128); @@ -114,10 +112,9 @@ TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& } } -gpu::Texture* processImage(const QByteArray& content, const QUrl& url, const std::string& hash, int maxNumPixels, const TextureLoader& loader) { +gpu::Texture* processImage(const QByteArray& content, const std::string& filename, int maxNumPixels, gpu::TextureType textureType) { // Help the QImage loader by extracting the image file format from the url filename ext. // Some tga are not created properly without it. - auto filename = url.fileName().toStdString(); auto filenameExtension = filename.substr(filename.find_last_of('.') + 1); QImage image = QImage::fromData(content, filenameExtension.c_str()); int imageWidth = image.width(); @@ -126,7 +123,7 @@ gpu::Texture* processImage(const QByteArray& content, const QUrl& url, const std // Validate that the image loaded if (imageWidth == 0 || imageHeight == 0 || image.format() == QImage::Format_Invalid) { QString reason(filenameExtension.empty() ? "" : "(no file extension)"); - qCWarning(imagelogging) << "Failed to load" << url << reason; + qCWarning(imagelogging) << "Failed to load" << filename.c_str() << reason; return nullptr; } @@ -139,12 +136,15 @@ gpu::Texture* processImage(const QByteArray& content, const QUrl& url, const std imageHeight = (int)(scaleFactor * (float)imageHeight + 0.5f); QImage newImage = image.scaled(QSize(imageWidth, imageHeight), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); image.swap(newImage); - qCDebug(imagelogging).nospace() << "Downscaled " << url << " (" << + qCDebug(imagelogging).nospace() << "Downscaled " << filename.c_str() << " (" << QSize(originalWidth, originalHeight) << " to " << QSize(imageWidth, imageHeight) << ")"; } - return loader(image, url.toString().toStdString()); + auto loader = getTextureLoaderForType(textureType); + auto texture = loader(image, filename); + + return texture; } @@ -352,7 +352,6 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag theTexture->setUsage(usage.build()); theTexture->setStoredMipFormat(formatMip); generateMips(theTexture, image, validAlpha, alphaAsMask, false, false); - theTexture->setSource(srcImageName); } return theTexture; @@ -399,8 +398,6 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); generateMips(theTexture, image, false, false, false, true); - - theTexture->setSource(srcImageName); } return theTexture; @@ -488,8 +485,6 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); generateMips(theTexture, image, false, false, false, true); - - theTexture->setSource(srcImageName); } return theTexture; @@ -519,8 +514,6 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); generateMips(theTexture, image, false, false, true, false); - - theTexture->setSource(srcImageName); } return theTexture; @@ -554,8 +547,6 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); generateMips(theTexture, image, false, false, true, false); - - theTexture->setSource(srcImageName); } return theTexture; @@ -586,8 +577,6 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); generateMips(theTexture, image, false, false, true, false); - - theTexture->setSource(srcImageName); } return theTexture; diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 391f871542..8a509e96d0 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -18,7 +18,6 @@ class QByteArray; class QImage; -class QUrl; namespace image { @@ -26,7 +25,7 @@ using TextureLoader = std::functiongetTextureType()); - texture.reset(image::processImage(_content, _url, hash, _maxNumPixels, loader)); - texture->setSource(_url.toString().toStdString()); - if (texture) { - texture->setFallbackTexture(networkTexture->getFallbackTexture()); - } + texture.reset(image::processImage(_content, _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType())); + texture->setSourceHash(hash); + texture->setFallbackTexture(networkTexture->getFallbackTexture()); } // Save the image into a KTXFile From ad16a935e9b4ddc03343d91e1bf3e191d8a05465 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 16 Apr 2017 14:34:39 -0700 Subject: [PATCH 19/32] Texture::create returns shared pointer --- interface/src/ui/ApplicationOverlay.cpp | 6 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 5 +- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 5 +- .../src/RenderableWebEntityItem.cpp | 2 +- libraries/gpu/src/gpu/Texture.cpp | 22 +++--- libraries/gpu/src/gpu/Texture.h | 18 ++--- libraries/gpu/src/gpu/Texture_ktx.cpp | 2 +- libraries/image/src/image/Image.cpp | 78 +++++++++---------- libraries/image/src/image/Image.h | 32 ++++---- .../src/model-networking/TextureCache.cpp | 21 +++-- .../src/AmbientOcclusionEffect.cpp | 4 +- .../render-utils/src/AntialiasingEffect.cpp | 2 +- .../render-utils/src/DeferredFramebuffer.cpp | 10 +-- .../src/DeferredLightingEffect.cpp | 4 +- .../render-utils/src/RenderForwardTask.cpp | 4 +- .../render-utils/src/SubsurfaceScattering.cpp | 6 +- .../render-utils/src/SurfaceGeometryPass.cpp | 18 ++--- libraries/render-utils/src/text/Font.cpp | 4 +- libraries/render/src/render/BlurTask.cpp | 4 +- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 2 +- tests/ktx/src/main.cpp | 2 +- 22 files changed, 125 insertions(+), 128 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 7239e49d89..a99fe002ee 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -94,7 +94,7 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { PROFILE_RANGE(app, __FUNCTION__); if (!_uiTexture) { - _uiTexture = gpu::TexturePointer(gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda())); + _uiTexture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _uiTexture->setSource(__FUNCTION__); } // Once we move UI rendering and screen rendering to different @@ -207,13 +207,13 @@ void ApplicationOverlay::buildFramebufferObject() { auto width = uiSize.x; auto height = uiSize.y; if (!_overlayFramebuffer->getDepthStencilBuffer()) { - auto overlayDepthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(DEPTH_FORMAT, width, height, gpu::Texture::SINGLE_MIP, DEFAULT_SAMPLER)); + auto overlayDepthTexture = gpu::Texture::createRenderBuffer(DEPTH_FORMAT, width, height, gpu::Texture::SINGLE_MIP, DEFAULT_SAMPLER); _overlayFramebuffer->setDepthStencilBuffer(overlayDepthTexture, DEPTH_FORMAT); } if (!_overlayFramebuffer->getRenderBuffer(0)) { const gpu::Sampler OVERLAY_SAMPLER(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); - auto colorBuffer = gpu::TexturePointer(gpu::Texture::createRenderBuffer(COLOR_FORMAT, width, height, gpu::Texture::SINGLE_MIP, OVERLAY_SAMPLER)); + auto colorBuffer = gpu::Texture::createRenderBuffer(COLOR_FORMAT, width, height, gpu::Texture::SINGLE_MIP, OVERLAY_SAMPLER); _overlayFramebuffer->setRenderBuffer(0, colorBuffer); } } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index f80589e5a1..24b12dacf0 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -298,7 +298,7 @@ void Web3DOverlay::render(RenderArgs* args) { if (!_texture) { auto webSurface = _webSurface; - _texture = gpu::TexturePointer(gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda())); + _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _texture->setSource(__FUNCTION__); } OffscreenQmlSurface::TextureAndFence newTextureAndFence; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index f5d335adea..306db98b35 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -354,12 +354,11 @@ void OpenGLDisplayPlugin::customizeContext() { } if ((image.width() > 0) && (image.height() > 0)) { - cursorData.texture.reset( - gpu::Texture::createStrict( + cursorData.texture = gpu::Texture::createStrict( gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); cursorData.texture->setSource("cursor texture"); auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); cursorData.texture->setUsage(usage.build()); diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 4c9e53c037..cab96c258b 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -295,12 +295,11 @@ void HmdDisplayPlugin::internalPresent() { image = image.mirrored(); image = image.convertToFormat(QImage::Format_RGBA8888); if (!_previewTexture) { - _previewTexture.reset( - gpu::Texture::createStrict( + _previewTexture = gpu::Texture::createStrict( gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); _previewTexture->setSource("HMD Preview Texture"); _previewTexture->setUsage(gpu::Texture::Usage::Builder().withColor().build()); _previewTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 109c4cbfe9..0d286c46eb 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -216,7 +216,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { if (!_texture) { auto webSurface = _webSurface; - _texture = gpu::TexturePointer(gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda())); + _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _texture->setSource(__FUNCTION__); } OffscreenQmlSurface::TextureAndFence newTextureAndFence; diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 1e212c01c7..ebde9d4d27 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -212,8 +212,8 @@ void Texture::MemoryStorage::assignMipFaceData(uint16 level, uint8 face, const s } } -Texture* Texture::createExternal(const ExternalRecycler& recycler, const Sampler& sampler) { - Texture* tex = new Texture(TextureUsageType::EXTERNAL); +TexturePointer Texture::createExternal(const ExternalRecycler& recycler, const Sampler& sampler) { + TexturePointer tex = std::make_shared(TextureUsageType::EXTERNAL); tex->_type = TEX_2D; tex->_maxMipLevel = 0; tex->_sampler = sampler; @@ -221,36 +221,36 @@ Texture* Texture::createExternal(const ExternalRecycler& recycler, const Sampler return tex; } -Texture* Texture::createRenderBuffer(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips, const Sampler& sampler) { +TexturePointer Texture::createRenderBuffer(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::RENDERBUFFER, TEX_2D, texelFormat, width, height, 1, 1, 0, numMips, sampler); } -Texture* Texture::create1D(const Element& texelFormat, uint16 width, uint16 numMips, const Sampler& sampler) { +TexturePointer Texture::create1D(const Element& texelFormat, uint16 width, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::RESOURCE, TEX_1D, texelFormat, width, 1, 1, 1, 0, numMips, sampler); } -Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips, const Sampler& sampler) { +TexturePointer Texture::create2D(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::RESOURCE, TEX_2D, texelFormat, width, height, 1, 1, 0, numMips, sampler); } -Texture* Texture::createStrict(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips, const Sampler& sampler) { +TexturePointer Texture::createStrict(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::STRICT_RESOURCE, TEX_2D, texelFormat, width, height, 1, 1, 0, numMips, sampler); } -Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numMips, const Sampler& sampler) { +TexturePointer Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::RESOURCE, TEX_3D, texelFormat, width, height, depth, 1, 0, numMips, sampler); } -Texture* Texture::createCube(const Element& texelFormat, uint16 width, uint16 numMips, const Sampler& sampler) { +TexturePointer Texture::createCube(const Element& texelFormat, uint16 width, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::RESOURCE, TEX_CUBE, texelFormat, width, width, 1, 1, 0, numMips, sampler); } -Texture* Texture::create(TextureUsageType usageType, Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, uint16 numMips, const Sampler& sampler) +TexturePointer Texture::create(TextureUsageType usageType, Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, uint16 numMips, const Sampler& sampler) { - Texture* tex = new Texture(usageType); + TexturePointer tex = std::make_shared(usageType); tex->_storage.reset(new MemoryStorage()); tex->_type = type; - tex->_storage->assignTexture(tex); + tex->_storage->assignTexture(tex.get()); tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices, numMips); tex->_sampler = sampler; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 34c4dd6f52..9250221708 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -345,13 +345,13 @@ public: static const uint16 MAX_NUM_MIPS = 0; static const uint16 SINGLE_MIP = 1; - static Texture* create1D(const Element& texelFormat, uint16 width, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); - static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); - static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); - static Texture* createCube(const Element& texelFormat, uint16 width, uint16 numMips = 1, const Sampler& sampler = Sampler()); - static Texture* createRenderBuffer(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); - static Texture* createStrict(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); - static Texture* createExternal(const ExternalRecycler& recycler, const Sampler& sampler = Sampler()); + static TexturePointer create1D(const Element& texelFormat, uint16 width, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); + static TexturePointer create2D(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); + static TexturePointer create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); + static TexturePointer createCube(const Element& texelFormat, uint16 width, uint16 numMips = 1, const Sampler& sampler = Sampler()); + static TexturePointer createRenderBuffer(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); + static TexturePointer createStrict(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); + static TexturePointer createExternal(const ExternalRecycler& recycler, const Sampler& sampler = Sampler()); // After the texture has been created, it should be defined bool isDefined() const { return _defined; } @@ -522,7 +522,7 @@ public: // Textures can be serialized directly to ktx data file, here is how static ktx::KTXUniquePointer serialize(const Texture& texture); - static Texture* unserialize(const std::string& ktxFile, TextureUsageType usageType = TextureUsageType::RESOURCE, Usage usage = Usage(), const Sampler::Desc& sampler = Sampler::Desc()); + static TexturePointer unserialize(const std::string& ktxFile, TextureUsageType usageType = TextureUsageType::RESOURCE, Usage usage = Usage(), const Sampler::Desc& sampler = Sampler::Desc()); static bool evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header); static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat); @@ -573,7 +573,7 @@ protected: bool _isIrradianceValid = false; bool _defined = false; - static Texture* create(TextureUsageType usageType, Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, uint16 numMips, const Sampler& sampler); + static TexturePointer create(TextureUsageType usageType, Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, uint16 numMips, const Sampler& sampler); Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, uint16 numMips); }; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index d8dd897101..772b8107ea 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -198,7 +198,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { return ktxBuffer; } -Texture* Texture::unserialize(const std::string& ktxfile, TextureUsageType usageType, Usage usage, const Sampler::Desc& sampler) { +TexturePointer Texture::unserialize(const std::string& ktxfile, TextureUsageType usageType, Usage usage, const Sampler::Desc& sampler) { std::unique_ptr ktxPointer = ktx::KTX::create(ktx::StoragePointer { new storage::FileStorage(ktxfile.c_str()) }); if (!ktxPointer) { return nullptr; diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 4c2d1b0857..9f6e5bcb68 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -112,7 +112,7 @@ TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& } } -gpu::Texture* processImage(const QByteArray& content, const std::string& filename, int maxNumPixels, gpu::TextureType textureType) { +gpu::TexturePointer processImage(const QByteArray& content, const std::string& filename, int maxNumPixels, gpu::TextureType textureType) { // 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); @@ -222,20 +222,20 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val struct MyOutputHandler : public nvtt::OutputHandler { MyOutputHandler(gpu::Texture* texture, int face) : _texture(texture), _face(face) {} - virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { + virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) override { _size = size; _miplevel = miplevel; _data = static_cast(malloc(size)); _current = _data; } - virtual bool writeData(const void* data, int size) { + virtual bool writeData(const void* data, int size) override { assert(_current + size <= _data + _size); memcpy(_current, data, size); _current += size; return true; } - virtual void endImage() { + virtual void endImage() override { if (_face >= 0) { _texture->assignStoredMipFace(_miplevel, _face, _size, static_cast(_data)); } else { @@ -319,13 +319,13 @@ void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool al #endif } -gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict) { +gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict) { PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); bool validAlpha = false; bool alphaAsMask = true; QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); - gpu::Texture* theTexture = nullptr; + gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatGPU; @@ -337,9 +337,9 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag gpu::Element formatMip = formatGPU; if (isStrict) { - theTexture = (gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture = gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); } else { - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); } theTexture->setSource(srcImageName); auto usage = gpu::Texture::Usage::Builder().withColor(); @@ -351,34 +351,34 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag } theTexture->setUsage(usage.build()); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture, image, validAlpha, alphaAsMask, false, false); + generateMips(theTexture.get(), image, validAlpha, alphaAsMask, false, false); } return theTexture; } -gpu::Texture* TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { return process2DTextureColorFromImage(srcImage, srcImageName, false, true); } -gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { return process2DTextureColorFromImage(srcImage, srcImageName, false); } -gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { return process2DTextureColorFromImage(srcImage, srcImageName, false); } -gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { return process2DTextureColorFromImage(srcImage, srcImageName, false); } -gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { return process2DTextureColorFromImage(srcImage, srcImageName, false); } -gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { PROFILE_RANGE(resource_parse, "createNormalTextureFromNormalImage"); QImage image = processSourceImage(srcImage, false); @@ -388,16 +388,16 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src } - gpu::Texture* theTexture = nullptr; + gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture, image, false, false, false, true); + generateMips(theTexture.get(), image, false, false, false, true); } return theTexture; @@ -415,7 +415,7 @@ double mapComponent(double sobelValue) { return (sobelValue + 1.0) * factor; } -gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) { PROFILE_RANGE(resource_parse, "createNormalTextureFromBumpImage"); QImage image = processSourceImage(srcImage, false); @@ -474,23 +474,23 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm } } - gpu::Texture* theTexture = nullptr; + gpu::TexturePointer theTexture = nullptr; if ((result.width() > 0) && (result.height() > 0)) { gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; - theTexture = (gpu::Texture::create2D(formatGPU, result.width(), result.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture = gpu::Texture::create2D(formatGPU, result.width(), result.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture, image, false, false, false, true); + generateMips(theTexture.get(), image, false, false, false, true); } return theTexture; } -gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { PROFILE_RANGE(resource_parse, "createRoughnessTextureFromImage"); QImage image = processSourceImage(srcImage, false); if (!image.hasAlphaChannel()) { @@ -505,21 +505,21 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma image = image.convertToFormat(QImage::Format_ARGB32); - gpu::Texture* theTexture = nullptr; + gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture, image, false, false, true, false); + generateMips(theTexture.get(), image, false, false, true, false); } return theTexture; } -gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) { PROFILE_RANGE(resource_parse, "createRoughnessTextureFromGlossImage"); QImage image = processSourceImage(srcImage, false); if (!image.hasAlphaChannel()) { @@ -537,22 +537,22 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s image = image.convertToFormat(QImage::Format_ARGB32); - gpu::Texture* theTexture = nullptr; + gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture, image, false, false, true, false); + generateMips(theTexture.get(), image, false, false, true, false); } return theTexture; } -gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { PROFILE_RANGE(resource_parse, "createMetallicTextureFromImage"); QImage image = processSourceImage(srcImage, false); if (!image.hasAlphaChannel()) { @@ -567,16 +567,16 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag image = image.convertToFormat(QImage::Format_ARGB32); - gpu::Texture* theTexture = nullptr; + gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture, image, false, false, true, false); + generateMips(theTexture.get(), image, false, false, true, false); } return theTexture; @@ -838,10 +838,10 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { }; const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); -gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance) { +gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance) { PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage"); - gpu::Texture* theTexture = nullptr; + gpu::TexturePointer theTexture = nullptr; if ((srcImage.width() > 0) && (srcImage.height() > 0)) { QImage image = processSourceImage(srcImage, true); if (image.format() != QImage::Format_ARGB32) { @@ -890,7 +890,7 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm theTexture->setStoredMipFormat(formatMip); for (int face = 0; face < faces.size(); ++face) { - generateMips(theTexture, faces[face], true, false, false, false, face); + generateMips(theTexture.get(), faces[face], true, false, false, false, face); } // Generate irradiance while we are at it @@ -914,11 +914,11 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm return theTexture; } -gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { return processCubeTextureColorFromImage(srcImage, srcImageName, false, true); } -gpu::Texture* TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { +gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { return processCubeTextureColorFromImage(srcImage, srcImageName, false, false); } diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 8a509e96d0..ba0b88ee43 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -21,30 +21,30 @@ class QImage; namespace image { -using TextureLoader = std::function; +using TextureLoader = std::function; TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& options = QVariantMap()); -gpu::Texture* processImage(const QByteArray& content, const std::string& url, int maxNumPixels, gpu::TextureType textureType); +gpu::TexturePointer processImage(const QByteArray& content, const std::string& url, int maxNumPixels, gpu::TextureType textureType); namespace TextureUsage { -gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createStrict2DTextureFromImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createAlbedoTextureFromImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createEmissiveTextureFromImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createRoughnessTextureFromImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createRoughnessTextureFromGlossImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createMetallicTextureFromImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); -gpu::Texture* createCubeTextureFromImageWithoutIrradiance(const QImage& image, const std::string& srcImageName); -gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer create2DTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createStrict2DTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createAlbedoTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createEmissiveTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createRoughnessTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createRoughnessTextureFromGlossImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createMetallicTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createCubeTextureFromImageWithoutIrradiance(const QImage& image, const std::string& srcImageName); +gpu::TexturePointer createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); -gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict = false); -gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance); +gpu::TexturePointer process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict = false); +gpu::TexturePointer processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance); } // namespace TextureUsage diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 23a85d6eb5..1731ffb132 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -111,7 +111,7 @@ const gpu::TexturePointer& TextureCache::getPermutationNormalTexture() { data[i + 2] = ((randvec.z + 1.0f) / 2.0f) * 255.0f; } - _permutationNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB), 256, 2)); + _permutationNormalTexture = gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB), 256, 2); _permutationNormalTexture->setStoredMipFormat(_permutationNormalTexture->getTexelFormat()); _permutationNormalTexture->assignStoredMip(0, sizeof(data), data); } @@ -125,7 +125,7 @@ const unsigned char OPAQUE_BLACK[] = { 0x00, 0x00, 0x00, 0xFF }; const gpu::TexturePointer& TextureCache::getWhiteTexture() { if (!_whiteTexture) { - _whiteTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); + _whiteTexture = gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1); _whiteTexture->setSource("TextureCache::_whiteTexture"); _whiteTexture->setStoredMipFormat(_whiteTexture->getTexelFormat()); _whiteTexture->assignStoredMip(0, sizeof(OPAQUE_WHITE), OPAQUE_WHITE); @@ -135,7 +135,7 @@ const gpu::TexturePointer& TextureCache::getWhiteTexture() { const gpu::TexturePointer& TextureCache::getGrayTexture() { if (!_grayTexture) { - _grayTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); + _grayTexture = gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1); _grayTexture->setSource("TextureCache::_grayTexture"); _grayTexture->setStoredMipFormat(_grayTexture->getTexelFormat()); _grayTexture->assignStoredMip(0, sizeof(OPAQUE_GRAY), OPAQUE_GRAY); @@ -145,7 +145,7 @@ const gpu::TexturePointer& TextureCache::getGrayTexture() { const gpu::TexturePointer& TextureCache::getBlueTexture() { if (!_blueTexture) { - _blueTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); + _blueTexture = gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1); _blueTexture->setSource("TextureCache::_blueTexture"); _blueTexture->setStoredMipFormat(_blueTexture->getTexelFormat()); _blueTexture->assignStoredMip(0, sizeof(OPAQUE_BLUE), OPAQUE_BLUE); @@ -155,7 +155,7 @@ const gpu::TexturePointer& TextureCache::getBlueTexture() { const gpu::TexturePointer& TextureCache::getBlackTexture() { if (!_blackTexture) { - _blackTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); + _blackTexture = gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1); _blackTexture->setSource("TextureCache::_blackTexture"); _blackTexture->setStoredMipFormat(_blackTexture->getTexelFormat()); _blackTexture->assignStoredMip(0, sizeof(OPAQUE_BLACK), OPAQUE_BLACK); @@ -410,7 +410,7 @@ void ImageReader::read() { if (!texture) { KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash); if (ktxFile) { - texture.reset(gpu::Texture::unserialize(ktxFile->getFilepath())); + texture = gpu::Texture::unserialize(ktxFile->getFilepath()); if (texture) { texture = textureCache->cacheTextureByHash(hash, texture); } @@ -432,7 +432,7 @@ void ImageReader::read() { gpu::TexturePointer texture; { PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0); - texture.reset(image::processImage(_content, _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType())); + texture = image::processImage(_content, _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType()); texture->setSourceHash(hash); texture->setFallbackTexture(networkTexture->getFallbackTexture()); } @@ -444,13 +444,12 @@ void ImageReader::read() { if (memKtx) { const char* data = reinterpret_cast(memKtx->_storage->data()); size_t length = memKtx->_storage->size(); - KTXFilePointer file; auto& ktxCache = textureCache->_ktxCache; - if (!memKtx || !(file = ktxCache.writeFile(data, KTXCache::Metadata(hash, length)))) { + networkTexture->_file = ktxCache.writeFile(data, KTXCache::Metadata(hash, length)); + if (!networkTexture->_file) { qCWarning(modelnetworking) << _url << "file cache failed"; } else { - networkTexture->_file = file; - texture->setKtxBacking(file->getFilepath()); + texture->setKtxBacking(networkTexture->_file->getFilepath()); } } else { qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 9f4a71ef08..83753131c8 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -74,11 +74,11 @@ void AmbientOcclusionFramebuffer::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; - _occlusionTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _occlusionTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); _occlusionFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion")); _occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture); - _occlusionBlurredTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _occlusionBlurredTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); _occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusionBlurred")); _occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture); } diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 9a81320416..cd378d4e5b 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -52,7 +52,7 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { _antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing")); auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get()->getLightingTexture()->getTexelFormat(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - _antialiasingTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); + _antialiasingTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); } diff --git a/libraries/render-utils/src/DeferredFramebuffer.cpp b/libraries/render-utils/src/DeferredFramebuffer.cpp index 5d345f0851..64ea8f0342 100644 --- a/libraries/render-utils/src/DeferredFramebuffer.cpp +++ b/libraries/render-utils/src/DeferredFramebuffer.cpp @@ -53,9 +53,9 @@ void DeferredFramebuffer::allocate() { auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - _deferredColorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); - _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); - _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); + _deferredColorTexture = gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); + _deferredNormalTexture = gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); + _deferredSpecularTexture = gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture); _deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture); @@ -65,7 +65,7 @@ void DeferredFramebuffer::allocate() { auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format if (!_primaryDepthTexture) { - _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); + _primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); } _deferredFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); @@ -75,7 +75,7 @@ void DeferredFramebuffer::allocate() { auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR); - _lightingTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); + _lightingTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, gpu::Texture::SINGLE_MIP, defaultSampler); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("lighting")); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 34fd481c44..93a176f4f3 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -496,14 +496,14 @@ void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, g auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - auto primaryColorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler)); + auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _primaryFramebuffer->setRenderBuffer(0, primaryColorTexture); auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format - auto primaryDepthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler)); + auto primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _primaryFramebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat); } diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 46a7128fee..84514eeb1a 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -75,11 +75,11 @@ void PrepareFramebuffer::run(const RenderContextPointer& renderContext, auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - auto colorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler)); + auto colorTexture = gpu::Texture::create2D(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _framebuffer->setRenderBuffer(0, colorTexture); auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format - auto depthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler)); + auto depthTexture = gpu::Texture::create2D(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); } diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index c92acc11ad..40b3c85675 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -414,7 +414,7 @@ gpu::TexturePointer SubsurfaceScatteringResource::generateScatteringProfile(Rend const int PROFILE_RESOLUTION = 512; // const auto pixelFormat = gpu::Element::COLOR_SRGBA_32; const auto pixelFormat = gpu::Element::COLOR_R11G11B10; - auto profileMap = gpu::TexturePointer(gpu::Texture::createRenderBuffer(pixelFormat, PROFILE_RESOLUTION, 1, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); + auto profileMap = gpu::Texture::createRenderBuffer(pixelFormat, PROFILE_RESOLUTION, 1, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); profileMap->setSource("Generated Scattering Profile"); diffuseProfileGPU(profileMap, args); return profileMap; @@ -425,7 +425,7 @@ gpu::TexturePointer SubsurfaceScatteringResource::generatePreIntegratedScatterin const int TABLE_RESOLUTION = 512; // const auto pixelFormat = gpu::Element::COLOR_SRGBA_32; const auto pixelFormat = gpu::Element::COLOR_R11G11B10; - auto scatteringLUT = gpu::TexturePointer(gpu::Texture::createRenderBuffer(pixelFormat, TABLE_RESOLUTION, TABLE_RESOLUTION, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); + auto scatteringLUT = gpu::Texture::createRenderBuffer(pixelFormat, TABLE_RESOLUTION, TABLE_RESOLUTION, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); //diffuseScatter(scatteringLUT); scatteringLUT->setSource("Generated pre-integrated scattering"); diffuseScatterGPU(profile, scatteringLUT, args); @@ -434,7 +434,7 @@ gpu::TexturePointer SubsurfaceScatteringResource::generatePreIntegratedScatterin gpu::TexturePointer SubsurfaceScatteringResource::generateScatteringSpecularBeckmann(RenderArgs* args) { const int SPECULAR_RESOLUTION = 256; - auto beckmannMap = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, SPECULAR_RESOLUTION, SPECULAR_RESOLUTION, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP))); + auto beckmannMap = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, SPECULAR_RESOLUTION, SPECULAR_RESOLUTION, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); beckmannMap->setSource("Generated beckmannMap"); computeSpecularBeckmannGPU(beckmannMap, args); return beckmannMap; diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index 164aca0624..ef50960b7d 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -72,19 +72,19 @@ void LinearDepthFramebuffer::allocate() { auto height = _frameSize.y; // For Linear Depth: - _linearDepthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), width, height, gpu::Texture::SINGLE_MIP, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _linearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), width, height, gpu::Texture::SINGLE_MIP, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); _linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth")); _linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture); _linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat()); // For Downsampling: const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = 5; - _halfLinearDepthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), _halfFrameSize.x, _halfFrameSize.y, HALF_LINEAR_DEPTH_MAX_MIP_LEVEL, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _halfLinearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), _halfFrameSize.x, _halfFrameSize.y, HALF_LINEAR_DEPTH_MAX_MIP_LEVEL, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); - _halfNormalTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _halfFrameSize.x, _halfFrameSize.y, gpu::Texture::SINGLE_MIP, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _halfNormalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _halfFrameSize.x, _halfFrameSize.y, gpu::Texture::SINGLE_MIP, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); _downsampleFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("halfLinearDepth")); _downsampleFramebuffer->setRenderBuffer(0, _halfLinearDepthTexture); @@ -304,15 +304,15 @@ void SurfaceGeometryFramebuffer::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; - _curvatureTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _curvatureTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); _curvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("surfaceGeometry::curvature")); _curvatureFramebuffer->setRenderBuffer(0, _curvatureTexture); - _lowCurvatureTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _lowCurvatureTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); _lowCurvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("surfaceGeometry::lowCurvature")); _lowCurvatureFramebuffer->setRenderBuffer(0, _lowCurvatureTexture); - _blurringTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _blurringTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); _blurringFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("surfaceGeometry::blurring")); _blurringFramebuffer->setRenderBuffer(0, _blurringTexture); } diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index 00fcabd7da..c6a7da3a1a 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -207,8 +207,8 @@ void Font::read(QIODevice& in) { formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::BGRA); } - _texture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::SINGLE_MIP, - gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR))); + _texture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::SINGLE_MIP, + gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR)); _texture->setStoredMipFormat(formatMip); _texture->assignStoredMip(0, image.byteCount(), image.constBits()); } diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 2fc7dc0ea0..0a6b3d16fc 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -108,7 +108,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra // _blurredFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat()); //} auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); - auto blurringTarget = gpu::TexturePointer(gpu::Texture::create2D(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler)); + auto blurringTarget = gpu::Texture::create2D(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); _blurredFramebuffer->setRenderBuffer(0, blurringTarget); } @@ -131,7 +131,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra _outputFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat()); }*/ auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); - auto blurringTarget = gpu::TexturePointer(gpu::Texture::create2D(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler)); + auto blurringTarget = gpu::Texture::create2D(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); _outputFramebuffer->setRenderBuffer(0, blurringTarget); } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 585a0d00ef..8105de7a13 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -495,7 +495,7 @@ void OpenVrDisplayPlugin::customizeContext() { _compositeInfos[0].texture = _compositeFramebuffer->getRenderBuffer(0); for (size_t i = 0; i < COMPOSITING_BUFFER_SIZE; ++i) { if (0 != i) { - _compositeInfos[i].texture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _renderTargetSize.x, _renderTargetSize.y, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT))); + _compositeInfos[i].texture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _renderTargetSize.x, _renderTargetSize.y, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT)); } _compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture); } diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index 2be22a00c6..41a0586df2 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -95,7 +95,7 @@ int main(int argc, char** argv) { QLoggingCategory::setFilterRules(LOG_FILTER_RULES); QImage image(TEST_IMAGE); - gpu::Texture* testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, true); + gpu::TexturePointer testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, true); auto ktxMemory = gpu::Texture::serialize(*testTexture); { From fc1b920341022d24ee3e18728fbdad3d0c8d5349 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 17 Apr 2017 16:37:53 -0700 Subject: [PATCH 20/32] Add ability to disable texture compression --- libraries/image/src/image/Image.cpp | 171 +++++++++++++----- libraries/image/src/image/Image.h | 4 +- libraries/image/src/image/ImageLogging.cpp | 2 +- .../src/model-networking/TextureCache.cpp | 12 +- tests/ktx/src/main.cpp | 2 +- 5 files changed, 143 insertions(+), 48 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 9f6e5bcb68..9e73aad0bf 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -26,6 +26,7 @@ using namespace gpu; #define CPU_MIPMAPS 1 +#define COMPRESSED_TEXTURES 1 static const glm::uvec2 SPARSE_PAGE_SIZE(128); static const glm::uvec2 MAX_TEXTURE_SIZE(4096); @@ -122,8 +123,8 @@ gpu::TexturePointer processImage(const QByteArray& content, const std::string& f // Validate that the image loaded if (imageWidth == 0 || imageHeight == 0 || image.format() == QImage::Format_Invalid) { - QString reason(filenameExtension.empty() ? "" : "(no file extension)"); - qCWarning(imagelogging) << "Failed to load" << filename.c_str() << reason; + QString reason(filenameExtension.empty() ? "(no file extension)" : ""); + qCWarning(imagelogging) << "Failed to load" << filename.c_str() << qPrintable(reason); return nullptr; } @@ -258,35 +259,89 @@ struct MyErrorHandler : public nvtt::ErrorHandler { } }; -void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool alphaAsMask, bool grayscale = false, bool normalMap = false, int face = -1) { +void generateMips(gpu::Texture* texture, QImage& image, int face = -1) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); - Q_ASSERT(image.format() == QImage::Format_ARGB32); + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } const int width = image.width(), height = image.height(); const void* data = static_cast(image.constBits()); nvtt::TextureType textureType = nvtt::TextureType_2D; nvtt::InputFormat inputFormat = nvtt::InputFormat_BGRA_8UB; - nvtt::AlphaMode alphaMode = validAlpha ? nvtt::AlphaMode_Transparency : nvtt::AlphaMode_None; nvtt::WrapMode wrapMode = nvtt::WrapMode_Repeat; nvtt::RoundMode roundMode = nvtt::RoundMode_None; - nvtt::Format compressionFormat = nvtt::Format_BC1; - if (validAlpha) { - if (alphaAsMask) { - compressionFormat = nvtt::Format_BC1a; - } else { - compressionFormat = nvtt::Format_BC3; - } - } else if (grayscale) { - compressionFormat = nvtt::Format_BC4; - } else if (normalMap) { - compressionFormat = nvtt::Format_BC5; - } + nvtt::AlphaMode alphaMode = nvtt::AlphaMode_None; + float inputGamma = 2.2f; float outputGamma = 2.2f; + nvtt::CompressionOptions compressionOptions; + compressionOptions.setQuality(nvtt::Quality_Production); + + auto mipFormat = texture->getStoredMipFormat(); + if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGB) { + compressionOptions.setFormat(nvtt::Format_BC1); + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA_MASK) { + alphaMode = nvtt::AlphaMode_Transparency; + compressionOptions.setFormat(nvtt::Format_BC1a); + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA) { + alphaMode = nvtt::AlphaMode_Transparency; + compressionOptions.setFormat(nvtt::Format_BC3); + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_RED) { + compressionOptions.setFormat(nvtt::Format_BC4); + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_XY) { + compressionOptions.setFormat(nvtt::Format_BC5); + } else if (mipFormat == gpu::Element::COLOR_RGBA_32) { + compressionOptions.setFormat(nvtt::Format_RGBA); + compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm); + compressionOptions.setPixelFormat(32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); + inputGamma = 1.0f; + outputGamma = 1.0f; + } else if (mipFormat == gpu::Element::COLOR_BGRA_32) { + compressionOptions.setFormat(nvtt::Format_RGBA); + compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm); + compressionOptions.setPixelFormat(32, + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0xFF000000); + inputGamma = 1.0f; + outputGamma = 1.0f; + } else if (mipFormat == gpu::Element::COLOR_SRGBA_32) { + compressionOptions.setFormat(nvtt::Format_RGBA); + compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm); + compressionOptions.setPixelFormat(32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); + } else if (mipFormat == gpu::Element::COLOR_SBGRA_32) { + compressionOptions.setFormat(nvtt::Format_RGBA); + compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm); + compressionOptions.setPixelFormat(32, + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0xFF000000); + } else if (mipFormat == gpu::Element::COLOR_R_8) { + compressionOptions.setFormat(nvtt::Format_RGB); + compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm); + compressionOptions.setPixelFormat(8, 0, 0, 0); + } else { + qCWarning(imagelogging) << "Unknown mip format"; + Q_UNREACHABLE(); + return; + } + + nvtt::InputOptions inputOptions; inputOptions.setTextureLayout(textureType, width, height); inputOptions.setMipmapData(data, width, height); @@ -308,10 +363,6 @@ void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool al MyErrorHandler errorHandler; outputOptions.setErrorHandler(&errorHandler); - nvtt::CompressionOptions compressionOptions; - compressionOptions.setFormat(compressionFormat); - compressionOptions.setQuality(nvtt::Quality_Production); - nvtt::Compressor compressor; compressor.process(inputOptions, compressionOptions, outputOptions); #else @@ -319,7 +370,7 @@ void generateMips(gpu::Texture* texture, QImage& image, bool validAlpha, bool al #endif } -gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict) { +gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isStrict) { PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); bool validAlpha = false; bool alphaAsMask = true; @@ -328,6 +379,7 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { +#ifdef COMPRESSED_TEXTURES gpu::Element formatGPU; if (validAlpha) { formatGPU = alphaAsMask ? gpu::Element::COLOR_COMPRESSED_SRGBA_MASK : gpu::Element::COLOR_COMPRESSED_SRGBA; @@ -335,6 +387,10 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s formatGPU = gpu::Element::COLOR_COMPRESSED_SRGB; } gpu::Element formatMip = formatGPU; +#else + gpu::Element formatMip = gpu::Element::COLOR_SBGRA_32; + gpu::Element formatGPU = gpu::Element::COLOR_SRGBA_32; +#endif if (isStrict) { theTexture = gpu::Texture::createStrict(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); @@ -351,30 +407,30 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s } theTexture->setUsage(usage.build()); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image, validAlpha, alphaAsMask, false, false); + generateMips(theTexture.get(), image); } return theTexture; } gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false, true); + return process2DTextureColorFromImage(srcImage, srcImageName, true); } gpu::TexturePointer TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false); + return process2DTextureColorFromImage(srcImage, srcImageName); } gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false); + return process2DTextureColorFromImage(srcImage, srcImageName); } gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false); + return process2DTextureColorFromImage(srcImage, srcImageName); } gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, false); + return process2DTextureColorFromImage(srcImage, srcImageName); } @@ -391,13 +447,18 @@ gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(const QImag gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { +#ifdef COMPRESSED_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; +#else + gpu::Element formatMip = gpu::Element::COLOR_RGBA_32; + gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; +#endif theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image, false, false, false, true); + generateMips(theTexture.get(), image); } return theTexture; @@ -477,14 +538,18 @@ gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(const QImage& gpu::TexturePointer theTexture = nullptr; if ((result.width() > 0) && (result.height() > 0)) { +#ifdef COMPRESSED_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; - +#else + gpu::Element formatMip = gpu::Element::COLOR_RGBA_32; + gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; +#endif theTexture = gpu::Texture::create2D(formatGPU, result.width(), result.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image, false, false, false, true); + generateMips(theTexture.get(), result); } return theTexture; @@ -507,13 +572,18 @@ gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(const QImage& gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; +#ifdef COMPRESSED_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; +#else + gpu::Element formatMip = gpu::Element::COLOR_R_8; + gpu::Element formatGPU = gpu::Element::COLOR_R_8; +#endif theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image, false, false, true, false); + generateMips(theTexture.get(), image); } return theTexture; @@ -540,13 +610,18 @@ gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(const QIm gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; +#ifdef COMPRESSED_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; +#else + gpu::Element formatMip = gpu::Element::COLOR_R_8; + gpu::Element formatGPU = gpu::Element::COLOR_R_8; +#endif theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image, false, false, true, false); + generateMips(theTexture.get(), image); } return theTexture; @@ -570,13 +645,18 @@ gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(const QImage& s gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; +#ifdef COMPRESSED_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; +#else + gpu::Element formatMip = gpu::Element::COLOR_R_8; + gpu::Element formatGPU = gpu::Element::COLOR_R_8; +#endif theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image, false, false, true, false); + generateMips(theTexture.get(), image); } return theTexture; @@ -838,7 +918,7 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { }; const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); -gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance) { +gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool generateIrradiance) { PROFILE_RANGE(resource_parse, "processCubeTextureColorFromImage"); gpu::TexturePointer theTexture = nullptr; @@ -848,8 +928,13 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& image = image.convertToFormat(QImage::Format_ARGB32); } - gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; +#ifdef COMPRESSED_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_SRGBA; + gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; +#else + gpu::Element formatMip = gpu::Element::COLOR_SRGBA_32; + gpu::Element formatGPU = gpu::Element::COLOR_SRGBA_32; +#endif // Find the layout of the cubemap in the 2D image // Use the original image size since processSourceImage may have altered the size / aspect ratio @@ -890,14 +975,14 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& theTexture->setStoredMipFormat(formatMip); for (int face = 0; face < faces.size(); ++face) { - generateMips(theTexture.get(), faces[face], true, false, false, false, face); + generateMips(theTexture.get(), faces[face], face); } // Generate irradiance while we are at it if (generateIrradiance) { auto irradianceTexture = gpu::Texture::createCube(gpu::Element::COLOR_SRGBA_32, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); irradianceTexture->setSource(srcImageName); - irradianceTexture->setStoredMipFormat(gpu::Element::COLOR_SRGBA_32); + irradianceTexture->setStoredMipFormat(gpu::Element::COLOR_SBGRA_32); for (int face = 0; face < faces.size(); ++face) { irradianceTexture->assignStoredMipFace(0, face, faces[face].byteCount(), faces[face].constBits()); } @@ -915,11 +1000,11 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& } gpu::TexturePointer TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, true); + return processCubeTextureColorFromImage(srcImage, srcImageName, true); } gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false, false); + return processCubeTextureColorFromImage(srcImage, srcImageName, false); } } // namespace image \ No newline at end of file diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index ba0b88ee43..8232edac37 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -43,8 +43,8 @@ gpu::TexturePointer createCubeTextureFromImageWithoutIrradiance(const QImage& im gpu::TexturePointer createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); -gpu::TexturePointer process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool isStrict = false); -gpu::TexturePointer processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool generateIrradiance); +gpu::TexturePointer process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isStrict = false); +gpu::TexturePointer processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool generateIrradiance); } // namespace TextureUsage diff --git a/libraries/image/src/image/ImageLogging.cpp b/libraries/image/src/image/ImageLogging.cpp index ef78b44e02..1df8820f93 100644 --- a/libraries/image/src/image/ImageLogging.cpp +++ b/libraries/image/src/image/ImageLogging.cpp @@ -11,4 +11,4 @@ #include "ImageLogging.h" -Q_LOGGING_CATEGORY(imagelogging, "hifi.model") \ No newline at end of file +Q_LOGGING_CATEGORY(imagelogging, "hifi.image") \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 1731ffb132..9720b2ea5e 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -433,12 +433,22 @@ void ImageReader::read() { { PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0); texture = image::processImage(_content, _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType()); + + if (!texture) { + qCWarning(modelnetworking) << "Could not process:" << _url; + QMetaObject::invokeMethod(resource.data(), "setImage", + Q_ARG(gpu::TexturePointer, texture), + Q_ARG(int, 0), + Q_ARG(int, 0)); + return; + } + texture->setSourceHash(hash); texture->setFallbackTexture(networkTexture->getFallbackTexture()); } // Save the image into a KTXFile - if (textureCache) { + if (texture && textureCache) { auto memKtx = gpu::Texture::serialize(*texture); if (memKtx) { diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index 41a0586df2..225fcbb2ed 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -95,7 +95,7 @@ int main(int argc, char** argv) { QLoggingCategory::setFilterRules(LOG_FILTER_RULES); QImage image(TEST_IMAGE); - gpu::TexturePointer testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, true); + gpu::TexturePointer testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true); auto ktxMemory = gpu::Texture::serialize(*testTexture); { From 62b7855e1f9891814d7dd44549fbabfb76abef69 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 17 Apr 2017 18:35:58 -0700 Subject: [PATCH 21/32] Add pending to stats --- interface/resources/qml/Stats.qml | 5 +++++ interface/src/ui/Stats.cpp | 4 ++++ interface/src/ui/Stats.h | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 98e7f61ff7..dde6c445c8 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -211,6 +211,11 @@ Item { text: "Downloads: " + root.downloads + "/" + root.downloadLimit + ", Pending: " + root.downloadsPending; } + StatText { + visible: root.expanded; + text: "Processing: " + root.processing + + ", Pending: " + root.processingPending; + } StatText { visible: root.expanded && root.downloadUrls.length > 0; text: "Download URLs:" diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 01740b88ca..803104dd6d 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -31,6 +31,7 @@ #include "Menu.h" #include "Util.h" #include "SequenceNumberStats.h" +#include "StatTracker.h" HIFI_QML_DEF(Stats) @@ -250,6 +251,9 @@ void Stats::updateStats(bool force) { STAT_UPDATE(downloads, loadingRequests.size()); STAT_UPDATE(downloadLimit, ResourceCache::getRequestLimit()) STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount()); + STAT_UPDATE(processing, DependencyManager::get()->getStat("Processing").toInt()); + STAT_UPDATE(processingPending, DependencyManager::get()->getStat("PendingProcessing").toInt()); + // See if the active download urls have changed bool shouldUpdateUrls = _downloads != _downloadUrls.size(); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index a2ed125008..85c64bae90 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -89,6 +89,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, downloadLimit, 0) STATS_PROPERTY(int, downloadsPending, 0) Q_PROPERTY(QStringList downloadUrls READ downloadUrls NOTIFY downloadUrlsChanged) + STATS_PROPERTY(int, processing, 0) + STATS_PROPERTY(int, processingPending, 0) STATS_PROPERTY(int, triangles, 0) STATS_PROPERTY(int, quads, 0) STATS_PROPERTY(int, materialSwitches, 0) @@ -214,6 +216,8 @@ signals: void downloadLimitChanged(); void downloadsPendingChanged(); void downloadUrlsChanged(); + void processingChanged(); + void processingPendingChanged(); void trianglesChanged(); void quadsChanged(); void materialSwitchesChanged(); From 145af2b911bc54aa63b0d1413cb7efbf0dce3951 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Apr 2017 13:28:21 -0700 Subject: [PATCH 22/32] Fix ImageReader for images with a wrong extension --- libraries/image/src/image/Image.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 9e73aad0bf..9f375a7496 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -15,6 +15,8 @@ #include #include +#include +#include #include #include @@ -117,13 +119,33 @@ gpu::TexturePointer processImage(const QByteArray& content, const std::string& f // 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); - QImage image = QImage::fromData(content, filenameExtension.c_str()); + QBuffer buffer; + buffer.setData(content); + QImageReader imageReader(&buffer, filenameExtension.c_str()); + QImage image; + + if (imageReader.canRead()) { + image = imageReader.read(); + } else { + // Extension could be incorrect, try to detect the format from the content + QImageReader newImageReader; + newImageReader.setDecideFormatFromContent(true); + buffer.setData(content); + newImageReader.setDevice(&buffer); + + if (newImageReader.canRead()) { + qWarning(imagelogging) << "Image file" << filename.c_str() << "has extension" << filenameExtension.c_str() + << "but is actually a" << qPrintable(newImageReader.format()) << "(recovering)"; + image = newImageReader.read(); + } + } + int imageWidth = image.width(); int imageHeight = image.height(); // Validate that the image loaded if (imageWidth == 0 || imageHeight == 0 || image.format() == QImage::Format_Invalid) { - QString reason(filenameExtension.empty() ? "(no file extension)" : ""); + QString reason(image.format() == QImage::Format_Invalid ? "(Invalid Format)" : "(Size is invalid)"); qCWarning(imagelogging) << "Failed to load" << filename.c_str() << qPrintable(reason); return nullptr; } From fae49668b473900ab11ecd0761fb6f5166f53d76 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Apr 2017 14:53:25 -0700 Subject: [PATCH 23/32] Disable CubeMap and NormalMap compression --- libraries/image/src/image/Image.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 9f375a7496..fffe41cf89 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -28,7 +28,10 @@ using namespace gpu; #define CPU_MIPMAPS 1 -#define COMPRESSED_TEXTURES 1 +#define COMPRESS_COLOR_TEXTURES 1 +#define COMPRESS_NORMALMAP_TEXTURES 0 // Disable Normalmap compression for now +#define COMPRESS_GRAYSCALE_TEXTURES 1 +#define COMPRESS_CUBEMAP_TEXTURES 0 // Disable Cubemap compression for now static const glm::uvec2 SPARSE_PAGE_SIZE(128); static const glm::uvec2 MAX_TEXTURE_SIZE(4096); @@ -401,7 +404,7 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESSED_TEXTURES +#if CPU_MIPMAPS && COMPRESS_COLOR_TEXTURES gpu::Element formatGPU; if (validAlpha) { formatGPU = alphaAsMask ? gpu::Element::COLOR_COMPRESSED_SRGBA_MASK : gpu::Element::COLOR_COMPRESSED_SRGBA; @@ -469,7 +472,7 @@ gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(const QImag gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESSED_TEXTURES +#if CPU_MIPMAPS && COMPRESS_NORMALMAP_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; #else @@ -560,7 +563,7 @@ gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(const QImage& gpu::TexturePointer theTexture = nullptr; if ((result.width() > 0) && (result.height() > 0)) { -#ifdef COMPRESSED_TEXTURES +#if CPU_MIPMAPS && COMPRESS_NORMALMAP_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; #else @@ -594,7 +597,8 @@ gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(const QImage& gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESSED_TEXTURES + +#if CPU_MIPMAPS && COMPRESS_GRAYSCALE_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; #else @@ -632,7 +636,7 @@ gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(const QIm gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESSED_TEXTURES +#if CPU_MIPMAPS && COMPRESS_GRAYSCALE_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; #else @@ -667,7 +671,7 @@ gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(const QImage& s gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { -#ifdef COMPRESSED_TEXTURES +#if CPU_MIPMAPS && COMPRESS_GRAYSCALE_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; #else @@ -950,7 +954,7 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& image = image.convertToFormat(QImage::Format_ARGB32); } -#ifdef COMPRESSED_TEXTURES +#if CPU_MIPMAPS && COMPRESS_CUBEMAP_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_SRGBA; gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; #else From 77d8bf20a7a01e5af4d2cd41fd57d72fa31d8230 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Apr 2017 18:35:37 -0700 Subject: [PATCH 24/32] Fix warnings --- libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp | 6 ++++-- libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp | 9 ++++++--- libraries/image/src/image/Image.cpp | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index ac5eab4738..be6dd384ba 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -100,7 +100,8 @@ void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_RG_RGTC2: - glCompressedTexSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + glCompressedTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, internalFormat, + static_cast(sourceSize), sourcePointer); break; default: glTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); @@ -115,7 +116,8 @@ void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_RG_RGTC2: - glCompressedTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + glCompressedTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, internalFormat, + static_cast(sourceSize), sourcePointer); break; default: glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 1814be08d7..5a5e3d684f 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -125,7 +125,8 @@ void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_RG_RGTC2: - glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, + static_cast(sourceSize), sourcePointer); break; default: glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer); @@ -140,9 +141,11 @@ void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_RG_RGTC2: if (glCompressedTextureSubImage2DEXT) { auto target = GLTexture::CUBE_FACE_LAYOUT[face]; - glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat, sourceSize, sourcePointer); + glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat, + static_cast(sourceSize), sourcePointer); } else { - glCompressedTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, internalFormat, sourceSize, sourcePointer); + glCompressedTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, internalFormat, + static_cast(sourceSize), sourcePointer); } break; default: diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index fffe41cf89..084642cc7a 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -1000,7 +1000,7 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - for (int face = 0; face < faces.size(); ++face) { + for (uint8 face = 0; face < faces.size(); ++face) { generateMips(theTexture.get(), faces[face], face); } @@ -1009,7 +1009,7 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& auto irradianceTexture = gpu::Texture::createCube(gpu::Element::COLOR_SRGBA_32, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); irradianceTexture->setSource(srcImageName); irradianceTexture->setStoredMipFormat(gpu::Element::COLOR_SBGRA_32); - for (int face = 0; face < faces.size(); ++face) { + for (uint8 face = 0; face < faces.size(); ++face) { irradianceTexture->assignStoredMipFace(0, face, faces[face].byteCount(), faces[face].constBits()); } From b98cd7355ee006ba4f9fd4a7dad4362709aaf7cf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Apr 2017 18:36:41 -0700 Subject: [PATCH 25/32] Code cleanup --- libraries/gpu/src/gpu/Texture_ktx.cpp | 4 +- libraries/image/src/image/Image.cpp | 355 +++++++++----------------- libraries/image/src/image/Image.h | 5 +- 3 files changed, 133 insertions(+), 231 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 772b8107ea..50e9cb6d07 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -166,7 +166,9 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { static const std::string SOURCE_HASH_KEY = "hifi.sourceHash"; auto hash = texture.sourceHash(); - keyValues.emplace_back(ktx::KeyValue(SOURCE_HASH_KEY, hash.size(), (ktx::Byte*) hash.c_str())); + if (!hash.empty()) { + keyValues.emplace_back(ktx::KeyValue(SOURCE_HASH_KEY, static_cast(hash.size()), (ktx::Byte*) hash.c_str())); + } auto ktxBuffer = ktx::KTX::create(header, images, keyValues); #if 0 diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 084642cc7a..72c4ae674f 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -65,59 +65,85 @@ namespace image { TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& options) { switch (type) { - case gpu::ALBEDO_TEXTURE: { + case gpu::ALBEDO_TEXTURE: return image::TextureUsage::createAlbedoTextureFromImage; - break; - } - case gpu::EMISSIVE_TEXTURE: { + case gpu::EMISSIVE_TEXTURE: return image::TextureUsage::createEmissiveTextureFromImage; - break; - } - case gpu::LIGHTMAP_TEXTURE: { + case gpu::LIGHTMAP_TEXTURE: return image::TextureUsage::createLightmapTextureFromImage; - break; - } - case gpu::CUBE_TEXTURE: { + case gpu::CUBE_TEXTURE: if (options.value("generateIrradiance", true).toBool()) { return image::TextureUsage::createCubeTextureFromImage; } else { return image::TextureUsage::createCubeTextureFromImageWithoutIrradiance; } - break; - } - case gpu::BUMP_TEXTURE: { + case gpu::BUMP_TEXTURE: return image::TextureUsage::createNormalTextureFromBumpImage; - break; - } - case gpu::NORMAL_TEXTURE: { + case gpu::NORMAL_TEXTURE: return image::TextureUsage::createNormalTextureFromNormalImage; - break; - } - case gpu::ROUGHNESS_TEXTURE: { + case gpu::ROUGHNESS_TEXTURE: return image::TextureUsage::createRoughnessTextureFromImage; - break; - } - case gpu::GLOSS_TEXTURE: { + case gpu::GLOSS_TEXTURE: return image::TextureUsage::createRoughnessTextureFromGlossImage; - break; - } - case gpu::SPECULAR_TEXTURE: { + case gpu::SPECULAR_TEXTURE: return image::TextureUsage::createMetallicTextureFromImage; - break; - } - case gpu::STRICT_TEXTURE: { + case gpu::STRICT_TEXTURE: return image::TextureUsage::createStrict2DTextureFromImage; - break; - } case gpu::DEFAULT_TEXTURE: - default: { + default: return image::TextureUsage::create2DTextureFromImage; - break; - } } } +gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, true); +} + +gpu::TexturePointer TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false); +} + +gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false); +} + +gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false); +} + +gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, srcImageName, false); +} + +gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureNormalMapFromImage(srcImage, srcImageName, false); +} + +gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureNormalMapFromImage(srcImage, srcImageName, true); +} + +gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureGrayscaleFromImage(srcImage, srcImageName, false); +} + +gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureGrayscaleFromImage(srcImage, srcImageName, true); +} + +gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureGrayscaleFromImage(srcImage, srcImageName, false); +} + +gpu::TexturePointer TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return processCubeTextureColorFromImage(srcImage, srcImageName, true); +} + +gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { + return processCubeTextureColorFromImage(srcImage, srcImageName, false); +} + gpu::TexturePointer processImage(const QByteArray& content, const std::string& filename, int maxNumPixels, gpu::TextureType textureType) { // Help the QImage loader by extracting the image file format from the url filename ext. // Some tga are not created properly without it. @@ -205,46 +231,6 @@ QImage processSourceImage(const QImage& srcImage, bool cubemap) { return srcImage; } -const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask) { - PROFILE_RANGE(resource_parse, "process2DImageColor"); - QImage image = processSourceImage(srcImage, false); - validAlpha = false; - alphaAsMask = true; - const uint8 OPAQUE_ALPHA = 255; - const uint8 TRANSPARENT_ALPHA = 0; - if (image.hasAlphaChannel()) { - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - // Figure out if we can use a mask for alpha or not - int numOpaques = 0; - int numTranslucents = 0; - const int NUM_PIXELS = image.width() * image.height(); - const int MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(NUM_PIXELS)); - const QRgb* data = reinterpret_cast(image.constBits()); - for (int i = 0; i < NUM_PIXELS; ++i) { - auto alpha = qAlpha(data[i]); - if (alpha == OPAQUE_ALPHA) { - numOpaques++; - } else if (alpha != TRANSPARENT_ALPHA) { - if (++numTranslucents > MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK) { - alphaAsMask = false; - break; - } - } - } - validAlpha = (numOpaques != NUM_PIXELS); - } - - // Force all the color images to be rgba32bits - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - return image; -} - struct MyOutputHandler : public nvtt::OutputHandler { MyOutputHandler(gpu::Texture* texture, int face) : _texture(texture), _face(face) {} @@ -395,11 +381,46 @@ void generateMips(gpu::Texture* texture, QImage& image, int face = -1) { #endif } +void processTextureAlpha(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask) { + PROFILE_RANGE(resource_parse, "processTextureAlpha"); + validAlpha = false; + alphaAsMask = true; + const uint8 OPAQUE_ALPHA = 255; + const uint8 TRANSPARENT_ALPHA = 0; + + // Figure out if we can use a mask for alpha or not + int numOpaques = 0; + int numTranslucents = 0; + const int NUM_PIXELS = srcImage.width() * srcImage.height(); + const int MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(NUM_PIXELS)); + const QRgb* data = reinterpret_cast(srcImage.constBits()); + for (int i = 0; i < NUM_PIXELS; ++i) { + auto alpha = qAlpha(data[i]); + if (alpha == OPAQUE_ALPHA) { + numOpaques++; + } else if (alpha != TRANSPARENT_ALPHA) { + if (++numTranslucents > MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK) { + alphaAsMask = false; + break; + } + } + } + validAlpha = (numOpaques != NUM_PIXELS); +} + gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isStrict) { PROFILE_RANGE(resource_parse, "process2DTextureColorFromImage"); - bool validAlpha = false; - bool alphaAsMask = true; - QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); + QImage image = processSourceImage(srcImage, false); + bool validAlpha = image.hasAlphaChannel(); + bool alphaAsMask = false; + + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + + if (validAlpha) { + processTextureAlpha(srcImage, validAlpha, alphaAsMask); + } gpu::TexturePointer theTexture = nullptr; @@ -438,57 +459,6 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s return theTexture; } -gpu::TexturePointer TextureUsage::createStrict2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName, true); -} - -gpu::TexturePointer TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName); -} - -gpu::TexturePointer TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName); -} - -gpu::TexturePointer TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName); -} - -gpu::TexturePointer TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, srcImageName); -} - - -gpu::TexturePointer TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createNormalTextureFromNormalImage"); - QImage image = processSourceImage(srcImage, false); - - // Make sure the normal map source image is ARGB32 - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - - gpu::TexturePointer theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - -#if CPU_MIPMAPS && COMPRESS_NORMALMAP_TEXTURES - gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; - gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_XY; -#else - gpu::Element formatMip = gpu::Element::COLOR_RGBA_32; - gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; -#endif - - theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image); - } - - return theTexture; -} - int clampPixelCoordinate(int coordinate, int maxCoordinate) { return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate)); } @@ -501,10 +471,7 @@ double mapComponent(double sobelValue) { return (sobelValue + 1.0) * factor; } -gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createNormalTextureFromBumpImage"); - QImage image = processSourceImage(srcImage, false); - +QImage processBumpMap(QImage& image) { if (image.format() != QImage::Format_Grayscale8) { image = image.convertToFormat(QImage::Format_Grayscale8); } @@ -560,8 +527,23 @@ gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(const QImage& } } + return result; +} +gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(const QImage& srcImage, const std::string& srcImageName, bool isBumpMap) { + PROFILE_RANGE(resource_parse, "process2DTextureNormalMapFromImage"); + QImage image = processSourceImage(srcImage, false); + + if (isBumpMap) { + image = processBumpMap(image); + } + + // Make sure the normal map source image is ARGB32 + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + gpu::TexturePointer theTexture = nullptr; - if ((result.width() > 0) && (result.height() > 0)) { + if ((image.width() > 0) && (image.height() > 0)) { #if CPU_MIPMAPS && COMPRESS_NORMALMAP_TEXTURES gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_XY; @@ -571,29 +553,27 @@ gpu::TexturePointer TextureUsage::createNormalTextureFromBumpImage(const QImage& gpu::Element formatGPU = gpu::Element::COLOR_RGBA_32; #endif - theTexture = gpu::Texture::create2D(formatGPU, result.width(), result.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); + theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); theTexture->setSource(srcImageName); theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), result); + generateMips(theTexture.get(), image); } return theTexture; } -gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createRoughnessTextureFromImage"); +gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(const QImage& srcImage, const std::string& srcImageName, bool isInvertedPixels) { + PROFILE_RANGE(resource_parse, "process2DTextureGrayscaleFromImage"); QImage image = processSourceImage(srcImage, false); - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } + + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); } - image = image.convertToFormat(QImage::Format_ARGB32); + if (isInvertedPixels) { + // Gloss turned into Rough + image.invertPixels(QImage::InvertRgba); + } gpu::TexturePointer theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { @@ -612,80 +592,7 @@ gpu::TexturePointer TextureUsage::createRoughnessTextureFromImage(const QImage& generateMips(theTexture.get(), image); } - return theTexture; -} - -gpu::TexturePointer TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createRoughnessTextureFromGlossImage"); - QImage image = processSourceImage(srcImage, false); - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } - } - - // Gloss turned into Rough - image.invertPixels(QImage::InvertRgba); - - image = image.convertToFormat(QImage::Format_ARGB32); - - gpu::TexturePointer theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - -#if CPU_MIPMAPS && COMPRESS_GRAYSCALE_TEXTURES - gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; - gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; -#else - gpu::Element formatMip = gpu::Element::COLOR_R_8; - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - - theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image); - } - - return theTexture; -} - -gpu::TexturePointer TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - PROFILE_RANGE(resource_parse, "createMetallicTextureFromImage"); - QImage image = processSourceImage(srcImage, false); - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } - } - - image = image.convertToFormat(QImage::Format_ARGB32); - - gpu::TexturePointer theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - -#if CPU_MIPMAPS && COMPRESS_GRAYSCALE_TEXTURES - gpu::Element formatMip = gpu::Element::COLOR_COMPRESSED_RED; - gpu::Element formatGPU = gpu::Element::COLOR_COMPRESSED_RED; -#else - gpu::Element formatMip = gpu::Element::COLOR_R_8; - gpu::Element formatGPU = gpu::Element::COLOR_R_8; -#endif - - theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); - theTexture->setSource(srcImageName); - theTexture->setStoredMipFormat(formatMip); - generateMips(theTexture.get(), image); - } - - return theTexture; + return theTexture; } class CubeLayout { @@ -1006,6 +913,7 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& // Generate irradiance while we are at it if (generateIrradiance) { + PROFILE_RANGE(resource_parse, "generateIrradiance"); auto irradianceTexture = gpu::Texture::createCube(gpu::Element::COLOR_SRGBA_32, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)); irradianceTexture->setSource(srcImageName); irradianceTexture->setStoredMipFormat(gpu::Element::COLOR_SBGRA_32); @@ -1013,7 +921,6 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& irradianceTexture->assignStoredMipFace(0, face, faces[face].byteCount(), faces[face].constBits()); } - PROFILE_RANGE(resource_parse, "generateIrradiance"); irradianceTexture->generateIrradiance(); auto irradiance = irradianceTexture->getIrradiance(); @@ -1025,12 +932,4 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& return theTexture; } -gpu::TexturePointer TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, true); -} - -gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) { - return processCubeTextureColorFromImage(srcImage, srcImageName, false); -} - } // namespace image \ No newline at end of file diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 8232edac37..be66f82919 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -42,8 +42,9 @@ gpu::TexturePointer createCubeTextureFromImage(const QImage& image, const std::s gpu::TexturePointer createCubeTextureFromImageWithoutIrradiance(const QImage& image, const std::string& srcImageName); gpu::TexturePointer createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); -const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); -gpu::TexturePointer process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isStrict = false); +gpu::TexturePointer process2DTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isStrict); +gpu::TexturePointer process2DTextureNormalMapFromImage(const QImage& srcImage, const std::string& srcImageName, bool isBumpMap); +gpu::TexturePointer process2DTextureGrayscaleFromImage(const QImage& srcImage, const std::string& srcImageName, bool isInvertedPixels); gpu::TexturePointer processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool generateIrradiance); } // namespace TextureUsage From d6ab35ba1ad175c77b7af977c757e20002ca1bb7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Apr 2017 18:37:58 -0700 Subject: [PATCH 26/32] Logging cleanup --- libraries/image/src/image/Image.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 72c4ae674f..998cb88b19 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -163,8 +163,8 @@ gpu::TexturePointer processImage(const QByteArray& content, const std::string& f newImageReader.setDevice(&buffer); if (newImageReader.canRead()) { - qWarning(imagelogging) << "Image file" << filename.c_str() << "has extension" << filenameExtension.c_str() - << "but is actually a" << qPrintable(newImageReader.format()) << "(recovering)"; + qCWarning(imagelogging) << "Image file" << filename.c_str() << "has extension" << filenameExtension.c_str() + << "but is actually a" << qPrintable(newImageReader.format()) << "(recovering)"; image = newImageReader.read(); } } @@ -266,7 +266,7 @@ struct MyOutputHandler : public nvtt::OutputHandler { }; struct MyErrorHandler : public nvtt::ErrorHandler { virtual void error(nvtt::Error e) override { - qDebug() << "Texture compression error:" << nvtt::errorString(e); + qCWarning(imagelogging) << "Texture compression error:" << nvtt::errorString(e); } }; From 1820207259ddd75328b232f0a6d32864ccb452b5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 19 Apr 2017 11:31:58 -0700 Subject: [PATCH 27/32] Fix processTextureAlpha --- libraries/image/src/image/Image.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 998cb88b19..c66a3b7f17 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -419,7 +419,7 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s } if (validAlpha) { - processTextureAlpha(srcImage, validAlpha, alphaAsMask); + processTextureAlpha(image, validAlpha, alphaAsMask); } gpu::TexturePointer theTexture = nullptr; From 1cc86b72036a08b30b5fb82a9f796b5ccc81855a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 20 Apr 2017 17:12:27 -0700 Subject: [PATCH 28/32] Fix build error --- libraries/gpu-gl/src/gpu/gl/GLTexture.h | 2 +- libraries/gpu-gl/src/gpu/gl41/GL41Backend.h | 2 +- libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.h b/libraries/gpu-gl/src/gpu/gl/GLTexture.h index f12ac12df3..69a7e2a1ae 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.h @@ -177,7 +177,7 @@ public: protected: GLExternalTexture(const std::weak_ptr& backend, const Texture& texture, GLuint id); void generateMips() const override {} - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const override {} + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override {} Size size() const override { return 0; } }; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 3f530e28b8..50a2139e88 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -105,7 +105,7 @@ public: void promote() override; void demote() override; void populateTransferQueue() override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; Size size() const override { return _size; } Size _size { 0 }; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index be6dd384ba..34e9e45886 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -276,9 +276,9 @@ void GL41VariableAllocationTexture::allocateStorage(uint16 allocatedMip) { } -void GL41VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum type, const void* sourcePointer) const { +void GL41VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { withPreservedTexture([&] { - Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, format, type, sourcePointer); + Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, format, internalFormat, type, sourceSize, sourcePointer); }); } From e3ab2615c15870279b97abec7bfde53d5fbbd5e9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 20 Apr 2017 16:56:45 -0700 Subject: [PATCH 29/32] allow NVTT to be built as external on android --- cmake/externals/nvtt/CMakeLists.txt | 147 ++++++++++++++-------------- 1 file changed, 75 insertions(+), 72 deletions(-) diff --git a/cmake/externals/nvtt/CMakeLists.txt b/cmake/externals/nvtt/CMakeLists.txt index fcaf10330c..0e1c240c77 100644 --- a/cmake/externals/nvtt/CMakeLists.txt +++ b/cmake/externals/nvtt/CMakeLists.txt @@ -5,80 +5,83 @@ set(EXTERNAL_NAME nvtt) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -if (NOT ANDROID) - if (WIN32) - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip - URL_MD5 3ea6eeadbcc69071acf9c49ba565760e - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 - ) +if (WIN32) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip + URL_MD5 3ea6eeadbcc69071acf9c49ba565760e + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) - ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT release library") - set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/Release>/x64" CACHE PATH "Location of NVTT release DLL") + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "Location of NVTT include directory") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Release/x64/nvtt.lib CACHE FILEPATH "Path to NVTT release library") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/Release>/x64" CACHE PATH "Location of NVTT release DLL") +else () + + if (ANDROID) + set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") + endif () + + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip + URL_MD5 81b8fa6a9ee3f986088eb6e2215d6a57 + CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + ) + + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "Location of NVTT include directory") + + if (APPLE) + set(_LIB_EXT "dylib") else () - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip - URL_MD5 81b8fa6a9ee3f986088eb6e2215d6a57 - CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 - ) - - ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "Location of NVTT include directory") - - if (APPLE) - set(_LIB_EXT "dylib") - else () - set(_LIB_EXT "so") - endif () - - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libnvtt.${_LIB_EXT} CACHE FILEPATH "Path to NVTT library") - - if (APPLE) - # on OS X we have to use install_name_tool to fix the paths found in the NVTT shared libraries - # so that they can be found and linked during the linking phase - set(_NVTT_LIB_DIR "${INSTALL_DIR}/lib") - - # first fix the install names of all present libraries - ExternalProject_Add_Step( - ${EXTERNAL_NAME} - change-install-name - COMMENT "Calling install_name_tool on NVTT libraries to fix install name for dylib linking" - COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_NVTT_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake - DEPENDEES install - WORKING_DIRECTORY - LOG 1 - ) - - # then, for the main library (libnvtt) fix the paths to the dependency libraries (core, image, math) - ExternalProject_Add_Step( - ${EXTERNAL_NAME} - change-dependency-paths - COMMENT "Calling install_name_tool on NVTT libraries to fix paths for dependency libraries" - COMMAND install_name_tool -change libnvimage.dylib ${INSTALL_DIR}/lib/libnvimage.dylib libnvtt.dylib - COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvtt.dylib - COMMAND install_name_tool -change libnvmath.dylib ${INSTALL_DIR}/lib/libnvmath.dylib libnvtt.dylib - COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvimage.dylib - COMMAND install_name_tool -change libnvmath.dylib ${INSTALL_DIR}/lib/libnvmath.dylib libnvimage.dylib - COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvmath.dylib - DEPENDEES install - WORKING_DIRECTORY /lib - LOG 1 - ) - endif () + set(_LIB_EXT "so") endif () - # Hide this external target (for IDE users) - set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") -endif() + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libnvtt.${_LIB_EXT} CACHE FILEPATH "Path to NVTT library") + + if (APPLE) + # on OS X we have to use install_name_tool to fix the paths found in the NVTT shared libraries + # so that they can be found and linked during the linking phase + set(_NVTT_LIB_DIR "${INSTALL_DIR}/lib") + + # first fix the install names of all present libraries + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-install-name + COMMENT "Calling install_name_tool on NVTT libraries to fix install name for dylib linking" + COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_NVTT_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake + DEPENDEES install + WORKING_DIRECTORY + LOG 1 + ) + + # then, for the main library (libnvtt) fix the paths to the dependency libraries (core, image, math) + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-dependency-paths + COMMENT "Calling install_name_tool on NVTT libraries to fix paths for dependency libraries" + COMMAND install_name_tool -change libnvimage.dylib ${INSTALL_DIR}/lib/libnvimage.dylib libnvtt.dylib + COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvtt.dylib + COMMAND install_name_tool -change libnvmath.dylib ${INSTALL_DIR}/lib/libnvmath.dylib libnvtt.dylib + COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvimage.dylib + COMMAND install_name_tool -change libnvmath.dylib ${INSTALL_DIR}/lib/libnvmath.dylib libnvimage.dylib + COMMAND install_name_tool -change libnvcore.dylib ${INSTALL_DIR}/lib/libnvcore.dylib libnvmath.dylib + DEPENDEES install + WORKING_DIRECTORY /lib + LOG 1 + ) + endif () +endif () + +# Hide this external target (for IDE users) +set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") From 56f656f92ade20ba1d6f3416ae316eca95a15f45 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 20 Apr 2017 19:21:21 -0700 Subject: [PATCH 30/32] Disable compression during runtime --- libraries/image/src/image/Image.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index c66a3b7f17..299f9716ee 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -28,9 +28,9 @@ using namespace gpu; #define CPU_MIPMAPS 1 -#define COMPRESS_COLOR_TEXTURES 1 +#define COMPRESS_COLOR_TEXTURES 0 #define COMPRESS_NORMALMAP_TEXTURES 0 // Disable Normalmap compression for now -#define COMPRESS_GRAYSCALE_TEXTURES 1 +#define COMPRESS_GRAYSCALE_TEXTURES 0 #define COMPRESS_CUBEMAP_TEXTURES 0 // Disable Cubemap compression for now static const glm::uvec2 SPARSE_PAGE_SIZE(128); From 9dbae4b54eaf9a9c4f84c91bc04307a7996b2840 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 25 Apr 2017 13:53:46 -0700 Subject: [PATCH 31/32] CR --- libraries/gpu/src/gpu/Format.cpp | 8 ++++---- libraries/image/src/image/Image.cpp | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index 31de77b547..19d8855bd9 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -19,11 +19,11 @@ const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::COLOR_BGRA_32{ VEC4, NUINT8, BGRA }; const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; -const Element Element::COLOR_COMPRESSED_RED{VEC4, NUINT8, COMPRESSED_BC4_RED}; +const Element Element::COLOR_COMPRESSED_RED{ VEC4, NUINT8, COMPRESSED_BC4_RED }; const Element Element::COLOR_COMPRESSED_SRGB{ VEC4, NUINT8, COMPRESSED_BC1_SRGB }; -const Element Element::COLOR_COMPRESSED_SRGBA_MASK{VEC4, NUINT8, COMPRESSED_BC1_SRGBA}; -const Element Element::COLOR_COMPRESSED_SRGBA{VEC4, NUINT8, COMPRESSED_BC3_SRGBA}; -const Element Element::COLOR_COMPRESSED_XY{VEC4, NUINT8, COMPRESSED_BC5_XY}; +const Element Element::COLOR_COMPRESSED_SRGBA_MASK{ VEC4, NUINT8, COMPRESSED_BC1_SRGBA }; +const Element Element::COLOR_COMPRESSED_SRGBA{ VEC4, NUINT8, COMPRESSED_BC3_SRGBA }; +const Element Element::COLOR_COMPRESSED_XY{ VEC4, NUINT8, COMPRESSED_BC5_XY }; const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 }; const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 299f9716ee..3c3fdef717 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -362,7 +362,6 @@ void generateMips(gpu::Texture* texture, QImage& image, int face = -1) { inputOptions.setAlphaMode(alphaMode); inputOptions.setWrapMode(wrapMode); inputOptions.setRoundMode(roundMode); - // inputOptions.setMaxExtents(int d); inputOptions.setMipmapGeneration(true); inputOptions.setMipmapFilter(nvtt::MipmapFilter_Box); @@ -932,4 +931,4 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& return theTexture; } -} // namespace image \ No newline at end of file +} // namespace image From 33f58f99d18c1692353169c25fd314297ab1e99b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 25 Apr 2017 15:52:33 -0700 Subject: [PATCH 32/32] CR --- interface/src/Application.cpp | 4 +- libraries/entities-renderer/CMakeLists.txt | 2 +- .../src/EntityTreeRenderer.cpp | 4 +- libraries/gpu-gl/src/gpu/gl/GLTexture.cpp | 4 +- libraries/gpu-gl/src/gpu/gl/GLTexture.h | 4 +- libraries/gpu-gl/src/gpu/gl41/GL41Backend.h | 4 +- .../src/gpu/gl41/GL41BackendTexture.cpp | 6 +-- libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 2 +- .../src/gpu/gl45/GL45BackendTexture.cpp | 2 +- libraries/gpu/src/gpu/Texture.h | 17 -------- libraries/image/src/image/Image.cpp | 28 ++++++------- libraries/image/src/image/Image.h | 28 ++++++++++--- .../src/model-networking/ModelCache.cpp | 40 +++++++++---------- .../src/model-networking/ModelCache.h | 4 +- .../src/model-networking/TextureCache.cpp | 40 +++++++++---------- .../src/model-networking/TextureCache.h | 11 ++--- libraries/procedural/CMakeLists.txt | 2 +- libraries/render-utils/CMakeLists.txt | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/script-engine/CMakeLists.txt | 4 +- plugins/openvr/CMakeLists.txt | 2 +- tests/render-perf/CMakeLists.txt | 2 +- tests/render-texture-load/CMakeLists.txt | 2 +- 23 files changed, 108 insertions(+), 108 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 325fa86838..f51c3d2b46 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1445,8 +1445,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QString skyboxUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-cubemap.jpg" }; QString skyboxAmbientUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-ambient.jpg" }; - _defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, gpu::TextureType::CUBE_TEXTURE, { { "generateIrradiance", false } }); - _defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, gpu::TextureType::CUBE_TEXTURE, { { "generateIrradiance", true } }); + _defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, image::TextureUsage::CUBE_TEXTURE, { { "generateIrradiance", false } }); + _defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, image::TextureUsage::CUBE_TEXTURE, { { "generateIrradiance", true } }); _defaultSkybox->setCubemap(_defaultSkyboxTexture); diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 0063f4a701..8ef28bbc7b 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME entities-renderer) AUTOSCRIBE_SHADER_LIB(gpu model procedural render render-utils) setup_hifi_library(Widgets Network Script) -link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils) +link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils image) target_bullet() diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 6b06b7d389..20d07b1e6d 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -495,7 +495,7 @@ bool EntityTreeRenderer::applySkyboxAndHasAmbient() { bool isAmbientSet = false; if (_pendingAmbientTexture && !_ambientTexture) { - _ambientTexture = textureCache->getTexture(_ambientTextureURL, gpu::TextureType::CUBE_TEXTURE); + _ambientTexture = textureCache->getTexture(_ambientTextureURL, image::TextureUsage::CUBE_TEXTURE); } if (_ambientTexture && _ambientTexture->isLoaded()) { _pendingAmbientTexture = false; @@ -512,7 +512,7 @@ bool EntityTreeRenderer::applySkyboxAndHasAmbient() { if (_pendingSkyboxTexture && (!_skyboxTexture || (_skyboxTexture->getURL() != _skyboxTextureURL))) { - _skyboxTexture = textureCache->getTexture(_skyboxTextureURL, gpu::TextureType::CUBE_TEXTURE); + _skyboxTexture = textureCache->getTexture(_skyboxTextureURL, image::TextureUsage::CUBE_TEXTURE); } if (_skyboxTexture && _skyboxTexture->isLoaded()) { _pendingSkyboxTexture = false; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp index 30d2bc8377..a6e6bf4fa3 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp @@ -123,7 +123,7 @@ void GLTexture::copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip, u auto mipSize = _gpuObject.getStoredMipFaceSize(sourceMip, face); if (mipData) { GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), _gpuObject.getStoredMipFormat()); - copyMipFaceLinesFromTexture(targetMip, face, size, 0, texelFormat.format, texelFormat.internalFormat, texelFormat.type, mipSize, mipData->readData()); + copyMipFaceLinesFromTexture(targetMip, face, size, 0, texelFormat.internalFormat, texelFormat.format, texelFormat.type, mipSize, mipData->readData()); } else { qCDebug(gpugllogging) << "Missing mipData level=" << sourceMip << " face=" << (int)face << " for texture " << _gpuObject.source().c_str(); } @@ -239,7 +239,7 @@ TransferJob::TransferJob(const GLTexture& parent, uint16_t sourceMip, uint16_t t Backend::updateTextureTransferPendingSize(0, _transferSize); _transferLambda = [=] { - _parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, format, internalFormat, type, _buffer.size(), _buffer.data()); + _parent.copyMipFaceLinesFromTexture(targetMip, face, transferDimensions, lineOffset, internalFormat, format, type, _buffer.size(), _buffer.data()); std::vector emptyVector; _buffer.swap(emptyVector); }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.h b/libraries/gpu-gl/src/gpu/gl/GLTexture.h index 69a7e2a1ae..8b4b545b7d 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.h @@ -163,7 +163,7 @@ public: protected: virtual Size size() const = 0; virtual void generateMips() const = 0; - virtual void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const = 0; + virtual void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const = 0; virtual void copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip, uint8_t face) const final; GLTexture(const std::weak_ptr& backend, const Texture& texture, GLuint id); @@ -177,7 +177,7 @@ public: protected: GLExternalTexture(const std::weak_ptr& backend, const Texture& texture, GLuint id); void generateMips() const override {} - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override {} + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override {} Size size() const override { return 0; } }; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 50a2139e88..19979a1778 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -50,7 +50,7 @@ public: protected: GL41Texture(const std::weak_ptr& backend, const Texture& texture); void generateMips() const override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override; virtual void syncSampler() const; void withPreservedTexture(std::function f) const; @@ -105,7 +105,7 @@ public: void promote() override; void demote() override; void populateTransferQueue() override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override; Size size() const override { return _size; } Size _size { 0 }; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 34e9e45886..bff5bf3f2c 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -92,7 +92,7 @@ void GL41Texture::generateMips() const { (void)CHECK_GL_ERROR(); } -void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { +void GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { switch (internalFormat) { case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: @@ -276,9 +276,9 @@ void GL41VariableAllocationTexture::allocateStorage(uint16 allocatedMip) { } -void GL41VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { +void GL41VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const { withPreservedTexture([&] { - Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, format, internalFormat, type, sourceSize, sourcePointer); + Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, internalFormat, format, type, sourceSize, sourcePointer); }); } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index c1bbfdd162..dbedd81c76 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -48,7 +48,7 @@ public: protected: GL45Texture(const std::weak_ptr& backend, const Texture& texture); void generateMips() const override; - void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const override; + void copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override; virtual void syncSampler() const; }; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 5a5e3d684f..c6f1ef41ae 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -117,7 +117,7 @@ void GL45Texture::generateMips() const { (void)CHECK_GL_ERROR(); } -void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum format, GLenum internalFormat, GLenum type, Size sourceSize, const void* sourcePointer) const { +void GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const { if (GL_TEXTURE_2D == _target) { switch (internalFormat) { case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 9250221708..2f63bd6719 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -157,23 +157,6 @@ enum class TextureUsageType { EXTERNAL, }; -enum TextureType { - DEFAULT_TEXTURE, - STRICT_TEXTURE, - ALBEDO_TEXTURE, - NORMAL_TEXTURE, - BUMP_TEXTURE, - SPECULAR_TEXTURE, - METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey - ROUGHNESS_TEXTURE, - GLOSS_TEXTURE, - EMISSIVE_TEXTURE, - CUBE_TEXTURE, - OCCLUSION_TEXTURE, - SCATTERING_TEXTURE = OCCLUSION_TEXTURE, - LIGHTMAP_TEXTURE -}; - class Texture : public Resource { static std::atomic _textureCPUCount; static std::atomic _textureCPUMemoryUsage; diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 3c3fdef717..707a2e4496 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -63,34 +63,34 @@ glm::uvec2 rectifyToSparseSize(const glm::uvec2& size) { namespace image { -TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& options) { +TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, const QVariantMap& options) { switch (type) { - case gpu::ALBEDO_TEXTURE: + case ALBEDO_TEXTURE: return image::TextureUsage::createAlbedoTextureFromImage; - case gpu::EMISSIVE_TEXTURE: + case EMISSIVE_TEXTURE: return image::TextureUsage::createEmissiveTextureFromImage; - case gpu::LIGHTMAP_TEXTURE: + case LIGHTMAP_TEXTURE: return image::TextureUsage::createLightmapTextureFromImage; - case gpu::CUBE_TEXTURE: + case CUBE_TEXTURE: if (options.value("generateIrradiance", true).toBool()) { return image::TextureUsage::createCubeTextureFromImage; } else { return image::TextureUsage::createCubeTextureFromImageWithoutIrradiance; } - case gpu::BUMP_TEXTURE: + case BUMP_TEXTURE: return image::TextureUsage::createNormalTextureFromBumpImage; - case gpu::NORMAL_TEXTURE: + case NORMAL_TEXTURE: return image::TextureUsage::createNormalTextureFromNormalImage; - case gpu::ROUGHNESS_TEXTURE: + case ROUGHNESS_TEXTURE: return image::TextureUsage::createRoughnessTextureFromImage; - case gpu::GLOSS_TEXTURE: + case GLOSS_TEXTURE: return image::TextureUsage::createRoughnessTextureFromGlossImage; - case gpu::SPECULAR_TEXTURE: + case SPECULAR_TEXTURE: return image::TextureUsage::createMetallicTextureFromImage; - case gpu::STRICT_TEXTURE: + case STRICT_TEXTURE: return image::TextureUsage::createStrict2DTextureFromImage; - case gpu::DEFAULT_TEXTURE: + case DEFAULT_TEXTURE: default: return image::TextureUsage::create2DTextureFromImage; } @@ -144,7 +144,7 @@ gpu::TexturePointer TextureUsage::createCubeTextureFromImageWithoutIrradiance(co return processCubeTextureColorFromImage(srcImage, srcImageName, false); } -gpu::TexturePointer processImage(const QByteArray& content, const std::string& filename, int maxNumPixels, gpu::TextureType textureType) { +gpu::TexturePointer processImage(const QByteArray& content, const std::string& filename, int maxNumPixels, TextureUsage::Type textureType) { // 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); @@ -193,7 +193,7 @@ gpu::TexturePointer processImage(const QByteArray& content, const std::string& f QSize(imageWidth, imageHeight) << ")"; } - auto loader = getTextureLoaderForType(textureType); + auto loader = TextureUsage::getTextureLoaderForType(textureType); auto texture = loader(image, filename); return texture; diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index be66f82919..3e5aa868d2 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -21,14 +21,28 @@ class QImage; namespace image { -using TextureLoader = std::function; - -TextureLoader getTextureLoaderForType(gpu::TextureType type, const QVariantMap& options = QVariantMap()); - -gpu::TexturePointer processImage(const QByteArray& content, const std::string& url, int maxNumPixels, gpu::TextureType textureType); - namespace TextureUsage { +enum Type { + DEFAULT_TEXTURE, + STRICT_TEXTURE, + ALBEDO_TEXTURE, + NORMAL_TEXTURE, + BUMP_TEXTURE, + SPECULAR_TEXTURE, + METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey + ROUGHNESS_TEXTURE, + GLOSS_TEXTURE, + EMISSIVE_TEXTURE, + CUBE_TEXTURE, + OCCLUSION_TEXTURE, + SCATTERING_TEXTURE = OCCLUSION_TEXTURE, + LIGHTMAP_TEXTURE +}; + +using TextureLoader = std::function; +TextureLoader getTextureLoaderForType(Type type, const QVariantMap& options = QVariantMap()); + gpu::TexturePointer create2DTextureFromImage(const QImage& image, const std::string& srcImageName); gpu::TexturePointer createStrict2DTextureFromImage(const QImage& image, const std::string& srcImageName); gpu::TexturePointer createAlbedoTextureFromImage(const QImage& image, const std::string& srcImageName); @@ -49,6 +63,8 @@ gpu::TexturePointer processCubeTextureColorFromImage(const QImage& srcImage, con } // namespace TextureUsage +gpu::TexturePointer processImage(const QByteArray& content, const std::string& url, int maxNumPixels, TextureUsage::Type textureType); + } // namespace image #endif // hifi_image_Image_h diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index cd673cdf98..623832aaa8 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -489,7 +489,7 @@ QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const FBXTexture& textu } model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture, - gpu::TextureType type, MapChannel channel) { + image::TextureUsage::Type type, MapChannel channel) { const auto url = getTextureUrl(baseUrl, fbxTexture); const auto texture = DependencyManager::get()->getTexture(url, type, fbxTexture.content, fbxTexture.maxNumPixels); _textures[channel] = Texture { fbxTexture.name, texture }; @@ -503,7 +503,7 @@ model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, c return map; } -model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, gpu::TextureType type, MapChannel channel) { +model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel) { const auto texture = DependencyManager::get()->getTexture(url, type); _textures[channel].texture = texture; @@ -518,7 +518,7 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur { _textures = Textures(MapChannel::NUM_MAP_CHANNELS); if (!material.albedoTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, gpu::TextureType::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); _albedoTransform = material.albedoTexture.transform; map->setTextureTransform(_albedoTransform); @@ -535,45 +535,45 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur if (!material.normalTexture.filename.isEmpty()) { - auto type = (material.normalTexture.isBumpmap ? gpu::TextureType::BUMP_TEXTURE : gpu::TextureType::NORMAL_TEXTURE); + auto type = (material.normalTexture.isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE); auto map = fetchTextureMap(textureBaseUrl, material.normalTexture, type, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } if (!material.roughnessTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, gpu::TextureType::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } else if (!material.glossTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, gpu::TextureType::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, image::TextureUsage::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } if (!material.metallicTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, gpu::TextureType::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } else if (!material.specularTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, gpu::TextureType::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, image::TextureUsage::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } if (!material.occlusionTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, gpu::TextureType::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); map->setTextureTransform(material.occlusionTexture.transform); setTextureMap(MapChannel::OCCLUSION_MAP, map); } if (!material.emissiveTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, gpu::TextureType::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); setTextureMap(MapChannel::EMISSIVE_MAP, map); } if (!material.scatteringTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, gpu::TextureType::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); setTextureMap(MapChannel::SCATTERING_MAP, map); } if (!material.lightmapTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, gpu::TextureType::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); _lightmapTransform = material.lightmapTexture.transform; _lightmapParams = material.lightmapParams; map->setTextureTransform(_lightmapTransform); @@ -596,7 +596,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!albedoName.isEmpty()) { auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, gpu::TextureType::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); map->setTextureTransform(_albedoTransform); // when reassigning the albedo texture we also check for the alpha channel used as opacity map->setUseAlphaChannel(true); @@ -605,45 +605,45 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!normalName.isEmpty()) { auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, gpu::TextureType::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } if (!roughnessName.isEmpty()) { auto url = textureMap.contains(roughnessName) ? textureMap[roughnessName].toUrl() : QUrl(); // FIXME: If passing a gloss map instead of a roughmap how do we know? - auto map = fetchTextureMap(url, gpu::TextureType::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } if (!metallicName.isEmpty()) { auto url = textureMap.contains(metallicName) ? textureMap[metallicName].toUrl() : QUrl(); // FIXME: If passing a specular map instead of a metallic how do we know? - auto map = fetchTextureMap(url, gpu::TextureType::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } if (!occlusionName.isEmpty()) { auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, gpu::TextureType::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); setTextureMap(MapChannel::OCCLUSION_MAP, map); } if (!emissiveName.isEmpty()) { auto url = textureMap.contains(emissiveName) ? textureMap[emissiveName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, gpu::TextureType::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); setTextureMap(MapChannel::EMISSIVE_MAP, map); } if (!scatteringName.isEmpty()) { auto url = textureMap.contains(scatteringName) ? textureMap[scatteringName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, gpu::TextureType::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); setTextureMap(MapChannel::SCATTERING_MAP, map); } if (!lightmapName.isEmpty()) { auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, gpu::TextureType::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); map->setTextureTransform(_lightmapTransform); map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); setTextureMap(MapChannel::LIGHTMAP_MAP, map); diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index ea86b819da..f23cba04a0 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -183,8 +183,8 @@ private: // Helpers for the ctors QUrl getTextureUrl(const QUrl& baseUrl, const FBXTexture& fbxTexture); model::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture, - gpu::TextureType type, MapChannel channel); - model::TextureMapPointer fetchTextureMap(const QUrl& url, gpu::TextureType type, MapChannel channel); + image::TextureUsage::Type type, MapChannel channel); + model::TextureMapPointer fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel); Transform _albedoTransform; Transform _lightmapTransform; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 9720b2ea5e..f6e256bb06 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -166,18 +166,18 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() { /// Extra data for creating textures. class TextureExtra { public: - gpu::TextureType type; + image::TextureUsage::Type type; const QByteArray& content; int maxNumPixels; }; ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels) { auto byteArray = QByteArray(); - TextureExtra extra = { (gpu::TextureType)type, byteArray, maxNumPixels }; + TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels }; return ResourceCache::prefetch(url, &extra); } -NetworkTexturePointer TextureCache::getTexture(const QUrl& url, gpu::TextureType type, const QByteArray& content, int maxNumPixels) { +NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) { TextureExtra extra = { type, content, maxNumPixels }; return ResourceCache::getResource(url, QUrl(), &extra).staticCast(); } @@ -210,7 +210,7 @@ gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, co return result; } -gpu::TexturePointer getFallbackTextureForType(gpu::TextureType type) { +gpu::TexturePointer getFallbackTextureForType(image::TextureUsage::Type type) { gpu::TexturePointer result; auto textureCache = DependencyManager::get(); // Since this can be called on a background thread, there's a chance that the cache @@ -219,27 +219,27 @@ gpu::TexturePointer getFallbackTextureForType(gpu::TextureType type) { return result; } switch (type) { - case gpu::DEFAULT_TEXTURE: - case gpu::ALBEDO_TEXTURE: - case gpu::ROUGHNESS_TEXTURE: - case gpu::OCCLUSION_TEXTURE: + case image::TextureUsage::DEFAULT_TEXTURE: + case image::TextureUsage::ALBEDO_TEXTURE: + case image::TextureUsage::ROUGHNESS_TEXTURE: + case image::TextureUsage::OCCLUSION_TEXTURE: result = textureCache->getWhiteTexture(); break; - case gpu::NORMAL_TEXTURE: + case image::TextureUsage::NORMAL_TEXTURE: result = textureCache->getBlueTexture(); break; - case gpu::EMISSIVE_TEXTURE: - case gpu::LIGHTMAP_TEXTURE: + case image::TextureUsage::EMISSIVE_TEXTURE: + case image::TextureUsage::LIGHTMAP_TEXTURE: result = textureCache->getBlackTexture(); break; - case gpu::BUMP_TEXTURE: - case gpu::SPECULAR_TEXTURE: - case gpu::GLOSS_TEXTURE: - case gpu::CUBE_TEXTURE: - case gpu::STRICT_TEXTURE: + case image::TextureUsage::BUMP_TEXTURE: + case image::TextureUsage::SPECULAR_TEXTURE: + case image::TextureUsage::GLOSS_TEXTURE: + case image::TextureUsage::CUBE_TEXTURE: + case image::TextureUsage::STRICT_TEXTURE: default: break; } @@ -247,23 +247,23 @@ gpu::TexturePointer getFallbackTextureForType(gpu::TextureType type) { } /// Returns a texture version of an image file -gpu::TexturePointer TextureCache::getImageTexture(const QString& path, gpu::TextureType type, QVariantMap options) { +gpu::TexturePointer TextureCache::getImageTexture(const QString& path, image::TextureUsage::Type type, QVariantMap options) { QImage image = QImage(path); - auto loader = image::getTextureLoaderForType(type, options); + auto loader = image::TextureUsage::getTextureLoaderForType(type, options); return gpu::TexturePointer(loader(image, QUrl::fromLocalFile(path).fileName().toStdString())); } QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) { const TextureExtra* textureExtra = static_cast(extra); - auto type = textureExtra ? textureExtra->type : gpu::DEFAULT_TEXTURE; + auto type = textureExtra ? textureExtra->type : image::TextureUsage::DEFAULT_TEXTURE; auto content = textureExtra ? textureExtra->content : QByteArray(); auto maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; NetworkTexture* texture = new NetworkTexture(url, type, content, maxNumPixels); return QSharedPointer(texture, &Resource::deleter); } -NetworkTexture::NetworkTexture(const QUrl& url, gpu::TextureType type, const QByteArray& content, int maxNumPixels) : +NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) : Resource(url), _type(type), _maxNumPixels(maxNumPixels) diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 95b77bc330..d0600c3dce 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "KTXCache.h" @@ -43,7 +44,7 @@ class NetworkTexture : public Resource, public Texture { Q_OBJECT public: - NetworkTexture(const QUrl& url, gpu::TextureType type, const QByteArray& content, int maxNumPixels); + NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels); QString getType() const override { return "NetworkTexture"; } @@ -51,7 +52,7 @@ public: int getOriginalHeight() const { return _originalHeight; } int getWidth() const { return _width; } int getHeight() const { return _height; } - gpu::TextureType getTextureType() const { return _type; } + image::TextureUsage::Type getTextureType() const { return _type; } gpu::TexturePointer getFallbackTexture() const; @@ -70,7 +71,7 @@ private: friend class KTXReader; friend class ImageReader; - gpu::TextureType _type; + image::TextureUsage::Type _type; KTXFilePointer _file; int _originalWidth { 0 }; int _originalHeight { 0 }; @@ -105,10 +106,10 @@ public: const gpu::TexturePointer& getBlackTexture(); /// Returns a texture version of an image file - static gpu::TexturePointer getImageTexture(const QString& path, gpu::TextureType type = gpu::DEFAULT_TEXTURE, QVariantMap options = QVariantMap()); + static gpu::TexturePointer getImageTexture(const QString& path, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, QVariantMap options = QVariantMap()); /// Loads a texture from the specified URL. - NetworkTexturePointer getTexture(const QUrl& url, gpu::TextureType type = gpu::DEFAULT_TEXTURE, + NetworkTexturePointer getTexture(const QUrl& url, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index 7145f7de5c..8c66442c59 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME procedural) AUTOSCRIBE_SHADER_LIB(gpu model) setup_hifi_library() -link_hifi_libraries(shared gpu gpu-gl networking model model-networking) +link_hifi_libraries(shared gpu gpu-gl networking model model-networking image) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 3bf389973a..454097233a 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -3,7 +3,7 @@ AUTOSCRIBE_SHADER_LIB(gpu model render) # pull in the resources.qrc file qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") setup_hifi_library(Widgets OpenGL Network Qml Quick Script) -link_hifi_libraries(shared ktx gpu model model-networking render animation fbx entities) +link_hifi_libraries(shared ktx gpu model model-networking render animation fbx entities image) if (NOT ANDROID) target_nsight() diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 66c436d1d6..313b176f19 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -199,7 +199,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren { // Grab a texture map representing the different status icons and assign that to the drawStatsuJob auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; - auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath, gpu::TextureType::STRICT_TEXTURE); + auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath, image::TextureUsage::STRICT_TEXTURE); task.addJob("DrawStatus", opaques, DrawStatus(statusIconMap)); } } diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index b0dbbc111b..7b176a6973 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -16,6 +16,6 @@ if (NOT ANDROID) endif () -link_hifi_libraries(shared networking octree gpu ui procedural model model-networking recording avatars fbx entities controllers animation audio physics) +link_hifi_libraries(shared networking octree gpu ui procedural model model-networking recording avatars fbx entities controllers animation audio physics image) # ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit -include_hifi_library_headers(gl) \ No newline at end of file +include_hifi_library_headers(gl) diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt index 79bfd91068..2300a38e56 100644 --- a/plugins/openvr/CMakeLists.txt +++ b/plugins/openvr/CMakeLists.txt @@ -13,7 +13,7 @@ if (WIN32) setup_hifi_plugin(OpenGL Script Qml Widgets) link_hifi_libraries(shared gl networking controllers ui plugins display-plugins ui-plugins input-plugins script-engine - render-utils model gpu gpu-gl render model-networking fbx) + render-utils model gpu gpu-gl render model-networking fbx image) include_hifi_library_headers(octree) diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index 96cede9c43..1e85dd3ea8 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -10,7 +10,7 @@ setup_hifi_project(Quick Gui OpenGL) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries -link_hifi_libraries(shared octree ktx gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics) +link_hifi_libraries(shared octree ktx gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics image) package_libraries_for_deployment() diff --git a/tests/render-texture-load/CMakeLists.txt b/tests/render-texture-load/CMakeLists.txt index 0e5f32f46a..b73b67f56c 100644 --- a/tests/render-texture-load/CMakeLists.txt +++ b/tests/render-texture-load/CMakeLists.txt @@ -10,7 +10,7 @@ setup_hifi_project(Quick Gui OpenGL) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries -link_hifi_libraries(shared octree gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics) +link_hifi_libraries(shared octree gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics image) package_libraries_for_deployment()