From 1ca87fa06962ae3d8645a8665f316492f6926d1f Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 1 Apr 2016 11:44:57 -0700 Subject: [PATCH] Refactoring a bit the texture loaders to factorize work --- .../src/model-networking/ModelCache.cpp | 6 +- .../src/model-networking/TextureCache.cpp | 13 +- .../src/model-networking/TextureCache.h | 1 + libraries/model/src/model/TextureMap.cpp | 171 +++++++----------- libraries/model/src/model/TextureMap.h | 4 + 5 files changed, 88 insertions(+), 107 deletions(-) diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 4120062308..ef78c83d76 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -400,7 +400,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, DEFAULT_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); _albedoTransform = material.albedoTexture.transform; map->setTextureTransform(_albedoTransform); @@ -471,7 +471,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!albedoName.isEmpty()) { auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, DEFAULT_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(url, 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); @@ -480,7 +480,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!normalName.isEmpty()) { auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, DEFAULT_TEXTURE, MapChannel::NORMAL_MAP); + auto map = fetchTextureMap(url, NORMAL_TEXTURE, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 3ba36dc2da..b6c87ca386 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -199,6 +199,18 @@ NetworkTexture::NetworkTexture(const QUrl& url, const TextureLoaderFunc& texture NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { switch (_type) { + case ALBEDO_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createAlbedoTextureFromImage); + break; + } + case EMISSIVE_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createEmissiveTextureFromImage); + break; + } + case LIGHTMAP_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createLightmapTextureFromImage); + break; + } case CUBE_TEXTURE: { return TextureLoaderFunc(model::TextureUsage::createCubeTextureFromImage); break; @@ -228,7 +240,6 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { break; } case DEFAULT_TEXTURE: - case EMISSIVE_TEXTURE: default: { return TextureLoaderFunc(model::TextureUsage::create2DTextureFromImage); break; diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 858a40de36..4fe9a89460 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -31,6 +31,7 @@ typedef QSharedPointer NetworkTexturePointer; enum TextureType { DEFAULT_TEXTURE, + ALBEDO_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index cc44ddef4c..56cc88bfc8 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -49,9 +49,7 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) { _lightmapOffsetScale.y = scale; } - -// FIXME why is this in the model library? Move to GPU or GPU_GL -gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, bool isLinear, bool doCompress, bool generateMips) { QImage image = srcImage; bool validAlpha = false; bool alphaAsMask = true; @@ -63,7 +61,7 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } - + // Actual alpha channel? create the histogram for (int y = 0; y < image.height(); ++y) { const QRgb* data = reinterpret_cast(image.constScanLine(y)); @@ -83,22 +81,58 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05); } - } - + } + if (!validAlpha && image.format() != QImage::Format_RGB888) { image = image.convertToFormat(QImage::Format_RGB888); } - + gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU; + gpu::Element formatMip; + if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + gpu::Semantic gpuSemantic; + gpu::Semantic mipSemantic; + if (isLinear) { + mipSemantic = gpu::SBGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_SRGBA; + } else { + gpuSemantic = gpu::SRGBA; + } + } else { + mipSemantic = gpu::BGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_RGBA; + } else { + gpuSemantic = gpu::RGBA; + } + } + 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::SRGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_SRGB; + } else { + gpuSemantic = gpu::SRGB; + } + } else { + mipSemantic = gpu::RGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_RGB; + } else { + gpuSemantic = gpu::RGB; + } + } + formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); + formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); } theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -113,15 +147,32 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con theTexture->setUsage(usage.build()); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - theTexture->autoGenerateMips(-1); - - // FIXME queue for transfer to GPU and block on completion + if (generateMips) { + theTexture->autoGenerateMips(-1); + } } - + return theTexture; } +gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, false, true); +} + + +gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, true, true); +} + +gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, true, true); +} + +gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, true, true); +} + gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { QImage image = srcImage; @@ -598,89 +649,3 @@ gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, c return theTexture; } - - -gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - QImage image = srcImage; - - int imageArea = image.width() * image.height(); - - int opaquePixels = 0; - int translucentPixels = 0; - //bool isTransparent = false; - int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; - const int EIGHT_BIT_MAXIMUM = 255; - QColor averageColor(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM); - - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - // int redTotal = 0, greenTotal = 0, blueTotal = 0; - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - QRgb rgb = image.pixel(x, y); - redTotal += qRed(rgb); - greenTotal += qGreen(rgb); - blueTotal += qBlue(rgb); - } - } - if (imageArea > 0) { - averageColor.setRgb(redTotal / imageArea, greenTotal / imageArea, blueTotal / imageArea); - } - } else { - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - // check for translucency/false transparency - // int opaquePixels = 0; - // int translucentPixels = 0; - // int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - QRgb rgb = image.pixel(x, y); - redTotal += qRed(rgb); - greenTotal += qGreen(rgb); - blueTotal += qBlue(rgb); - int alpha = qAlpha(rgb); - alphaTotal += alpha; - if (alpha == EIGHT_BIT_MAXIMUM) { - opaquePixels++; - } else if (alpha != 0) { - translucentPixels++; - } - } - } - if (opaquePixels == imageArea) { - qCDebug(modelLog) << "Image with alpha channel is completely opaque:" << QString(srcImageName.c_str()); - image = image.convertToFormat(QImage::Format_RGB888); - } - - averageColor = QColor(redTotal / imageArea, - greenTotal / imageArea, blueTotal / imageArea, alphaTotal / imageArea); - - //isTransparent = (translucentPixels >= imageArea / 2); - } - - gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - - // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); - } - - - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - theTexture->autoGenerateMips(-1); - } - - return theTexture; -} diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index e845aebb81..fa0eea55cb 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -32,6 +32,8 @@ public: int _environmentUsage = 0; static gpu::Texture* create2DTextureFromImage(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); @@ -40,6 +42,8 @@ public: static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); + + static gpu::Texture* process2DTextureColorFromImage(const QImage& imageSrc, bool isLinear, bool doCompress, bool generateMips); };