really fix texture baking, and turn off irradiance generation during baking

This commit is contained in:
SamGondelman 2019-04-23 15:47:12 -07:00
parent 7245d1a037
commit 3b746384ca
16 changed files with 34 additions and 35 deletions

View file

@ -31,7 +31,6 @@
#include <FBXWriter.h> #include <FBXWriter.h>
#include "ModelBakingLoggingCategory.h" #include "ModelBakingLoggingCategory.h"
#include "TextureBaker.h"
FBXBaker::FBXBaker(const QUrl& inputModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) : FBXBaker::FBXBaker(const QUrl& inputModelURL, const QString& bakedOutputDirectory, const QString& originalOutputDirectory, bool hasBeenBaked) :
ModelBaker(inputModelURL, bakedOutputDirectory, originalOutputDirectory, hasBeenBaked) { ModelBaker(inputModelURL, bakedOutputDirectory, originalOutputDirectory, hasBeenBaked) {

View file

@ -18,15 +18,11 @@
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
#include "Baker.h" #include "Baker.h"
#include "TextureBaker.h"
#include "ModelBaker.h" #include "ModelBaker.h"
#include "ModelBakingLoggingCategory.h" #include "ModelBakingLoggingCategory.h"
#include <gpu/Texture.h>
#include <FBX.h> #include <FBX.h>
using TextureBakerThreadGetter = std::function<QThread*()>;
class FBXBaker : public ModelBaker { class FBXBaker : public ModelBaker {
Q_OBJECT Q_OBJECT

View file

@ -138,7 +138,7 @@ void MaterialBaker::processMaterial() {
auto baseTextureFileName = _textureFileNamer.createBaseTextureFileName(textureURL.fileName(), type); auto baseTextureFileName = _textureFileNamer.createBaseTextureFileName(textureURL.fileName(), type);
QSharedPointer<TextureBaker> textureBaker { QSharedPointer<TextureBaker> textureBaker {
new TextureBaker(textureURL, type, _textureOutputDir, "", baseTextureFileName, content), new TextureBaker(textureURL, type, _textureOutputDir, baseTextureFileName, content),
&TextureBaker::deleteLater &TextureBaker::deleteLater
}; };
textureBaker->setMapChannel(mapChannel); textureBaker->setMapChannel(mapChannel);

View file

@ -13,13 +13,9 @@
#define hifi_OBJBaker_h #define hifi_OBJBaker_h
#include "Baker.h" #include "Baker.h"
#include "TextureBaker.h"
#include "ModelBaker.h" #include "ModelBaker.h"
#include "ModelBakingLoggingCategory.h" #include "ModelBakingLoggingCategory.h"
using TextureBakerThreadGetter = std::function<QThread*()>;
using NodeID = qlonglong; using NodeID = qlonglong;
class OBJBaker : public ModelBaker { class OBJBaker : public ModelBaker {

View file

@ -33,14 +33,13 @@ const QString BAKED_META_TEXTURE_SUFFIX = ".texmeta.json";
bool TextureBaker::_compressionEnabled = true; bool TextureBaker::_compressionEnabled = true;
TextureBaker::TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType, TextureBaker::TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType,
const QDir& outputDirectory, const QString& metaTexturePathPrefix, const QDir& outputDirectory, const QString& baseFilename,
const QString& baseFilename, const QByteArray& textureContent) : const QByteArray& textureContent) :
_textureURL(textureURL), _textureURL(textureURL),
_originalTexture(textureContent), _originalTexture(textureContent),
_textureType(textureType), _textureType(textureType),
_baseFilename(baseFilename), _baseFilename(baseFilename),
_outputDirectory(outputDirectory), _outputDirectory(outputDirectory)
_metaTexturePathPrefix(metaTexturePathPrefix)
{ {
if (baseFilename.isEmpty()) { if (baseFilename.isEmpty()) {
// figure out the baked texture filename // figure out the baked texture filename
@ -151,7 +150,7 @@ void TextureBaker::processTexture() {
// IMPORTANT: _originalTexture is empty past this point // IMPORTANT: _originalTexture is empty past this point
_originalTexture.clear(); _originalTexture.clear();
_outputFiles.push_back(originalCopyFilePath); _outputFiles.push_back(originalCopyFilePath);
meta.original = _metaTexturePathPrefix + _originalCopyFilePath.fileName(); meta.original = _originalCopyFilePath.fileName();
} }
// Load the copy of the original file from the baked output directory. New images will be created using the original as the source data. // Load the copy of the original file from the baked output directory. New images will be created using the original as the source data.
@ -204,7 +203,7 @@ void TextureBaker::processTexture() {
return; return;
} }
_outputFiles.push_back(filePath); _outputFiles.push_back(filePath);
meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName; meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = fileName;
} }
} }
@ -240,7 +239,7 @@ void TextureBaker::processTexture() {
return; return;
} }
_outputFiles.push_back(filePath); _outputFiles.push_back(filePath);
meta.uncompressed = _metaTexturePathPrefix + fileName; meta.uncompressed = fileName;
} else { } else {
buffer.reset(); buffer.reset();
} }

View file

@ -32,8 +32,8 @@ class TextureBaker : public Baker {
public: public:
TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType, TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType,
const QDir& outputDirectory, const QString& metaTexturePathPrefix = "", const QDir& outputDirectory, const QString& baseFilename = QString(),
const QString& baseFilename = QString(), const QByteArray& textureContent = QByteArray()); const QByteArray& textureContent = QByteArray());
const QByteArray& getOriginalTexture() const { return _originalTexture; } const QByteArray& getOriginalTexture() const { return _originalTexture; }
@ -74,7 +74,6 @@ private:
QString _baseFilename; QString _baseFilename;
QDir _outputDirectory; QDir _outputDirectory;
QString _metaTextureFileName; QString _metaTextureFileName;
QString _metaTexturePathPrefix;
QUrl _originalCopyFilePath; QUrl _originalCopyFilePath;
std::atomic<bool> _abortProcessing { false }; std::atomic<bool> _abortProcessing { false };

View file

@ -37,11 +37,11 @@ ContextMetricCount Texture::_textureCPUCount;
ContextMetricSize Texture::_textureCPUMemSize; ContextMetricSize Texture::_textureCPUMemSize;
std::atomic<Texture::Size> Texture::_allowedCPUMemoryUsage { 0 }; std::atomic<Texture::Size> Texture::_allowedCPUMemoryUsage { 0 };
#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 #define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5
bool recommendedSparseTextures = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES); bool recommendedSparseTextures = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES);
std::atomic<bool> Texture::_enableSparseTextures { recommendedSparseTextures }; std::atomic<bool> Texture::_enableSparseTextures { recommendedSparseTextures };
bool Texture::_generateIrradiance { true };
void Texture::setEnableSparseTextures(bool enabled) { void Texture::setEnableSparseTextures(bool enabled) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View file

@ -550,7 +550,7 @@ public:
void setUsage(const Usage& usage) { _usage = usage; } void setUsage(const Usage& usage) { _usage = usage; }
Usage getUsage() const { return _usage; } Usage getUsage() const { return _usage; }
// For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them availalbe with the texture // For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them available with the texture
bool generateIrradiance(gpu::BackendTarget target); bool generateIrradiance(gpu::BackendTarget target);
const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; } const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; }
void overrideIrradiance(SHPointer irradiance) { _irradiance = irradiance; } void overrideIrradiance(SHPointer irradiance) { _irradiance = irradiance; }
@ -583,6 +583,8 @@ public:
static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat); static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat);
static bool getCompressedFormat(khronos::gl::texture::InternalFormat format, Element& elFormat); static bool getCompressedFormat(khronos::gl::texture::InternalFormat format, Element& elFormat);
static bool _generateIrradiance;
protected: protected:
const TextureUsageType _usageType; const TextureUsageType _usageType;

View file

@ -103,7 +103,7 @@ gpu::Element getHDRTextureFormatForTarget(BackendTarget target, bool compressed)
} }
} }
TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, const QVariantMap& options) { TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type) {
switch (type) { switch (type) {
case ALBEDO_TEXTURE: case ALBEDO_TEXTURE:
return image::TextureUsage::createAlbedoTextureFromImage; return image::TextureUsage::createAlbedoTextureFromImage;
@ -114,7 +114,7 @@ TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, con
case SKY_TEXTURE: case SKY_TEXTURE:
return image::TextureUsage::createCubeTextureFromImage; return image::TextureUsage::createCubeTextureFromImage;
case AMBIENT_TEXTURE: case AMBIENT_TEXTURE:
if (options.value("generateIrradiance", true).toBool()) { if (Texture::_generateIrradiance) {
return image::TextureUsage::createAmbientCubeTextureAndIrradianceFromImage; return image::TextureUsage::createAmbientCubeTextureAndIrradianceFromImage;
} else { } else {
return image::TextureUsage::createAmbientCubeTextureFromImage; return image::TextureUsage::createAmbientCubeTextureFromImage;
@ -388,7 +388,7 @@ gpu::TexturePointer processImage(std::shared_ptr<QIODevice> content, const std::
if (sourceChannel != ColorChannel::NONE) { if (sourceChannel != ColorChannel::NONE) {
mapToRedChannel(image, sourceChannel); mapToRedChannel(image, sourceChannel);
} }
auto loader = TextureUsage::getTextureLoaderForType(textureType); auto loader = TextureUsage::getTextureLoaderForType(textureType);
auto texture = loader(std::move(image), filename, compress, target, abortProcessing); auto texture = loader(std::move(image), filename, compress, target, abortProcessing);

View file

@ -76,7 +76,7 @@ enum Type {
}; };
using TextureLoader = std::function<gpu::TexturePointer(Image&&, const std::string&, bool, gpu::BackendTarget, const std::atomic<bool>&)>; using TextureLoader = std::function<gpu::TexturePointer(Image&&, const std::string&, bool, gpu::BackendTarget, const std::atomic<bool>&)>;
TextureLoader getTextureLoaderForType(Type type, const QVariantMap& options = QVariantMap()); TextureLoader getTextureLoaderForType(Type type);
gpu::TexturePointer create2DTextureFromImage(Image&& image, const std::string& srcImageName, gpu::TexturePointer create2DTextureFromImage(Image&& image, const std::string& srcImageName,
bool compress, gpu::BackendTarget target, const std::atomic<bool>& abortProcessing); bool compress, gpu::BackendTarget target, const std::atomic<bool>& abortProcessing);

View file

@ -311,13 +311,13 @@ gpu::BackendTarget getBackendTarget() {
} }
/// Returns a texture version of an image file /// Returns a texture version of an image file
gpu::TexturePointer TextureCache::getImageTexture(const QString& path, image::TextureUsage::Type type, QVariantMap options) { gpu::TexturePointer TextureCache::getImageTexture(const QString& path, image::TextureUsage::Type type) {
QImage image = QImage(path); QImage image = QImage(path);
if (image.isNull()) { if (image.isNull()) {
qCWarning(networking) << "Unable to load required resource texture" << path; qCWarning(networking) << "Unable to load required resource texture" << path;
return nullptr; return nullptr;
} }
auto loader = image::TextureUsage::getTextureLoaderForType(type, options); auto loader = image::TextureUsage::getTextureLoaderForType(type);
#ifdef USE_GLES #ifdef USE_GLES
constexpr bool shouldCompress = true; constexpr bool shouldCompress = true;

View file

@ -176,7 +176,7 @@ public:
const gpu::TexturePointer& getBlackTexture(); const gpu::TexturePointer& getBlackTexture();
/// Returns a texture version of an image file /// Returns a texture version of an image file
static gpu::TexturePointer getImageTexture(const QString& path, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, QVariantMap options = QVariantMap()); static gpu::TexturePointer getImageTexture(const QString& path, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE);
/// Loads a texture from the specified URL. /// Loads a texture from the specified URL.
NetworkTexturePointer getTexture(const QUrl& url, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, NetworkTexturePointer getTexture(const QUrl& url, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE,

View file

@ -198,10 +198,11 @@ void DomainBaker::addTextureBaker(const QString& property, const QString& url, i
// setup a texture baker for this URL, as long as we aren't baking a texture already // setup a texture baker for this URL, as long as we aren't baking a texture already
if (!_textureBakers.contains(key)) { if (!_textureBakers.contains(key)) {
auto baseTextureFileName = _textureFileNamer.createBaseTextureFileName(textureURL.fileName(), type);
// setup a baker for this texture // setup a baker for this texture
QSharedPointer<TextureBaker> textureBaker { QSharedPointer<TextureBaker> textureBaker {
new TextureBaker(textureURL, type, _contentOutputPath), new TextureBaker(textureURL, type, _contentOutputPath, baseTextureFileName),
&TextureBaker::deleteLater &TextureBaker::deleteLater
}; };
@ -221,7 +222,8 @@ void DomainBaker::addTextureBaker(const QString& property, const QString& url, i
// add this QJsonValueRef to our multi hash so that it can re-write the texture URL // add this QJsonValueRef to our multi hash so that it can re-write the texture URL
// to the baked version once the baker is complete // to the baked version once the baker is complete
_entitiesNeedingRewrite.insert(textureURL, { property, jsonRef }); // it doesn't really matter what this key is as long as it's consistent
_entitiesNeedingRewrite.insert(textureURL.toDisplayString() + type, { property, jsonRef });
} else { } else {
qDebug() << "Texture extension not supported: " << extension; qDebug() << "Texture extension not supported: " << extension;
} }
@ -498,9 +500,11 @@ void DomainBaker::handleFinishedTextureBaker() {
auto baker = qobject_cast<TextureBaker*>(sender()); auto baker = qobject_cast<TextureBaker*>(sender());
if (baker) { if (baker) {
QUrl rewriteKey = baker->getTextureURL().toDisplayString() + baker->getTextureType();
if (!baker->hasErrors()) { if (!baker->hasErrors()) {
// this TextureBaker is done and everything went according to plan // this TextureBaker is done and everything went according to plan
qDebug() << "Re-writing entity references to" << baker->getTextureURL(); qDebug() << "Re-writing entity references to" << baker->getTextureURL() << "with usage" << baker->getTextureType();
// setup a new URL using the prefix we were passed // setup a new URL using the prefix we were passed
auto relativeTextureFilePath = QDir(_contentOutputPath).relativeFilePath(baker->getMetaTextureFileName()); auto relativeTextureFilePath = QDir(_contentOutputPath).relativeFilePath(baker->getMetaTextureFileName());
@ -511,7 +515,7 @@ void DomainBaker::handleFinishedTextureBaker() {
// enumerate the QJsonRef values for the URL of this texture from our multi hash of // enumerate the QJsonRef values for the URL of this texture from our multi hash of
// entity objects needing a URL re-write // entity objects needing a URL re-write
for (auto propertyEntityPair : _entitiesNeedingRewrite.values(baker->getTextureURL())) { for (auto propertyEntityPair : _entitiesNeedingRewrite.values(rewriteKey)) {
QString property = propertyEntityPair.first; QString property = propertyEntityPair.first;
// convert the entity QJsonValueRef to a QJsonObject so we can modify its URL // convert the entity QJsonValueRef to a QJsonObject so we can modify its URL
auto entity = propertyEntityPair.second.toObject(); auto entity = propertyEntityPair.second.toObject();
@ -555,7 +559,7 @@ void DomainBaker::handleFinishedTextureBaker() {
} }
// remove the baked URL from the multi hash of entities needing a re-write // remove the baked URL from the multi hash of entities needing a re-write
_entitiesNeedingRewrite.remove(baker->getTextureURL()); _entitiesNeedingRewrite.remove(rewriteKey);
// drop our shared pointer to this baker so that it gets cleaned up // drop our shared pointer to this baker so that it gets cleaned up
_textureBakers.remove({ baker->getTextureURL(), baker->getTextureType() }); _textureBakers.remove({ baker->getTextureURL(), baker->getTextureType() });

View file

@ -63,6 +63,7 @@ private:
QHash<QUrl, QSharedPointer<ModelBaker>> _modelBakers; QHash<QUrl, QSharedPointer<ModelBaker>> _modelBakers;
QHash<TextureKey, QSharedPointer<TextureBaker>> _textureBakers; QHash<TextureKey, QSharedPointer<TextureBaker>> _textureBakers;
TextureFileNamer _textureFileNamer;
QHash<QUrl, QSharedPointer<JSBaker>> _scriptBakers; QHash<QUrl, QSharedPointer<JSBaker>> _scriptBakers;
QHash<QUrl, QSharedPointer<MaterialBaker>> _materialBakers; QHash<QUrl, QSharedPointer<MaterialBaker>> _materialBakers;

View file

@ -52,6 +52,9 @@ Oven::Oven() {
modelFormatRegistry->addFormat(FBXSerializer()); modelFormatRegistry->addFormat(FBXSerializer());
modelFormatRegistry->addFormat(OBJSerializer()); modelFormatRegistry->addFormat(OBJSerializer());
} }
// We only need to generate irradiance at runtime
gpu::Texture::_generateIrradiance = false;
} }
Oven::~Oven() { Oven::~Oven() {

View file

@ -202,7 +202,7 @@ void SkyboxBakeWidget::bakeButtonClicked() {
ambientMapBaseFilename = QUrl(urlParts.front()).fileName(); ambientMapBaseFilename = QUrl(urlParts.front()).fileName();
// we need to bake the corresponding ambient map too // we need to bake the corresponding ambient map too
addBaker(new TextureBaker(skyboxToBakeURL, image::TextureUsage::AMBIENT_TEXTURE, outputDirectory.absolutePath(), QString(), ambientMapBaseFilename), addBaker(new TextureBaker(skyboxToBakeURL, image::TextureUsage::AMBIENT_TEXTURE, outputDirectory.absolutePath(), ambientMapBaseFilename),
outputDirectory); outputDirectory);
} }
} }