Refactoring a bit the texture loaders to factorize work

This commit is contained in:
samcake 2016-04-01 11:44:57 -07:00
parent 582a6b7db3
commit 1ca87fa069
5 changed files with 88 additions and 107 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -31,6 +31,7 @@ typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
enum TextureType {
DEFAULT_TEXTURE,
ALBEDO_TEXTURE,
NORMAL_TEXTURE,
BUMP_TEXTURE,
SPECULAR_TEXTURE,

View file

@ -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<const QRgb*>(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;
}

View file

@ -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);
};