diff --git a/components/bgsm/file.hpp b/components/bgsm/file.hpp index b409752d74..f2e9904715 100644 --- a/components/bgsm/file.hpp +++ b/components/bgsm/file.hpp @@ -53,6 +53,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/fog.hpp b/components/nifosg/fog.hpp index 5c49392a24..4557092477 100644 --- a/components/nifosg/fog.hpp +++ b/components/nifosg/fog.hpp @@ -15,6 +15,15 @@ namespace NifOsg META_StateAttribute(NifOsg, Fog, FOG) + int compare(const StateAttribute& sa) const override + { + if (const int base = osg::Fog::compare(sa); base != 0) + return base; + const Fog& rhs = static_cast(sa); + COMPARE_StateAttribute_Parameter(mDepth); + return 0; + } + void setDepth(float depth) { mDepth = depth; } float getDepth() const { return mDepth; } diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 05a8378c11..d9442229dd 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) @@ -2609,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 @@ -2620,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; @@ -2821,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) { @@ -2852,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) {