From d7bd5e76ca86c4ca5f468d39eaecb588e2680e82 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 23 Apr 2024 23:40:14 +0300 Subject: [PATCH 1/5] Move wrapping flag handling to relevant properties --- components/bgsm/file.hpp | 3 +++ components/nif/property.hpp | 6 ++++++ components/nifosg/nifloader.cpp | 22 ++++++++-------------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/components/bgsm/file.hpp b/components/bgsm/file.hpp index d3fb189256..2fe831e918 100644 --- a/components/bgsm/file.hpp +++ b/components/bgsm/file.hpp @@ -51,6 +51,9 @@ namespace Bgsm MaterialFile() = default; virtual void read(BGSMStream& stream); virtual ~MaterialFile() = default; + + bool wrapT() const { return mClamp & 1; } + bool wrapS() const { return mClamp & 2; } }; struct BGSMFile : MaterialFile diff --git a/components/nif/property.hpp b/components/nif/property.hpp index fbc7e8294c..f8798003d3 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -338,6 +338,9 @@ namespace Nif void read(NIFStream* nif) override; void post(Reader& nif) override; + bool wrapT() const { return mClamp & 1; } + bool wrapS() const { return mClamp & 2; } + bool doubleSided() const { return mShaderFlags2 & BSLSFlag2_DoubleSided; } bool treeAnim() const { return mShaderFlags2 & BSLSFlag2_TreeAnim; } }; @@ -366,6 +369,9 @@ namespace Nif void read(NIFStream* nif) override; + bool wrapT() const { return mClamp & 1; } + bool wrapS() const { return mClamp & 2; } + bool useFalloff() const { return mShaderFlags1 & BSLSFlag1_Falloff; } bool softEffect() const { return mShaderFlags1 & BSLSFlag1_SoftEffect; } bool doubleSided() const { return mShaderFlags2 & BSLSFlag2_DoubleSided; } diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 05a8378c11..0f338aa633 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -2176,8 +2176,8 @@ namespace NifOsg Bgsm::MaterialFilePtr material, osg::StateSet* stateset, std::vector& boundTextures) { const unsigned int uvSet = 0; - const bool wrapS = (material->mClamp >> 1) & 0x1; - const bool wrapT = material->mClamp & 0x1; + const bool wrapS = material->wrapS(); + const bool wrapT = material->wrapT(); if (material->mShaderType == Bgsm::ShaderType::Lighting) { const Bgsm::BGSMFile* bgsm = static_cast(material.get()); @@ -2486,11 +2486,9 @@ namespace NifOsg node->setUserValue("shaderRequired", shaderRequired); osg::StateSet* stateset = node->getOrCreateStateSet(); clearBoundTextures(stateset, boundTextures); - const bool wrapS = (texprop->mClamp >> 1) & 0x1; - const bool wrapT = texprop->mClamp & 0x1; if (!texprop->mTextureSet.empty()) - handleTextureSet( - texprop->mTextureSet.getPtr(), wrapS, wrapT, node->getName(), stateset, boundTextures); + handleTextureSet(texprop->mTextureSet.getPtr(), texprop->wrapS(), texprop->wrapT(), + node->getName(), stateset, boundTextures); handleTextureControllers(texprop, composite, stateset, animflags); if (texprop->refraction()) SceneUtil::setupDistortion(*node, texprop->mRefraction.mStrength); @@ -2534,11 +2532,9 @@ namespace NifOsg handleShaderMaterialNodeProperties(material, stateset, boundTextures); break; } - const bool wrapS = (texprop->mClamp >> 1) & 0x1; - const bool wrapT = texprop->mClamp & 0x1; if (!texprop->mTextureSet.empty()) - handleTextureSet( - texprop->mTextureSet.getPtr(), wrapS, wrapT, node->getName(), stateset, boundTextures); + handleTextureSet(texprop->mTextureSet.getPtr(), texprop->wrapS(), texprop->wrapT(), + node->getName(), stateset, boundTextures); handleTextureControllers(texprop, composite, stateset, animflags); if (texprop->doubleSided()) stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); @@ -2566,11 +2562,9 @@ namespace NifOsg if (!texprop->mSourceTexture.empty()) { const unsigned int uvSet = 0; - const bool wrapS = (texprop->mClamp >> 1) & 0x1; - const bool wrapT = texprop->mClamp & 0x1; unsigned int texUnit = boundTextures.size(); - attachExternalTexture( - "diffuseMap", texprop->mSourceTexture, wrapS, wrapT, uvSet, stateset, boundTextures); + attachExternalTexture("diffuseMap", texprop->mSourceTexture, texprop->wrapS(), texprop->wrapT(), + uvSet, stateset, boundTextures); { osg::ref_ptr texMat(new osg::TexMat); // This handles 20.2.0.7 UV settings like 4.0.0.2 UV settings (see NifOsg::UVController) From 713e741f9c7691c49d09e040d8f9046562fe7561 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 23 Apr 2024 23:53:34 +0300 Subject: [PATCH 2/5] Share fog state attributes --- components/nifosg/nifloader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 0f338aa633..fffa5ef48b 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -2603,6 +2603,7 @@ namespace NifOsg fog->setMode(osg::Fog::LINEAR); fog->setColor(osg::Vec4f(fogprop->mColour, 1.f)); fog->setDepth(fogprop->mFogDepth); + fog = shareAttribute(fog); stateset->setAttributeAndModes(fog, osg::StateAttribute::ON); // Intentionally ignoring radial fog flag // We don't really want to override the global setting @@ -2614,6 +2615,7 @@ namespace NifOsg fog->setMode(osg::Fog::LINEAR); fog->setStart(10000000); fog->setEnd(10000000); + fog = shareAttribute(fog); stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); } break; From a513049129e77402f4e08bbb5a58a64e2c2c7ab3 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 24 Apr 2024 00:26:05 +0300 Subject: [PATCH 3/5] Adjust drawable property state changes Reset shininess and specular strength when specular lighting is supposed to be disabled Don't add the material redundantly if a sorter is pushed Don't discard non-default emissive and specular multipliers if there's no sorter or material --- components/nifosg/nifloader.cpp | 37 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index fffa5ef48b..d9442229dd 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -2817,7 +2817,11 @@ namespace NifOsg // While NetImmerse and Gamebryo support specular lighting, Morrowind has its support disabled. if (mVersion <= Nif::NIFFile::VER_MW || !specEnabled) + { mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f)); + mat->setShininess(osg::Material::FRONT_AND_BACK, 0.f); + specStrength = 1.f; + } if (lightmode == Nif::NiVertexColorProperty::LightMode::LightMode_Emissive) { @@ -2848,32 +2852,31 @@ namespace NifOsg mat->setColorMode(osg::Material::OFF); } - if (!mPushedSorter && !hasSortAlpha && mHasStencilProperty) - setBin_Traversal(node->getOrCreateStateSet()); - - if (!mPushedSorter && !hasMatCtrl && mat->getColorMode() == osg::Material::OFF - && mat->getEmission(osg::Material::FRONT_AND_BACK) == osg::Vec4f(0, 0, 0, 1) - && mat->getDiffuse(osg::Material::FRONT_AND_BACK) == osg::Vec4f(1, 1, 1, 1) - && mat->getAmbient(osg::Material::FRONT_AND_BACK) == osg::Vec4f(1, 1, 1, 1) - && mat->getShininess(osg::Material::FRONT_AND_BACK) == 0 - && mat->getSpecular(osg::Material::FRONT_AND_BACK) == osg::Vec4f(0.f, 0.f, 0.f, 0.f)) + if (hasMatCtrl || mat->getColorMode() != osg::Material::OFF + || mat->getEmission(osg::Material::FRONT_AND_BACK) != osg::Vec4f(0, 0, 0, 1) + || mat->getDiffuse(osg::Material::FRONT_AND_BACK) != osg::Vec4f(1, 1, 1, 1) + || mat->getAmbient(osg::Material::FRONT_AND_BACK) != osg::Vec4f(1, 1, 1, 1) + || mat->getShininess(osg::Material::FRONT_AND_BACK) != 0 + || mat->getSpecular(osg::Material::FRONT_AND_BACK) != osg::Vec4f(0.f, 0.f, 0.f, 0.f)) { - // default state, skip - return; + mat = shareAttribute(mat); + node->getOrCreateStateSet()->setAttributeAndModes(mat, osg::StateAttribute::ON); } - mat = shareAttribute(mat); - - osg::StateSet* stateset = node->getOrCreateStateSet(); - stateset->setAttributeAndModes(mat, osg::StateAttribute::ON); if (emissiveMult != 1.f) - stateset->addUniform(new osg::Uniform("emissiveMult", emissiveMult)); + node->getOrCreateStateSet()->addUniform(new osg::Uniform("emissiveMult", emissiveMult)); + if (specStrength != 1.f) - stateset->addUniform(new osg::Uniform("specStrength", specStrength)); + node->getOrCreateStateSet()->addUniform(new osg::Uniform("specStrength", specStrength)); if (!mPushedSorter) + { + if (!hasSortAlpha && mHasStencilProperty) + setBin_Traversal(node->getOrCreateStateSet()); return; + } + osg::StateSet* stateset = node->getOrCreateStateSet(); auto assignBin = [&](Nif::NiSortAdjustNode::SortingMode mode, int type) { if (mode == Nif::NiSortAdjustNode::SortingMode::Off) { From 745be2e91bc986dddde47f211cf6a8552726c503 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 24 Apr 2024 01:32:12 +0300 Subject: [PATCH 4/5] Implement NifOsg::Fog::compare() --- components/nifosg/fog.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/components/nifosg/fog.hpp b/components/nifosg/fog.hpp index 5c49392a24..74bad98da5 100644 --- a/components/nifosg/fog.hpp +++ b/components/nifosg/fog.hpp @@ -15,6 +15,21 @@ namespace NifOsg META_StateAttribute(NifOsg, Fog, FOG) + int compare(const StateAttribute& sa) const override + { + COMPARE_StateAttribute_Types(Fog, sa); + + COMPARE_StateAttribute_Parameter(_mode); + COMPARE_StateAttribute_Parameter(_density); + // _start and _end are intentionally ignored as they go unused + COMPARE_StateAttribute_Parameter(_color); + COMPARE_StateAttribute_Parameter(_fogCoordinateSource); + COMPARE_StateAttribute_Parameter(_useRadialFog); + COMPARE_StateAttribute_Parameter(mDepth); + + return 0; + } + void setDepth(float depth) { mDepth = depth; } float getDepth() const { return mDepth; } From 7f13f6a4e920ea26721e80862e4e3fe35f6b3a47 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 25 Apr 2024 03:09:04 +0300 Subject: [PATCH 5/5] Use osg::Fog::compare in NifOsg::Fog::compare --- components/nifosg/fog.hpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/components/nifosg/fog.hpp b/components/nifosg/fog.hpp index 74bad98da5..4557092477 100644 --- a/components/nifosg/fog.hpp +++ b/components/nifosg/fog.hpp @@ -17,16 +17,10 @@ namespace NifOsg int compare(const StateAttribute& sa) const override { - COMPARE_StateAttribute_Types(Fog, sa); - - COMPARE_StateAttribute_Parameter(_mode); - COMPARE_StateAttribute_Parameter(_density); - // _start and _end are intentionally ignored as they go unused - COMPARE_StateAttribute_Parameter(_color); - COMPARE_StateAttribute_Parameter(_fogCoordinateSource); - COMPARE_StateAttribute_Parameter(_useRadialFog); + if (const int base = osg::Fog::compare(sa); base != 0) + return base; + const Fog& rhs = static_cast(sa); COMPARE_StateAttribute_Parameter(mDepth); - return 0; }