From 95ea874d43095ed5b48726ef53194cb7b520be91 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 28 Sep 2015 12:43:15 -0700 Subject: [PATCH 1/5] Minor fixes to the way the specular color is interpreted --- libraries/fbx/src/FBXReader.cpp | 2 +- libraries/fbx/src/FBXReader_Material.cpp | 4 +++- libraries/gpu/src/gpu/GLBackend.cpp | 5 ++++- libraries/render-utils/src/Model.cpp | 2 +- libraries/render-utils/src/Model.h | 1 + 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index da240e826a..6268cb3d0a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -934,7 +934,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS _textureContent.insert(filename, content); } } else if (object.name == "Material") { - FBXMaterial material(glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f), glm::vec3(), glm::vec2(0.f, 1.0f), 96.0f, 1.0f); + FBXMaterial material(glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.02f), glm::vec3(), glm::vec2(0.f, 1.0f), 96.0f, 1.0f); foreach (const FBXNode& subobject, object.children) { bool properties = false; QByteArray propertyName; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index c29c64030e..7ba6e6d703 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -139,7 +139,9 @@ void FBXReader::consolidateFBXMaterials() { } else { material._material->setDiffuse(material.diffuseColor); } - material._material->setMetallic(glm::length(material.specularColor)); + + float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z)); + material._material->setMetallic(metallic); material._material->setGloss(material.shininess); if (material.opacity <= 0.0f) { diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index e8bc32d567..85381a3640 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -418,8 +418,10 @@ void GLBackend::resetStages() { #define DO_IT_NOW(call, offset) void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) { - ADD_COMMAND_GL(glActiveBindTexture); + // clean the cache on the texture unit we are going to use + setResourceTexture(unit - GL_TEXTURE0, nullptr); + ADD_COMMAND_GL(glActiveBindTexture); _params.push_back(texture); _params.push_back(target); _params.push_back(unit); @@ -432,6 +434,7 @@ void GLBackend::do_glActiveBindTexture(Batch& batch, uint32 paramOffset) { glBindTexture( batch._params[paramOffset + 1]._uint, batch._params[paramOffset + 0]._uint); + (void) CHECK_GL_ERROR(); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 7aee46b108..71dac8d0df 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -189,6 +189,7 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model: locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); + locations.diffuseTextureUnit = program->getTextures().findLocation("diffuseMap"); locations.normalTextureUnit = program->getTextures().findLocation("normalMap"); locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); @@ -1625,7 +1626,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape // Diffuse if (materialKey.isDiffuseMap()) { auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP]; - if (diffuseMap && diffuseMap->isDefined()) { batch.setResourceTexture(DIFFUSE_MAP_SLOT, diffuseMap->getTextureView()); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index de760dc793..33a2e33316 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -344,6 +344,7 @@ private: int tangent; int alphaThreshold; int texcoordMatrices; + int diffuseTextureUnit; int normalTextureUnit; int specularTextureUnit; int emissiveTextureUnit; From 2a487a79a3551d7500c9e588e5f25bfabce7ed78 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 28 Sep 2015 17:24:31 -0700 Subject: [PATCH 2/5] Getting something done today --- libraries/fbx/src/FBXReader.cpp | 10 ++- libraries/fbx/src/FBXReader.h | 31 ++++--- libraries/fbx/src/FBXReader_Material.cpp | 10 ++- .../src/model-networking/TextureCache.cpp | 5 +- libraries/model/src/model/TextureMap.cpp | 87 +++++++++++++++++++ libraries/model/src/model/TextureMap.h | 1 + 6 files changed, 125 insertions(+), 19 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 6268cb3d0a..1e48a3c011 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -934,7 +934,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS _textureContent.insert(filename, content); } } else if (object.name == "Material") { - FBXMaterial material(glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.02f), glm::vec3(), glm::vec2(0.f, 1.0f), 96.0f, 1.0f); + FBXMaterial material; foreach (const FBXNode& subobject, object.children) { bool properties = false; QByteArray propertyName; @@ -954,9 +954,17 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (property.name == propertyName) { if (property.properties.at(0) == "DiffuseColor") { material.diffuseColor = getVec3(property.properties, index); + } else if (property.properties.at(0) == "Diffuse") { + material.diffuseColor = getVec3(property.properties, index); + } else if (property.properties.at(0) == "DiffuseFactor") { + // material.diffuseFactor = property.properties.at(index).value(); } else if (property.properties.at(0) == "SpecularColor") { material.specularColor = getVec3(property.properties, index); + } else if (property.properties.at(0) == "Specular") { + material.specularColor = getVec3(property.properties, index); + } else if (property.properties.at(0) == "SpecularFactor") { + // material.specularFactor = property.properties.at(index).value(); } else if (property.properties.at(0) == "Emissive") { material.emissiveColor = getVec3(property.properties, index); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 5cfff9826f..63d3c30a91 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -137,21 +137,24 @@ public: class FBXMaterial { public: FBXMaterial() {}; - FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor, - const glm::vec2& emissiveParams, float shininess, float opacity) : - diffuseColor(diffuseColor), - specularColor(specularColor), - emissiveColor(emissiveColor), - emissiveParams(emissiveParams), - shininess(shininess), - opacity(opacity) {} + FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor, + const glm::vec2& emissiveParams, float shininess, float opacity) : + diffuseColor(diffuseColor), + specularColor(specularColor), + emissiveColor(emissiveColor), + emissiveParams(emissiveParams), + shininess(shininess), + opacity(opacity) {} - glm::vec3 diffuseColor; - glm::vec3 specularColor; - glm::vec3 emissiveColor; - glm::vec2 emissiveParams; - float shininess; - float opacity; + glm::vec3 diffuseColor{ 1.0f }; + float diffuseFactor{ 1.0f }; + glm::vec3 specularColor{ 0.02f }; + float specularFactor{ 1.0f }; + + glm::vec3 emissiveColor{ 0.0f }; + glm::vec2 emissiveParams{ 0.0f, 1.0f }; + float shininess{ 23.0f }; + float opacity{ 1.0f }; QString materialID; model::MaterialPointer _material; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 7ba6e6d703..9c108fdc74 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -134,13 +134,17 @@ void FBXReader::consolidateFBXMaterials() { // Finally create the true material representation material._material = std::make_shared(); material._material->setEmissive(material.emissiveColor); - if (glm::all(glm::equal(material.diffuseColor, glm::vec3(0.0f)))) { - material._material->setDiffuse(material.diffuseColor); + + auto diffuse = material.diffuseColor; + diffuse *= material.diffuseFactor; + if (glm::all(glm::equal(diffuse, glm::vec3(0.0f)))) { + material._material->setDiffuse(diffuse); } else { - material._material->setDiffuse(material.diffuseColor); + material._material->setDiffuse(diffuse); } float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z)); + metallic *= material.specularFactor; material._material->setMetallic(metallic); material._material->setGloss(material.shininess); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 0bdc0749f6..3e80b6c7aa 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -230,12 +230,15 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromBumpImage); break; } + case NORMAL_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromNormalImage); + break; + } case CUSTOM_TEXTURE: { return _textureLoader; break; } case DEFAULT_TEXTURE: - case NORMAL_TEXTURE: case SPECULAR_TEXTURE: case EMISSIVE_TEXTURE: default: { diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index e3031e2b4d..4d0ccc27f8 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -137,6 +137,93 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con return theTexture; } + +gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(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; + + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + if (image.hasAlphaChannel()) { + formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (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; +} + int clampPixelCoordinate(int coordinate, int maxCoordinate) { return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate)); } diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index 343ef1f481..107ca2e879 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -32,6 +32,7 @@ public: int _environmentUsage = 0; static gpu::Texture* create2DTextureFromImage(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* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); }; From 1e9c19d535882ec85c52c8d67794c2e1423e5031 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 28 Sep 2015 17:46:48 -0700 Subject: [PATCH 3/5] Clean the Material FBX code and how we use the factor components for diffuse and specular --- libraries/fbx/src/FBXReader.cpp | 4 ++-- libraries/fbx/src/FBXReader_Material.cpp | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1e48a3c011..d6ec59499d 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -957,14 +957,14 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } else if (property.properties.at(0) == "Diffuse") { material.diffuseColor = getVec3(property.properties, index); } else if (property.properties.at(0) == "DiffuseFactor") { - // material.diffuseFactor = property.properties.at(index).value(); + material.diffuseFactor = property.properties.at(index).value(); } else if (property.properties.at(0) == "SpecularColor") { material.specularColor = getVec3(property.properties, index); } else if (property.properties.at(0) == "Specular") { material.specularColor = getVec3(property.properties, index); } else if (property.properties.at(0) == "SpecularFactor") { - // material.specularFactor = property.properties.at(index).value(); + material.specularFactor = property.properties.at(index).value(); } else if (property.properties.at(0) == "Emissive") { material.emissiveColor = getVec3(property.properties, index); diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 9c108fdc74..55a61c77fc 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -136,15 +136,13 @@ void FBXReader::consolidateFBXMaterials() { material._material->setEmissive(material.emissiveColor); auto diffuse = material.diffuseColor; - diffuse *= material.diffuseFactor; - if (glm::all(glm::equal(diffuse, glm::vec3(0.0f)))) { - material._material->setDiffuse(diffuse); - } else { - material._material->setDiffuse(diffuse); - } + // FIXME: Do not use the Diffuse Factor yet as some FBX models have it set to 0 + // diffuse *= material.diffuseFactor; + material._material->setDiffuse(diffuse); float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z)); - metallic *= material.specularFactor; + // FIXME: Do not use the Specular Factor yet as some FBX models have it set to 0 + // metallic *= material.specularFactor; material._material->setMetallic(metallic); material._material->setGloss(material.shininess); From 103e1c76b3d874225132850c64d00f663c84d3f7 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 29 Sep 2015 09:26:29 -0700 Subject: [PATCH 4/5] Member initialization respecting the standard --- libraries/fbx/src/FBXReader.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 63d3c30a91..da6df60f6d 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -147,14 +147,14 @@ public: opacity(opacity) {} glm::vec3 diffuseColor{ 1.0f }; - float diffuseFactor{ 1.0f }; + float diffuseFactor = 1.0f; glm::vec3 specularColor{ 0.02f }; - float specularFactor{ 1.0f }; + float specularFactor = 1.0f; glm::vec3 emissiveColor{ 0.0f }; glm::vec2 emissiveParams{ 0.0f, 1.0f }; - float shininess{ 23.0f }; - float opacity{ 1.0f }; + float shininess = 23.0f; + float opacity = 1.0f; QString materialID; model::MaterialPointer _material; From 73b458c72e531135e35a0d076371f7eb11d11624 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 29 Sep 2015 09:38:01 -0700 Subject: [PATCH 5/5] Cleaning the normal texture load path --- libraries/model/src/model/TextureMap.cpp | 55 +----------------------- 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 4d0ccc27f8..584debafb2 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -141,66 +141,14 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(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 { + } 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; @@ -215,7 +163,6 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (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);