diff --git a/src/esp/gfx/GenericDrawable.cpp b/src/esp/gfx/GenericDrawable.cpp index 5b01a48503..034d81d842 100644 --- a/src/esp/gfx/GenericDrawable.cpp +++ b/src/esp/gfx/GenericDrawable.cpp @@ -198,10 +198,8 @@ void GenericDrawable::draw(const Mn::Matrix4& transformationMatrix, // fragment shader .setObjectId( static_cast(camera).useDrawableIds() ? drawableId_ - : ((((flags_ & Mn::Shaders::PhongGL::Flag::InstancedObjectId) == - Mn::Shaders::PhongGL::Flag::InstancedObjectId) || - ((flags_ & Mn::Shaders::PhongGL::Flag::ObjectIdTexture)) == - Mn::Shaders::PhongGL::Flag::ObjectIdTexture)) + : (((flags_ >= Mn::Shaders::PhongGL::Flag::InstancedObjectId) || + (flags_ >= Mn::Shaders::PhongGL::Flag::ObjectIdTexture))) ? 0 : node_.getSemanticId()) .setTransformationMatrix(transformationMatrix) diff --git a/src/esp/gfx/PbrDrawable.cpp b/src/esp/gfx/PbrDrawable.cpp index a07a609b2a..6ed4a59028 100644 --- a/src/esp/gfx/PbrDrawable.cpp +++ b/src/esp/gfx/PbrDrawable.cpp @@ -7,10 +7,12 @@ #include #include #include +#include #include #include +using Magnum::Math::Literals::operator""_radf; namespace Mn = Magnum; namespace esp { @@ -56,85 +58,41 @@ void PbrDrawable::setMaterialValuesInternal( matCache.metalness = tmpMaterialData.metalness(); matCache.emissiveColor = tmpMaterialData.emissiveColor(); - if (materialData_->hasAttribute("metallicTexturePointer") && - materialData_->hasAttribute("roughnessTexturePointer")) { - CORRADE_ASSERT( - materialData_->attribute( - "metallicTexturePointer") == - materialData_->attribute( - "roughnessTexturePointer"), - "PbrDrawable::setMaterialValuesInternal(): if both the metallic and " - "roughness " - "texture exist, they must be packed in the same texture based on glTF " - "2.0 Spec.", ); - } if (tmpMaterialData.commonTextureMatrix() != Mn::Matrix3{}) { flags_ |= PbrShader::Flag::TextureTransformation; matCache.textureMatrix = tmpMaterialData.commonTextureMatrix(); } - if (materialData_->hasAttribute("baseColorTexturePointer")) { + if (const auto baseColorTexturePtr = + materialData_->findAttribute( + "baseColorTexturePointer")) { flags_ |= PbrShader::Flag::BaseColorTexture; - matCache.baseColorTexture = - materialData_->attribute("baseColorTexturePointer"); + matCache.baseColorTexture = *baseColorTexturePtr; } - matCache.hasAnyMetallicRoughnessTexture = false; - matCache.useMetallicRoughnessTexture = nullptr; - // noneRoughnessMetallic takes precedence, but currently all are - // treated the same way - if (materialData_->hasAttribute("noneRoughnessMetallicTexturePointer")) { + if (const auto noneRoughMetalTexturePtr = + materialData_->findAttribute( + "noneRoughnessMetallicTexturePointer")) { flags_ |= PbrShader::Flag::NoneRoughnessMetallicTexture; - matCache.noneRoughnessMetallicTexture = - materialData_->attribute( - "noneRoughnessMetallicTexturePointer"); - matCache.hasAnyMetallicRoughnessTexture = true; - matCache.useMetallicRoughnessTexture = - matCache.noneRoughnessMetallicTexture; - } - if (materialData_->hasAttribute("roughnessTexturePointer")) { - flags_ |= PbrShader::Flag::RoughnessTexture; - matCache.roughnessTexture = - materialData_->attribute("roughnessTexturePointer"); - if (!matCache.hasAnyMetallicRoughnessTexture) { - matCache.useMetallicRoughnessTexture = matCache.roughnessTexture; - } - matCache.hasAnyMetallicRoughnessTexture = true; - } - if (materialData_->hasAttribute("metallicTexturePointer")) { - flags_ |= PbrShader::Flag::MetallicTexture; - matCache.metallicTexture = - materialData_->attribute("metallicTexturePointer"); - - if (!matCache.hasAnyMetallicRoughnessTexture) { - matCache.useMetallicRoughnessTexture = matCache.metallicTexture; - } - matCache.hasAnyMetallicRoughnessTexture = true; + matCache.noneRoughnessMetallicTexture = *noneRoughMetalTexturePtr; } - CORRADE_ASSERT(((matCache.useMetallicRoughnessTexture != nullptr) == - matCache.hasAnyMetallicRoughnessTexture), - "PbrDrawable::setMaterialValuesInternal(): Error assigning " - "proper Metallic/Roughness texture pointers - either a " - "texture is expected but not present or vice versa.", ); - - if (materialData_->hasAttribute("normalTexturePointer")) { + if (const auto normalTexturePtr = + materialData_->findAttribute( + "normalTexturePointer")) { flags_ |= PbrShader::Flag::NormalTexture; - matCache.normalTexture = - materialData_->attribute("normalTexturePointer"); + matCache.normalTexture = *normalTexturePtr; if (meshAttributeFlags_ & gfx::Drawable::Flag::HasTangent) { flags_ |= PbrShader::Flag::PrecomputedTangent; } - if (tmpMaterialData.normalTextureScale() != 1.0f) { - flags_ |= PbrShader::Flag::NormalTextureScale; - CORRADE_ASSERT(tmpMaterialData.normalTextureScale() > 0.0f, - "PbrDrawable::PbrDrawable(): the normal texture scale " - "must be positive.", ); - } + // normal texture scale + matCache.normalTextureScale = tmpMaterialData.normalTextureScale(); } - if (materialData_->hasAttribute("emissiveTexturePointer")) { + + if (const auto emissiveTexturePtr = + materialData_->findAttribute( + "emissiveTexturePointer")) { flags_ |= PbrShader::Flag::EmissiveTexture; - matCache.emissiveTexture = - materialData_->attribute("emissiveTexturePointer"); + matCache.emissiveTexture = *emissiveTexturePtr; } if (materialData_->attribute("hasPerVertexObjectId")) { flags_ |= PbrShader::Flag::InstancedObjectId; @@ -142,6 +100,225 @@ void PbrDrawable::setMaterialValuesInternal( if (materialData_->isDoubleSided()) { flags_ |= PbrShader::Flag::DoubleSided; } + + //////////////// + // ClearCoat layer + if (materialData_->hasLayer(Mn::Trade::MaterialLayer::ClearCoat)) { + const auto& ccLayer = + materialData_->as(); + float cc_LayerFactor = ccLayer.layerFactor(); + // As per + // https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_clearcoat + // if layer is 0 entire layer is disabled/ignored. + if (cc_LayerFactor > 0.0f) { + // has non-trivial clearcoat layer + flags_ |= PbrShader::Flag::ClearCoatLayer; + // + matCache.clearCoat.factor = cc_LayerFactor; + matCache.clearCoat.roughnessFactor = ccLayer.roughness(); + if (const auto layerTexturePtr = + ccLayer.findAttribute( + "layerFactorTexturePointer")) { + flags_ |= PbrShader::Flag::ClearCoatTexture; + matCache.clearCoat.texture = *layerTexturePtr; + } + + if (const auto roughnessTexturePtr = + ccLayer.findAttribute( + "roughnessTexturePointer")) { + flags_ |= PbrShader::Flag::ClearCoatRoughnessTexture; + matCache.clearCoat.roughnessTexture = *roughnessTexturePtr; + } + + if (const auto normalTexturePtr = + ccLayer.findAttribute( + "normalTexturePointer")) { + flags_ |= PbrShader::Flag::ClearCoatNormalTexture; + matCache.clearCoat.normalTexture = *normalTexturePtr; + matCache.clearCoat.normalTextureScale = ccLayer.normalTextureScale(); + } + + } // non-zero layer factor + } // has clearcoat layer + + //////////////// + // KHR_materials_ior + if (const auto iorLayerID = + materialData_->findLayerId("#KHR_materials_ior")) { + // Read in custom material index of refraction + if (const auto ior = + materialData_->findAttribute(*iorLayerID, "ior")) { + // ior should be >= 1 or 0 (which gives full weight to specular layer + // independent of view angle) + matCache.ior_Index = *ior; + } + + } // has KHR_materials_ior layer + + //////////////// + // KHR_materials_specular layer + if (const auto specularLayerID = + materialData_->findLayerId("#KHR_materials_specular")) { + flags_ |= PbrShader::Flag::SpecularLayer; + /** + * The strength of the specular reflection. Defaults to 1.0f + */ + if (const auto specularFactor = materialData_->findAttribute( + *specularLayerID, "specularFactor")) { + matCache.specularLayer.factor = + Mn::Math::clamp(*specularFactor, 0.0f, 1.0f); + } + + /** + * A texture that defines the strength of the specular + * reflection, stored in the alpha (A) channel. This will be + * multiplied by specularFactor. + */ + if (const auto specularFactorTexture = + materialData_->findAttribute( + *specularLayerID, "specularTexturePointer")) { + flags_ |= PbrShader::Flag::SpecularLayerTexture; + matCache.specularLayer.texture = *specularFactorTexture; + } + /** + * The F0 color of the specular reflection (linear RGB). + */ + if (const auto specularColorFactor = + materialData_->findAttribute(*specularLayerID, + "specularColorFactor")) { + matCache.specularLayer.colorFactor = *specularColorFactor; + } + /** + * A texture that defines the F0 color of the specular + * reflection, stored in the RGB channels and encoded in + * sRGB. This texture will be multiplied by + * specularColorFactor. + */ + if (const auto specularColorTexture = + materialData_->findAttribute( + *specularLayerID, "specularColorTexturePointer")) { + flags_ |= PbrShader::Flag::SpecularLayerColorTexture; + matCache.specularLayer.colorTexture = *specularColorTexture; + } + } // has KHR_materials_specular layer + + /////////////// + // KHR_materials_anisotropy + if (const auto anisotropyLayerID = + materialData_->findLayerId("#KHR_materials_anisotropy")) { + /** + * The anisotropy strength. When anisotropyTexture is present, this value is + * multiplied by the blue channel. Default is 0.0f + */ + if (const auto anisotropyStrength = materialData_->findAttribute( + *anisotropyLayerID, "anisotropyStrength")) { + if (Mn::Math::abs(*anisotropyStrength) > 0.0) { + flags_ |= PbrShader::Flag::AnisotropyLayer; + matCache.anisotropyLayer.factor = + Mn::Math::clamp(*anisotropyStrength, -1.0f, 1.0f); + } + // Early adopters used anisotropy to mean strength + } else if (const auto anisotropyStrength = + materialData_->findAttribute(*anisotropyLayerID, + "anisotropy")) { + if (Mn::Math::abs(*anisotropyStrength) > 0.0) { + flags_ |= PbrShader::Flag::AnisotropyLayer; + matCache.anisotropyLayer.factor = + Mn::Math::clamp(*anisotropyStrength, -1.0f, 1.0f); + } + } + /** + * The rotation of the anisotropy in tangent, bitangent space, measured in + * radians counter-clockwise from the tangent. When anisotropyTexture is + * present, anisotropyRotation provides additional rotation to the vectors + * in the texture. Default is 0.0f + */ + if (const auto anisotropyRotation = materialData_->findAttribute( + *anisotropyLayerID, "anisotropyRotation")) { + if (*anisotropyRotation != 0.0) { + flags_ |= PbrShader::Flag::AnisotropyLayer; + Mn::Rad rotAngle = Mn::Rad{*anisotropyRotation}; + matCache.anisotropyLayer.direction = + Mn::Vector2{Mn::Complex::rotation(rotAngle)}; + } + // Early adopters used anisotropyDirection + } else if (const auto anisotropyRotation = + materialData_->findAttribute( + *anisotropyLayerID, "anisotropyDirection")) { + if (*anisotropyRotation != 0.0) { + flags_ |= PbrShader::Flag::AnisotropyLayer; + Mn::Rad rotAngle = Mn::Rad{*anisotropyRotation}; + matCache.anisotropyLayer.direction = + Mn::Vector2{Mn::Complex::rotation(rotAngle)}; + } + } + + /** + * A texture that defines the anisotropy of the material. Red and green + * channels represent the anisotropy direction in [-1, 1] tangent, + * bitangent space, to be rotated by anisotropyRotation. The blue + * channel contains strength as [0, 1] to be multiplied by + * anisotropyStrength. + */ + if (const auto anisotropyLayerTexture = + materialData_->findAttribute( + *anisotropyLayerID, "anisotropyTexturePointer")) { + // also covers flags_ |= PbrShader::Flag::AnisotropyLayer; + flags_ |= PbrShader::Flag::AnisotropyLayerTexture; + matCache.anisotropyLayer.texture = *anisotropyLayerTexture; + } + } // has KHR_materials_anisotropy + + //////////////// + // KHR_materials_transmission + if (const auto transmissionLayerID = + materialData_->findLayerId("#KHR_materials_transmission")) { + flags_ |= PbrShader::Flag::TransmissionLayer; + // transmissionFactor + if (const auto transmissionFactor = materialData_->findAttribute( + *transmissionLayerID, "transmissionFactor")) { + matCache.transmissionLayer.factor = *transmissionFactor; + } + // transmissionTexturePointer + if (const auto transmissionTexturePointer = + materialData_->findAttribute( + *transmissionLayerID, "transmissionTexturePointer")) { + flags_ |= PbrShader::Flag::TransmissionLayerTexture; + matCache.transmissionLayer.texture = *transmissionTexturePointer; + } + } // has KHR_materials_transmission layer + + //////////////// + // KHR_materials_volume + if (const auto volumeLayerID = + materialData_->findLayerId("#KHR_materials_volume")) { + flags_ |= PbrShader::Flag::VolumeLayer; + + if (const auto thicknessFactor = materialData_->findAttribute( + *volumeLayerID, "thicknessFactor")) { + matCache.volumeLayer.thicknessFactor = *thicknessFactor; + } + + if (const auto thicknessTexturePointer = + materialData_->findAttribute( + *volumeLayerID, "thicknessTexturePointer")) { + flags_ |= PbrShader::Flag::VolumeLayerThicknessTexture; + matCache.volumeLayer.thicknessTexture = *thicknessTexturePointer; + } + + if (const auto attDist = materialData_->findAttribute( + *volumeLayerID, "attenuationDistance")) { + if (*attDist > 0.0f) { + // Can't be 0 or inf + matCache.volumeLayer.attenuationDist = *attDist; + } + } + + if (const auto attenuationColor = materialData_->findAttribute( + *volumeLayerID, "attenuationColor")) { + matCache.volumeLayer.attenuationColor = *attenuationColor; + } + } // has KHR_materials_volume layer } // PbrDrawable::setMaterialValuesInternal void PbrDrawable::setLightSetup(const Mn::ResourceKey& lightSetupKey) { @@ -171,8 +348,8 @@ void PbrDrawable::draw(const Mn::Matrix4& transformationMatrix, // lines") on hard edges. (maybe due to potential numerical issues? we do // not know yet.) /* - if ((flags_ & PbrShader::Flag::DoubleSided) && glIsEnabled(GL_CULL_FACE)) { - Mn::GL::Renderer::disable(Mn::GL::Renderer::Feature::FaceCulling); + if ((flags_ & PbrShader::Flag::DoubleSided) && glIsEnabled(GL_CULL_FACE)) + { Mn::GL::Renderer::disable(Mn::GL::Renderer::Feature::FaceCulling); } */ Mn::Matrix4 modelMatrix = @@ -184,10 +361,10 @@ void PbrDrawable::draw(const Mn::Matrix4& transformationMatrix, // Normal matrix is calculated as `m.inverted().transposed()`, and // `m.inverted()` is the same as // `m.comatrix().transposed()/m.determinant()`. We need the determinant to - // figure out the winding direction as well, thus we calculate it separately - // and then do - // `(m.comatrix().transposed()/determinant).transposed()`, which is the same - // as `m.comatrix()/determinant`. + // figure out the winding direction as well, thus we calculate it + // separately and then do + // `(m.comatrix().transposed()/determinant).transposed()`, which is the + // same as `m.comatrix()/determinant`. Mn::Matrix3x3 normalMatrix = rotScale.comatrix() / normalDet; // Flip winding direction to correct handle backface culling @@ -201,8 +378,7 @@ void PbrDrawable::draw(const Mn::Matrix4& transformationMatrix, // the fragment shader .setObjectId(static_cast(camera).useDrawableIds() ? drawableId_ - : ((flags_ & PbrShader::Flag::InstancedObjectId) == - PbrShader::Flag::InstancedObjectId + : (flags_ >= PbrShader::Flag::InstancedObjectId ? 0 : node_.getSemanticId())) .setProjectionMatrix(camera.projectionMatrix()) @@ -225,13 +401,14 @@ void PbrDrawable::draw(const Mn::Matrix4& transformationMatrix, shader_->bindBaseColorTexture(*matCache.baseColorTexture); } - if (matCache.hasAnyMetallicRoughnessTexture) { + if (flags_ & PbrShader::Flag::NoneRoughnessMetallicTexture) { shader_->bindMetallicRoughnessTexture( - *matCache.useMetallicRoughnessTexture); + *matCache.noneRoughnessMetallicTexture); } if (flags_ & PbrShader::Flag::NormalTexture) { shader_->bindNormalTexture(*matCache.normalTexture); + shader_->setNormalTextureScale(matCache.normalTextureScale); } if (flags_ & PbrShader::Flag::EmissiveTexture) { @@ -285,8 +462,8 @@ void PbrDrawable::draw(const Mn::Matrix4& transformationMatrix, // WE stopped supporting doubleSided material due to lighting artifacts on // hard edges. See comments at the beginning of this function. /* - if ((flags_ & PbrShader::Flag::DoubleSided) && !glIsEnabled(GL_CULL_FACE)) { - Mn::GL::Renderer::enable(Mn::GL::Renderer::Feature::FaceCulling); + if ((flags_ & PbrShader::Flag::DoubleSided) && !glIsEnabled(GL_CULL_FACE)) + { Mn::GL::Renderer::enable(Mn::GL::Renderer::Feature::FaceCulling); } */ } // namespace gfx @@ -307,7 +484,8 @@ PbrDrawable& PbrDrawable::updateShader() { shader_ = shaderManager_.get( getShaderKey(lightCount, flags_)); - // if no shader with desired number of lights and flags exists, create one + // if no shader with desired number of lights and flags exists, create + // one if (!shader_) { shaderManager_.set( shader_.key(), new PbrShader{flags_, lightCount}, diff --git a/src/esp/gfx/PbrDrawable.h b/src/esp/gfx/PbrDrawable.h index a1d6974f70..afee6584b8 100644 --- a/src/esp/gfx/PbrDrawable.h +++ b/src/esp/gfx/PbrDrawable.h @@ -22,6 +22,8 @@ class PbrDrawable : public Drawable { * Magnum MaterialData to speed up access in draw. */ struct PBRMaterialCache { + //////////////// + // Base layer Mn::Color4 baseColor{1.0f}; float roughness = 1.0f; float metalness = 1.0f; @@ -30,20 +32,189 @@ class PbrDrawable : public Drawable { Mn::GL::Texture2D* baseColorTexture = nullptr; - bool hasAnyMetallicRoughnessTexture = false; - - Mn::GL::Texture2D* useMetallicRoughnessTexture = nullptr; /** - * Currently we only support a single NoneMetalnessRoughness texture for - * both metalness and roughness. Separate textures will be stored, but only - * the useMetallicRoughnessTexture should be sent to the shader + * Currently we only support a single noneRoughnessMetallicTexture texture + * for both metalness and roughness. */ Mn::GL::Texture2D* noneRoughnessMetallicTexture = nullptr; - Mn::GL::Texture2D* roughnessTexture = nullptr; - Mn::GL::Texture2D* metallicTexture = nullptr; - Mn::GL::Texture2D* normalTexture = nullptr; Mn::GL::Texture2D* emissiveTexture = nullptr; + + Mn::GL::Texture2D* normalTexture = nullptr; + + float normalTextureScale = 1.0f; + + //////////////// + // ClearCoat layer + + /** + * Structure holding clearcoat layer values + */ + struct ClearCoat { + /** + * Clear coat layer intensity + */ + float factor = 0.0f; + + /** + * Texture defining clearcoat intensity in R channel. Multiplied by scalar + * if both are present. + */ + Mn::GL::Texture2D* texture = nullptr; + + /** + * Clearcoat layer roughness. + */ + float roughnessFactor = 0.0f; + + /** + * Texture describing clear coat roughness in G channel. Multiplied by + * scalar if both are present. + */ + Mn::GL::Texture2D* roughnessTexture = nullptr; + + /** + * Scale value for clearcoat normal texture + */ + float normalTextureScale = 1.0f; + + /** + * Clearcoat Normal map texture, in RGB channels. + */ + Mn::GL::Texture2D* normalTexture = nullptr; + + } clearCoat; + + //////////////// + // KHR_materials_ior + + /** + * Index of refraction of material. Generally between 1-2, although values + * higher than 2 are possible. Defaults to 1.5. + * + * dielectricSpecular = ((ior - 1)/(ior + 1))^2 + * default ior value evaluates to dielectricSpecular = 0.04 + */ + float ior_Index = 1.5; + + //////////////// + // KHR_materials_specular layer + + /** + * Structure holdling specular layer values + */ + struct SpecularLayer { + /** + * The strength of the specular reflection. + */ + float factor = 1.0f; + + /** + * A texture that defines the strength of the specular reflection, stored + * in the alpha (A) channel. This will be multiplied by specularFactor. + */ + Mn::GL::Texture2D* texture = nullptr; + + /** + * The F0 color of the specular reflection (linear RGB). + */ + Mn::Color3 colorFactor{1.0f}; + + /** + * A texture that defines the F0 color of the specular reflection, + * stored in the RGB channels and encoded in sRGB. This texture will be + * multiplied by specularColorFactor. + */ + Mn::GL::Texture2D* colorTexture = nullptr; + + } specularLayer; + + /////////////// + // KHR_materials_anisotropy layer + /** + * Structure holdijng anisotropy layer values + */ + struct AnisotropyLayer { + /** + * The anisotropy strength. When anisotropyTexture is present, this value + * is multiplied by the blue channel. + */ + float factor = 0.0f; + + /** + * [cos(rotation), sin(rotation)] : Built from the rotation of the + * anisotropy in tangent, bitangent space, measured in radians + * counter-clockwise from the tangent. When anisotropyTexture is present, + * anisotropyRotation provides additional rotation to the vectors in the + * texture. + */ + Mn::Vector2 direction{1.0f, 0.0f}; + + /** + * A texture that defines the strength and orientation of the anisotropy + * of the material. Red and green channels represent the anisotropy + * direction in [-1, 1] tangent, bitangent space, to be rotated by + * anisotropyRotation. The blue channel contains strength as [0, 1] to be + * multiplied by anisotropyStrength + */ + Mn::GL::Texture2D* texture = nullptr; + } anisotropyLayer; + + //////////////// + // KHR_materials_transmission + + /** + * Structure holding transmission layer values + */ + struct TransmissionLayer { + /** + * The base percentage of light that is transmitted through the surface. + */ + float factor = 0.0f; + /** + * A texture that defines the transmission percentage of the surface, + * stored in the R channel. This will be multiplied by transmissionFactor. + */ + Mn::GL::Texture2D* texture = nullptr; + } transmissionLayer; + + //////////////// + // KHR_materials_volume + + /** + * Structure holding volume-layer values + */ + struct VolumeLayer { + /** + * The thickness of the volume beneath the surface. The value is given in + * the coordinate space of the mesh. If the value is 0 the material is + * thin-walled. Otherwise the material is a volume boundary. The + * doubleSided property has no effect on volume boundaries. Range is [0, + * +inf). + */ + float thicknessFactor = 0.0f; + + /** + * A texture that defines the thickness, stored in the G channel. This + * will be multiplied by thicknessFactor. Range is [0, 1] + */ + Mn::GL::Texture2D* thicknessTexture = nullptr; + + /** + * Density of the medium given as the average distance that light travels + * in the medium before interacting with a particle. The value is given in + * world space. Range is (0, +inf). Default is inf (treat -1). + */ + float attenuationDist = -1.0f; + + /** + * The color that white light turns into due to absorption when reaching + * the attenuation distance. + */ + + Mn::Color3 attenuationColor{1.0f}; + + } volumeLayer; }; /** diff --git a/src/esp/gfx/PbrShader.cpp b/src/esp/gfx/PbrShader.cpp index 03d776d990..0a575ca81e 100644 --- a/src/esp/gfx/PbrShader.cpp +++ b/src/esp/gfx/PbrShader.cpp @@ -76,8 +76,7 @@ PbrShader::PbrShader(Flags originalFlags, unsigned int lightCount) } // TODO: Occlusion texture to be added. const bool isTextured = bool( - flags_ & (Flag::BaseColorTexture | Flag::RoughnessTexture | - Flag::NoneRoughnessMetallicTexture | Flag::MetallicTexture | + flags_ & (Flag::BaseColorTexture | Flag::NoneRoughnessMetallicTexture | Flag::NormalTexture | Flag::EmissiveTexture)); if (isTextured) { @@ -111,18 +110,12 @@ PbrShader::PbrShader(Flags originalFlags, unsigned int lightCount) : "") .addSource(flags_ & Flag::EmissiveTexture ? "#define EMISSIVE_TEXTURE\n" : "") - .addSource(flags_ & Flag::RoughnessTexture ? "#define ROUGHNESS_TEXTURE\n" - : "") - .addSource(flags_ & Flag::MetallicTexture ? "#define METALLIC_TEXTURE\n" - : "") .addSource(flags_ & Flag::NoneRoughnessMetallicTexture ? "#define NONE_ROUGHNESS_METALLIC_TEXTURE\n" : "") .addSource(flags_ & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") - .addSource(flags_ & Flag::NormalTextureScale - ? "#define NORMAL_TEXTURE_SCALE\n" - : "") .addSource(flags_ & Flag::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(flags_ & Flag::ClearCoatLayer ? "#define CLEAR_COAT\n" : "") .addSource(flags_ & Flag::PrecomputedTangent ? "#define PRECOMPUTED_TANGENT\n" : "") @@ -153,8 +146,7 @@ PbrShader::PbrShader(Flags originalFlags, unsigned int lightCount) setUniform(uniformLocation("BaseColorTexture"), pbrTextureUnitSpace::TextureUnit::BaseColor); } - if (flags_ & (Flag::RoughnessTexture | Flag::MetallicTexture | - Flag::NoneRoughnessMetallicTexture)) { + if (flags_ & Flag::NoneRoughnessMetallicTexture) { setUniform(uniformLocation("MetallicRoughnessTexture"), pbrTextureUnitSpace::TextureUnit::MetallicRoughness); } @@ -220,8 +212,7 @@ PbrShader::PbrShader(Flags originalFlags, unsigned int lightCount) lightDirectionsUniform_ = uniformLocation("LightDirections"); } - if ((flags_ & Flag::NormalTexture) && (flags_ & Flag::NormalTextureScale) && - lightingIsEnabled()) { + if ((flags_ & Flag::NormalTexture) && lightingIsEnabled()) { normalTextureScaleUniform_ = uniformLocation("NormalTextureScale"); } @@ -300,8 +291,7 @@ PbrShader& PbrShader::bindBaseColorTexture(Mn::GL::Texture2D& texture) { PbrShader& PbrShader::bindMetallicRoughnessTexture(Mn::GL::Texture2D& texture) { CORRADE_ASSERT( - flags_ & (Flag::RoughnessTexture | Flag::MetallicTexture | - Flag::NoneRoughnessMetallicTexture), + flags_ & (Flag::NoneRoughnessMetallicTexture), "PbrShader::bindMetallicRoughnessTexture(): the shader was not " "created with metallicRoughness texture enabled.", *this); @@ -562,7 +552,7 @@ PbrShader& PbrShader::setNormalTextureScale(float scale) { "PbrShader::setNormalTextureScale(): the shader was not " "created with normal texture enabled", *this); - if ((flags_ & Flag::NormalTextureScale) && lightingIsEnabled()) { + if (lightingIsEnabled()) { setUniform(normalTextureScaleUniform_, scale); } return *this; diff --git a/src/esp/gfx/PbrShader.h b/src/esp/gfx/PbrShader.h index 5bce3fc516..3f97d9a1af 100644 --- a/src/esp/gfx/PbrShader.h +++ b/src/esp/gfx/PbrShader.h @@ -81,68 +81,31 @@ class PbrShader : public Magnum::GL::AbstractShaderProgram { */ BaseColorTexture = 1 << 0, - /** - * Multiply roughness with the roughness texture. - * This flag term means the roughness texture is independent, and - * "roughness" is stored in the R channel of it. - * NOTE: - * if NoneRoughnessMetallicTexture or OcclusionRoughnessMetallicTexture are - * presented, this texture will be ignored. - * @see @ref setRoughness(), @ref bindRoughnessTexture() - */ - RoughnessTexture = 1 << 1, - - /** - * Multiply metallic with the metallic texture. - * This flag term means the metallic texture is independent, and "metalness" - * is stored in the B channel of it. - * NOTE: - * if NoneRoughnessMetallicTexture or OcclusionRoughnessMetallicTexture are - * presented, this texture will be ignored. - * @see @ref setMetallic(), @ref bindMetallicTexture() - */ - MetallicTexture = 1 << 2, - /** * This flag term means the NoneRoughnessMetallic texture is present, with * the Roughness in G channel and metalness in B channel (R and Alpha * channels are not used). * @see @ref setMetallic(), @ref bindMetallicTexture() */ - NoneRoughnessMetallicTexture = 1 << 3, + NoneRoughnessMetallicTexture = 1 << 1, /* - * The occlusion map texture. + * The occlusion map texture is present. * The occlusion, Roughness and Metalness are packed together in one * texture, with Occlusion in R channel, Roughness in G channel and * metalness in B channel (Alpha channels is not used). */ - PackedOcclusionTexture = 1 << 4, - - /* - * The occlusion map texture. - * The occlusion map texture is separate from the metallicRoughness texture. - * The values are sampled from the R channel. - */ - SeparateOcclusionTexture = 1 << 5, + OcclusionTexture = 1 << 2, /** * Modify normals according to a texture. */ - NormalTexture = 1 << 6, - - /** - * Enable normal texture scale - * the shader expects that - * @ref Flag::NormalTexture is enabled as well. - * @see @ref setNormalTextureScale - */ - NormalTextureScale = 1 << 7, + NormalTexture = 1 << 3, /** * emissive texture */ - EmissiveTexture = 1 << 8, + EmissiveTexture = 1 << 4, /** * Enable texture coordinate transformation. If this flag is set, @@ -154,10 +117,10 @@ class PbrShader : public Magnum::GL::AbstractShaderProgram { * @ref Flag::OcclusionRoughnessMetallicTexture is enabled as well. * @see @ref setTextureMatrix() */ - TextureTransformation = 1 << 9, + TextureTransformation = 1 << 5, /** - * TODO: Do we need instanced object? (instanced texture, istanced id etc.) + * TODO: Do we need instanced object? (instanced texture, instanced id etc.) */ /** @@ -172,41 +135,102 @@ class PbrShader : public Magnum::GL::AbstractShaderProgram { * see PBR fragment shader code for more details * Requires the @ref Tangent4 attribute to be present. */ - PrecomputedTangent = 1 << 10, + PrecomputedTangent = 1 << 6, /** * Enable object ID output for this shader. */ - ObjectId = 1 << 11, + ObjectId = 1 << 7, /** * Support Instanced object ID. Retrieves a per-instance / per-vertex * object ID from the @ref ObjectId attribute. If this is false, the shader * will use the node's semantic ID */ - InstancedObjectId = (1 << 12) | ObjectId, + InstancedObjectId = (1 << 8) | ObjectId, + + /** + * Has ClearCoat layer. + */ + ClearCoatLayer = 1 << 9, + /** + * Has ClearCoat Texture in ClearCoat layer + */ + ClearCoatTexture = (1 << 10) | ClearCoatLayer, + /** + * Has Roughness Texture in ClearCoat layer + */ + ClearCoatRoughnessTexture = (1 << 11) | ClearCoatLayer, + /** + * Has Normal Texture in ClearCoat layer + */ + ClearCoatNormalTexture = (1 << 12) | ClearCoatLayer, + + /** + * Has KHR_materials_specular layer + */ + SpecularLayer = 1 << 13, + /** + * Has Specular Texture in KHR_materials_specular layer + */ + SpecularLayerTexture = (1 << 14) | SpecularLayer, + + /** + * Has Specular Color Texture in KHR_materials_specular layer + */ + SpecularLayerColorTexture = (1 << 15) | SpecularLayer, + + /** + * Has KHR_materials_anisotropy layer + */ + AnisotropyLayer = 1 << 16, + + /** + * Has Anisotropy Texture in KHR_materials_anisotropy layer + */ + AnisotropyLayerTexture = (1 << 17) | AnisotropyLayer, + + /** + * Has KHR_materials_transmission layer + */ + TransmissionLayer = 1 << 18, + /** + * Has transmission texture in KHR_materials_transmission layer + */ + TransmissionLayerTexture = (1 << 19) | TransmissionLayer, + + /** + * Has KHR_materials_volume layer + */ + VolumeLayer = 1 << 20, + + /** + * Has Thickness texture in KHR_materials_volume layer + */ + VolumeLayerThicknessTexture = (1 << 21) | VolumeLayer, + /** * Enable double-sided rendering. * (Temporarily STOP supporting this functionality. See comments in * the PbrDrawable::draw() function) */ - DoubleSided = 1 << 13, + DoubleSided = 1 << 22, /** * Enable image based lighting */ - ImageBasedLighting = 1 << 14, + ImageBasedLighting = 1 << 23, /** * render point light shadows using variance shadow map (VSM) */ - ShadowsVSM = 1 << 15, + ShadowsVSM = 1 << 24, /** * Enable shader debug mode. Then developer can set the uniform * PbrDebugDisplay in the fragment shader for debugging */ - DebugDisplay = 1 << 16, + DebugDisplay = 1 << 25, /* * TODO: alphaMask */ diff --git a/src/shaders/pbr.frag b/src/shaders/pbr.frag index 8c5e858cae..fa7fb8adc4 100644 --- a/src/shaders/pbr.frag +++ b/src/shaders/pbr.frag @@ -57,8 +57,7 @@ uniform MaterialData Material; #if defined(BASECOLOR_TEXTURE) uniform sampler2D BaseColorTexture; #endif -#if defined(METALLIC_TEXTURE) || defined(ROUGHNESS_TEXTURE) || \ - defined(NONE_ROUGHNESS_METALLIC_TEXTURE) +#if defined(NONE_ROUGHNESS_METALLIC_TEXTURE) uniform sampler2D MetallicRoughnessTexture; #endif #if defined(NORMAL_TEXTURE) @@ -312,12 +311,12 @@ void main() { #endif float roughness = Material.roughness; -#if defined(ROUGHNESS_TEXTURE) || defined(NONE_ROUGHNESS_METALLIC_TEXTURE) +#if defined(NONE_ROUGHNESS_METALLIC_TEXTURE) roughness *= texture(MetallicRoughnessTexture, texCoord).g; #endif float metallic = Material.metallic; -#if defined(METALLIC_TEXTURE) || defined(NONE_ROUGHNESS_METALLIC_TEXTURE) +#if defined(NONE_ROUGHNESS_METALLIC_TEXTURE) metallic *= texture(MetallicRoughnessTexture, texCoord).b; #endif