From 6b6a3bcfcaa57c4f8c9eb16b82796b8a99bc82d9 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 16 Jul 2023 20:41:03 +0300 Subject: [PATCH] Make decal rendering more accurate for Skyrim models, reducing Z-fighting --- components/nif/property.hpp | 1 + components/nifosg/nifloader.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/components/nif/property.hpp b/components/nif/property.hpp index bd80d64712..2fb3aa64d1 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -141,6 +141,7 @@ namespace Nif bool doubleSided() const { return (flags2 >> 4) & 1; } bool treeAnim() const { return (flags2 >> 29) & 1; } + bool decal() const { return (flags1 >> 26) & 1; } }; struct BSShaderLightingProperty : public BSShaderProperty diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 98cc25f90d..715c83707d 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -2479,6 +2481,31 @@ namespace NifOsg mat->setShininess(osg::Material::FRONT_AND_BACK, shaderprop->mGlossiness); emissiveMult = shaderprop->mEmissiveMult; specStrength = shaderprop->mSpecStrength; + if (shaderprop->decal()) + { + osg::StateSet* stateset = node->getOrCreateStateSet(); + if (!mPushedSorter && !hasSortAlpha) + stateset->setRenderBinDetails(1, "SORT_BACK_TO_FRONT"); + osg::ref_ptr polygonOffset(new osg::PolygonOffset); + polygonOffset->setUnits(SceneUtil::AutoDepth::isReversed() ? 1.f : -1.f); + polygonOffset->setFactor(SceneUtil::AutoDepth::isReversed() ? 0.65f : -0.65f); + stateset->setAttributeAndModes(polygonOffset, osg::StateAttribute::ON); + } + break; + } + case Nif::RC_BSEffectShaderProperty: + { + auto shaderprop = static_cast(property); + if (shaderprop->decal()) + { + osg::StateSet* stateset = node->getOrCreateStateSet(); + if (!mPushedSorter && !hasSortAlpha) + stateset->setRenderBinDetails(1, "SORT_BACK_TO_FRONT"); + osg::ref_ptr polygonOffset(new osg::PolygonOffset); + polygonOffset->setUnits(SceneUtil::AutoDepth::isReversed() ? 1.f : -1.f); + polygonOffset->setFactor(SceneUtil::AutoDepth::isReversed() ? 0.65f : -0.65f); + stateset->setAttributeAndModes(polygonOffset, osg::StateAttribute::ON); + } break; } default: