diff --git a/CHANGELOG.md b/CHANGELOG.md index 645bc59e9e..180e468e33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ Bug #7298: Water ripples from projectiles sometimes are not spawned Bug #7307: Alchemy "Magic Effect" search string does not match on tool tip for effects related to attributes Bug #7322: Shadows don't cover groundcover depending on the view angle and perspective with compute scene bounds = primitives + Bug #7380: NiZBufferProperty issue Bug #7413: Generated wilderness cells don't spawn fish Bug #7415: Unbreakable lock discrepancies Bug #7428: AutoCalc flag is not used to calculate enchantment costs diff --git a/apps/openmw_test_suite/nifosg/testnifloader.cpp b/apps/openmw_test_suite/nifosg/testnifloader.cpp index 5c37cb375f..f05d651301 100644 --- a/apps/openmw_test_suite/nifosg/testnifloader.cpp +++ b/apps/openmw_test_suite/nifosg/testnifloader.cpp @@ -108,7 +108,64 @@ osg::Group { )"); } - std::string formatOsgNodeForShaderProperty(std::string_view shaderPrefix) + std::string formatOsgNodeForBSShaderProperty(std::string_view shaderPrefix) + { + std::ostringstream oss; + oss << R"( +osg::Group { + UniqueID 1 + DataVariance STATIC + UserDataContainer TRUE { + osg::DefaultUserDataContainer { + UniqueID 2 + UDC_UserObjects 1 { + osg::StringValueObject { + UniqueID 3 + Name "fileHash" + } + } + } + } + Children 1 { + osg::Group { + UniqueID 4 + DataVariance STATIC + UserDataContainer TRUE { + osg::DefaultUserDataContainer { + UniqueID 5 + UDC_UserObjects 3 { + osg::UIntValueObject { + UniqueID 6 + Name "recIndex" + Value 4294967295 + } + osg::StringValueObject { + UniqueID 7 + Name "shaderPrefix" + Value ")" + << shaderPrefix << R"(" + } + osg::BoolValueObject { + UniqueID 8 + Name "shaderRequired" + Value TRUE + } + } + } + } + StateSet TRUE { + osg::StateSet { + UniqueID 9 + } + } + } + } +} +)"; + return oss.str(); + } + + std::string formatOsgNodeForBSLightingShaderProperty(std::string_view shaderPrefix) { std::ostringstream oss; oss << R"( @@ -162,7 +219,6 @@ osg::Group { AttributeList 1 { osg::Depth { UniqueID 10 - WriteMask FALSE } Value OFF } @@ -204,7 +260,7 @@ osg::Group { Nif::NIFFile file("test.nif"); file.mRoots.push_back(&node); auto result = Loader::load(file, &mImageManager); - EXPECT_EQ(serialize(*result), formatOsgNodeForShaderProperty(GetParam().mExpectedShaderPrefix)); + EXPECT_EQ(serialize(*result), formatOsgNodeForBSShaderProperty(GetParam().mExpectedShaderPrefix)); } INSTANTIATE_TEST_SUITE_P(Params, NifOsgLoaderBSShaderPrefixTest, ValuesIn(NifOsgLoaderBSShaderPrefixTest::sParams)); @@ -228,11 +284,13 @@ osg::Group { property.mTextureSet = nullptr; property.mController = nullptr; property.mType = GetParam().mShaderType; + property.mShaderFlags1 |= Nif::BSShaderFlags1::BSSFlag1_DepthTest; + property.mShaderFlags2 |= Nif::BSShaderFlags2::BSSFlag2_DepthWrite; node.mProperties.push_back(Nif::RecordPtrT(&property)); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&node); auto result = Loader::load(file, &mImageManager); - EXPECT_EQ(serialize(*result), formatOsgNodeForShaderProperty(GetParam().mExpectedShaderPrefix)); + EXPECT_EQ(serialize(*result), formatOsgNodeForBSLightingShaderProperty(GetParam().mExpectedShaderPrefix)); } INSTANTIATE_TEST_SUITE_P( diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 5b98f54599..b7ef547bd6 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1964,11 +1964,17 @@ namespace NifOsg return texEnv; } - void handleDepthFlags(osg::StateSet* stateset, bool depthTest, bool depthWrite, - osg::Depth::Function depthFunction = osg::Depth::LESS) + void handleDepthFlags(osg::StateSet* stateset, bool depthTest, bool depthWrite) { - stateset->setMode(GL_DEPTH_TEST, depthTest ? osg::StateAttribute::ON : osg::StateAttribute::OFF); - osg::ref_ptr depth = new osg::Depth(depthFunction, 0.0, 1.0, depthWrite); + if (!depthWrite && !depthTest) + { + stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + return; + } + osg::ref_ptr depth = new osg::Depth; + depth->setWriteMask(depthWrite); + if (!depthTest) + depth->setFunction(osg::Depth::ALWAYS); depth = shareAttribute(depth); stateset->setAttributeAndModes(depth, osg::StateAttribute::ON); } @@ -2328,10 +2334,8 @@ namespace NifOsg { const Nif::NiZBufferProperty* zprop = static_cast(property); osg::StateSet* stateset = node->getOrCreateStateSet(); - // Morrowind ignores depth test function, unless a NiStencilProperty is present, in which case it - // uses a fixed depth function of GL_ALWAYS. - osg::Depth::Function depthFunction = hasStencilProperty ? osg::Depth::ALWAYS : osg::Depth::LESS; - handleDepthFlags(stateset, zprop->depthTest(), zprop->depthWrite(), depthFunction); + // The test function from this property seems to be ignored. + handleDepthFlags(stateset, zprop->depthTest(), zprop->depthWrite()); break; } // OSG groups the material properties that NIFs have separate, so we have to parse them all again when @@ -2370,7 +2374,6 @@ namespace NifOsg textureSet, texprop->mClamp, node->getName(), stateset, imageManager, boundTextures); } handleTextureControllers(texprop, composite, imageManager, stateset, animflags); - handleDepthFlags(stateset, texprop->depthTest(), texprop->depthWrite()); break; } case Nif::RC_BSShaderNoLightingProperty: