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) {
_hasTransparentTextures = true;
for (auto&& material : _materials) {
if ((material->albedoTexture && !material->albedoTexture->isLoaded()) ||
(material->normalTexture && !material->normalTexture->isLoaded()) ||
@ -145,7 +147,16 @@ bool NetworkGeometry::isLoadedWithTextures() const {
(material->lightmapTexture && !material->lightmapTexture->isLoaded())) {
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;
}
return true;

View file

@ -75,6 +75,10 @@ public:
// true when the requested geometry and its textures are loaded.
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.
const FBXGeometry& getFBXGeometry() const { return *_geometry; }
const std::vector<std::unique_ptr<NetworkMesh>>& getMeshes() const { return _meshes; }
@ -151,6 +155,7 @@ protected:
// cache for isLoadedWithTextures()
mutable bool _isLoadedWithTextures = false;
mutable bool _hasTransparentTextures = false;
};
/// Reads geometry in a worker thread.

View file

@ -80,6 +80,10 @@ void Material::setMetallic(float 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) {
if (textureMap) {
@ -92,6 +96,3 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur
_textureMaps.erase(channel);
}
}

View file

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

View file

@ -15,7 +15,7 @@ struct Material {
vec4 _emissiveOpacity;
vec4 _albedoRoughness;
vec4 _fresnelMetallic;
vec4 _spare;
vec4 _spareKey;
};
uniform materialBuffer {
@ -37,25 +37,23 @@ float getMaterialMetallic(Material m) { return m._fresnelMetallic.a; }
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 ALBEDO_VAL_BIT = 0x00000002;
const int METALLIC_VAL_BIT = 0x00000004;
const int GLOSSY_VAL_BIT = 0x00000008;
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 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;
const int LIGHTMAP_MAP_BIT = 0x00002000;
<@endif@>

View file

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

View file

@ -74,6 +74,21 @@ Model::~Model() {
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) {
_translation = translation;
@ -728,6 +743,8 @@ void Model::setURL(const QUrl& url) {
}
_needsReload = true;
_needsUpdateTransparentTextures = true;
_hasTransparentTextures = false;
_meshGroupsKnown = false;
invalidCalculatedMeshBoxes();
deleteGeometry();

View file

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