Merge pull request #7281 from zzmp/fix/png-opacity

Fix materials to honor png texture opacity
This commit is contained in:
samcake 2016-03-15 16:08:36 -07:00
commit f30e8e9e0c
8 changed files with 70 additions and 27 deletions

View file

@ -135,6 +135,8 @@ bool NetworkGeometry::isLoadedWithTextures() const {
} }
if (!_isLoadedWithTextures) { if (!_isLoadedWithTextures) {
_hasTransparentTextures = true;
for (auto&& material : _materials) { for (auto&& material : _materials) {
if ((material->albedoTexture && !material->albedoTexture->isLoaded()) || if ((material->albedoTexture && !material->albedoTexture->isLoaded()) ||
(material->normalTexture && !material->normalTexture->isLoaded()) || (material->normalTexture && !material->normalTexture->isLoaded()) ||
@ -145,7 +147,16 @@ bool NetworkGeometry::isLoadedWithTextures() const {
(material->lightmapTexture && !material->lightmapTexture->isLoaded())) { (material->lightmapTexture && !material->lightmapTexture->isLoaded())) {
return false; return false;
} }
if (material->albedoTexture) {
// Reset the materialKey transparentTexture key only, as it is albedoTexture-dependent
const auto& usage = material->albedoTexture->getGPUTexture()->getUsage();
bool isTransparentTexture = usage.isAlpha() && !usage.isAlphaMask();
material->_material->setTransparentTexture(isTransparentTexture);
// FIXME: Materials with *some* transparent textures seem to give all *other* textures alphas of 0.
_hasTransparentTextures = isTransparentTexture && _hasTransparentTextures;
}
} }
_isLoadedWithTextures = true; _isLoadedWithTextures = true;
} }
return true; return true;

View file

@ -75,6 +75,10 @@ public:
// true when the requested geometry and its textures are loaded. // true when the requested geometry and its textures are loaded.
bool isLoadedWithTextures() const; bool isLoadedWithTextures() const;
// true if the albedo texture has a non-masking alpha channel.
// This can only be known after isLoadedWithTextures().
bool hasTransparentTextures() const { return _hasTransparentTextures; }
// WARNING: only valid when isLoaded returns true. // WARNING: only valid when isLoaded returns true.
const FBXGeometry& getFBXGeometry() const { return *_geometry; } const FBXGeometry& getFBXGeometry() const { return *_geometry; }
const std::vector<std::unique_ptr<NetworkMesh>>& getMeshes() const { return _meshes; } const std::vector<std::unique_ptr<NetworkMesh>>& getMeshes() const { return _meshes; }
@ -151,6 +155,7 @@ protected:
// cache for isLoadedWithTextures() // cache for isLoadedWithTextures()
mutable bool _isLoadedWithTextures = false; mutable bool _isLoadedWithTextures = false;
mutable bool _hasTransparentTextures = false;
}; };
/// Reads geometry in a worker thread. /// Reads geometry in a worker thread.

View file

@ -80,6 +80,10 @@ void Material::setMetallic(float metallic) {
_schemaBuffer.edit<Schema>()._metallic = metallic; _schemaBuffer.edit<Schema>()._metallic = metallic;
} }
void Material::setTransparentTexture(bool isTransparent) {
_key.setTransparentTexture(isTransparent);
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
}
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) { void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
if (textureMap) { if (textureMap) {
@ -92,6 +96,3 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur
_textureMaps.erase(channel); _textureMaps.erase(channel);
} }
} }

View file

@ -32,6 +32,7 @@ public:
METALLIC_VAL_BIT, METALLIC_VAL_BIT,
GLOSSY_VAL_BIT, GLOSSY_VAL_BIT,
TRANSPARENT_VAL_BIT, TRANSPARENT_VAL_BIT,
TRANSPARENT_TEX_VAL_BIT,
EMISSIVE_MAP_BIT, EMISSIVE_MAP_BIT,
ALBEDO_MAP_BIT, ALBEDO_MAP_BIT,
@ -101,6 +102,9 @@ public:
void setAlbedo(bool value) { _flags.set(ALBEDO_VAL_BIT, value); } void setAlbedo(bool value) { _flags.set(ALBEDO_VAL_BIT, value); }
bool isAlbedo() const { return _flags[ALBEDO_VAL_BIT]; } bool isAlbedo() const { return _flags[ALBEDO_VAL_BIT]; }
void setTransparentTexture(bool value) { _flags.set(TRANSPARENT_TEX_VAL_BIT, value); }
bool isTransparentTexture() const { return _flags[TRANSPARENT_TEX_VAL_BIT]; }
void setAlbedoMap(bool value) { _flags.set(ALBEDO_MAP_BIT, value); } void setAlbedoMap(bool value) { _flags.set(ALBEDO_MAP_BIT, value); }
bool isAlbedoMap() const { return _flags[ALBEDO_MAP_BIT]; } bool isAlbedoMap() const { return _flags[ALBEDO_MAP_BIT]; }
@ -164,6 +168,9 @@ public:
Builder& withoutAlbedo() { _value.reset(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } Builder& withoutAlbedo() { _value.reset(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); }
Builder& withAlbedo() { _value.set(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } Builder& withAlbedo() { _value.set(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); }
Builder& withoutTransparentTexture() { _value.reset(MaterialKey::TRANSPARENT_TEX_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_TEX_VAL_BIT); return (*this); }
Builder& withTransparentTexture() { _value.set(MaterialKey::TRANSPARENT_TEX_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_TEX_VAL_BIT); return (*this); }
Builder& withoutAlbedoMap() { _value.reset(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); } Builder& withoutAlbedoMap() { _value.reset(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); }
Builder& withAlbedoMap() { _value.set(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); } Builder& withAlbedoMap() { _value.set(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); }
@ -248,6 +255,8 @@ public:
void setRoughness(float roughness); void setRoughness(float roughness);
float getRoughness() const { return _schemaBuffer.get<Schema>()._roughness; } float getRoughness() const { return _schemaBuffer.get<Schema>()._roughness; }
void setTransparentTexture(bool isTransparent);
// Schema to access the attribute values of the material // Schema to access the attribute values of the material
class Schema { class Schema {
public: public:
@ -260,8 +269,7 @@ public:
glm::vec3 _fresnel{ 0.03f }; // Fresnel value for a default non metallic glm::vec3 _fresnel{ 0.03f }; // Fresnel value for a default non metallic
float _metallic{ 0.0f }; // Not Metallic float _metallic{ 0.0f }; // Not Metallic
glm::vec3 _spare{ 0.0f };
glm::vec3 _spare0{ 0.0f };
uint32_t _key{ 0 }; // a copy of the materialKey uint32_t _key{ 0 }; // a copy of the materialKey

View file

@ -15,7 +15,7 @@ struct Material {
vec4 _emissiveOpacity; vec4 _emissiveOpacity;
vec4 _albedoRoughness; vec4 _albedoRoughness;
vec4 _fresnelMetallic; vec4 _fresnelMetallic;
vec4 _spare; vec4 _spareKey;
}; };
uniform materialBuffer { uniform materialBuffer {
@ -37,25 +37,23 @@ float getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }
float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); } float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }
int getMaterialKey(Material m) { return floatBitsToInt(m._spare.w); } int getMaterialKey(Material m) { return floatBitsToInt(m._spareKey.w); }
const int EMISSIVE_VAL_BIT = 0x00000001; const int EMISSIVE_VAL_BIT = 0x00000001;
const int ALBEDO_VAL_BIT = 0x00000002; const int ALBEDO_VAL_BIT = 0x00000002;
const int METALLIC_VAL_BIT = 0x00000004; const int METALLIC_VAL_BIT = 0x00000004;
const int GLOSSY_VAL_BIT = 0x00000008; const int GLOSSY_VAL_BIT = 0x00000008;
const int TRANSPARENT_VAL_BIT = 0x00000010; const int TRANSPARENT_VAL_BIT = 0x00000010;
const int TRANSPARENT_TEX_VAL_BIT = 0x00000020;
const int EMISSIVE_MAP_BIT = 0x00000040;
const int ALBEDO_MAP_BIT = 0x00000080;
const int METALLIC_MAP_BIT = 0x00000100;
const int ROUGHNESS_MAP_BIT = 0x00000200;
const int TRANSPARENT_MAP_BIT = 0x00000400;
const int NORMAL_MAP_BIT = 0x00000800;
const int OCCLUSION_MAP_BIT = 0x00001000;
const int EMISSIVE_MAP_BIT = 0x00000020; const int LIGHTMAP_MAP_BIT = 0x00002000;
const int ALBEDO_MAP_BIT = 0x00000040;
const int METALLIC_MAP_BIT = 0x00000080;
const int ROUGHNESS_MAP_BIT = 0x00000100;
const int TRANSPARENT_MAP_BIT = 0x00000200;
const int NORMAL_MAP_BIT = 0x00000400;
const int OCCLUSION_MAP_BIT = 0x00000800;
const int LIGHTMAP_MAP_BIT = 0x00001000;
<@endif@> <@endif@>

View file

@ -81,7 +81,7 @@ ItemKey MeshPartPayload::getKey() const {
if (_drawMaterial) { if (_drawMaterial) {
auto matKey = _drawMaterial->getKey(); auto matKey = _drawMaterial->getKey();
if (matKey.isTransparent() || matKey.isTransparentMap()) { if (matKey.isTransparent() || matKey.isTransparentTexture() || matKey.isTransparentMap()) {
builder.withTransparent(); builder.withTransparent();
} }
} }
@ -100,7 +100,7 @@ ShapeKey MeshPartPayload::getShapeKey() const {
} }
ShapeKey::Builder builder; ShapeKey::Builder builder;
if (drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap()) { if (drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentTexture() || drawMaterialKey.isTransparentMap()) {
builder.withTranslucent(); builder.withTranslucent();
} }
if (drawMaterialKey.isNormalMap()) { if (drawMaterialKey.isNormalMap()) {
@ -365,7 +365,7 @@ ItemKey ModelMeshPartPayload::getKey() const {
if (_drawMaterial) { if (_drawMaterial) {
auto matKey = _drawMaterial->getKey(); auto matKey = _drawMaterial->getKey();
if (matKey.isTransparent() || matKey.isTransparentMap()) { if (matKey.isTransparent() || matKey.isTransparentTexture() || matKey.isTransparentMap()) {
builder.withTransparent(); builder.withTransparent();
} }
} }
@ -412,7 +412,8 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
drawMaterialKey = _drawMaterial->getKey(); drawMaterialKey = _drawMaterial->getKey();
} }
bool isTranslucent = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); bool isTranslucent =
drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentTexture() || drawMaterialKey.isTransparentMap();
bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty();
bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasSpecular = drawMaterialKey.isMetallicMap();
bool hasLightmap = drawMaterialKey.isLightmapMap(); bool hasLightmap = drawMaterialKey.isLightmapMap();

View file

@ -74,6 +74,21 @@ Model::~Model() {
AbstractViewStateInterface* Model::_viewState = NULL; AbstractViewStateInterface* Model::_viewState = NULL;
bool Model::needsFixupInScene() {
if (readyToAddToScene()) {
// Once textures are loaded, fixup if they are now transparent
if (!_needsReload && _needsUpdateTransparentTextures && _geometry->isLoadedWithTextures()) {
_needsUpdateTransparentTextures = false;
if (_hasTransparentTextures != _geometry->hasTransparentTextures()) {
return true;
}
}
if (!_readyWhenAdded) {
return true;
}
}
return false;
}
void Model::setTranslation(const glm::vec3& translation) { void Model::setTranslation(const glm::vec3& translation) {
_translation = translation; _translation = translation;
@ -728,6 +743,8 @@ void Model::setURL(const QUrl& url) {
} }
_needsReload = true; _needsReload = true;
_needsUpdateTransparentTextures = true;
_hasTransparentTextures = false;
_meshGroupsKnown = false; _meshGroupsKnown = false;
invalidCalculatedMeshBoxes(); invalidCalculatedMeshBoxes();
deleteGeometry(); deleteGeometry();

View file

@ -70,7 +70,7 @@ public:
// new Scene/Engine rendering support // new Scene/Engine rendering support
void setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scene); void setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scene);
bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } bool needsFixupInScene();
bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { bool readyToAddToScene(RenderArgs* renderArgs = nullptr) {
return !_needsReload && isRenderable() && isActive() && isLoaded(); return !_needsReload && isRenderable() && isActive() && isLoaded();
} }
@ -365,10 +365,12 @@ protected:
QSet<std::shared_ptr<MeshPartPayload>> _renderItemsSet; QSet<std::shared_ptr<MeshPartPayload>> _renderItemsSet;
QMap<render::ItemID, render::PayloadPointer> _renderItems; QMap<render::ItemID, render::PayloadPointer> _renderItems;
bool _readyWhenAdded = false; bool _readyWhenAdded { false };
bool _needsReload = true; bool _needsReload { true };
bool _needsUpdateClusterMatrices = true; bool _needsUpdateClusterMatrices { true };
bool _showCollisionHull = false; bool _needsUpdateTransparentTextures { true };
bool _hasTransparentTextures { false };
bool _showCollisionHull { false };
friend class ModelMeshPartPayload; friend class ModelMeshPartPayload;
RigPointer _rig; RigPointer _rig;