Update NIF property loading, first pass

Revise all FO3+ shader properties (attempt reading FO4, FO76 and Starfield properties)
Use constants for most instances of property flags
Drop invalid usage of non-existent double-sided flag for BSShader
Make formatting more consistent, drop unnecessary comments
macos_ci_fix
Alexei Kotov 1 year ago
parent 18b6eba709
commit 9ae1077808

@ -187,9 +187,9 @@ osg::Group {
init(node); init(node);
Nif::BSShaderPPLightingProperty property; Nif::BSShaderPPLightingProperty property;
property.recType = Nif::RC_BSShaderPPLightingProperty; property.recType = Nif::RC_BSShaderPPLightingProperty;
property.textureSet = nullptr; property.mTextureSet = nullptr;
property.mController = nullptr; property.mController = nullptr;
property.type = GetParam().mShaderType; property.mType = GetParam().mShaderType;
node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property)); node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node); file.mRoots.push_back(&node);
@ -217,7 +217,7 @@ osg::Group {
property.recType = Nif::RC_BSLightingShaderProperty; property.recType = Nif::RC_BSLightingShaderProperty;
property.mTextureSet = nullptr; property.mTextureSet = nullptr;
property.mController = nullptr; property.mController = nullptr;
property.type = GetParam().mShaderType; property.mType = GetParam().mShaderType;
node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property)); node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node); file.mRoots.push_back(&node);

@ -55,6 +55,7 @@ namespace Nif
void NiTexturingProperty::read(NIFStream* nif) void NiTexturingProperty::read(NIFStream* nif)
{ {
Property::read(nif); Property::read(nif);
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD
|| nif->getVersion() >= NIFStream::generateVersion(20, 1, 0, 2)) || nif->getVersion() >= NIFStream::generateVersion(20, 1, 0, 2))
flags = nif->getUShort(); flags = nif->getUShort();
@ -95,103 +96,247 @@ namespace Nif
void NiTexturingProperty::post(Reader& nif) void NiTexturingProperty::post(Reader& nif)
{ {
Property::post(nif); Property::post(nif);
for (size_t i = 0; i < textures.size(); i++) for (size_t i = 0; i < textures.size(); i++)
textures[i].post(nif); textures[i].post(nif);
for (size_t i = 0; i < shaderTextures.size(); i++) for (size_t i = 0; i < shaderTextures.size(); i++)
shaderTextures[i].post(nif); shaderTextures[i].post(nif);
} }
void BSSPParallaxParams::read(NIFStream* nif)
{
nif->read(mMaxPasses);
nif->read(mScale);
}
void BSSPRefractionParams::read(NIFStream* nif)
{
nif->read(mStrength);
nif->read(mPeriod);
}
void BSShaderProperty::read(NIFStream* nif) void BSShaderProperty::read(NIFStream* nif)
{ {
NiShadeProperty::read(nif); NiShadeProperty::read(nif);
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
{ {
type = nif->getUInt(); nif->read(mType);
flags1 = nif->getUInt(); nif->read(mShaderFlags1);
flags2 = nif->getUInt(); nif->read(mShaderFlags2);
envMapIntensity = nif->getFloat(); nif->read(mEnvMapScale);
} }
} }
void BSShaderLightingProperty::read(NIFStream* nif) void BSShaderLightingProperty::read(NIFStream* nif)
{ {
BSShaderProperty::read(nif); BSShaderProperty::read(nif);
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
clamp = nif->getUInt(); nif->read(mClamp);
} }
void BSShaderPPLightingProperty::read(NIFStream* nif) void BSShaderPPLightingProperty::read(NIFStream* nif)
{ {
BSShaderLightingProperty::read(nif); BSShaderLightingProperty::read(nif);
textureSet.read(nif);
if (nif->getBethVersion() <= 14) mTextureSet.read(nif);
return; if (nif->getBethVersion() >= 15)
refraction.strength = nif->getFloat(); mRefraction.read(nif);
refraction.period = nif->getInt(); if (nif->getBethVersion() >= 25)
if (nif->getBethVersion() <= 24) mParallax.read(nif);
return;
parallax.passes = nif->getFloat();
parallax.scale = nif->getFloat();
} }
void BSShaderPPLightingProperty::post(Reader& nif) void BSShaderPPLightingProperty::post(Reader& nif)
{ {
BSShaderLightingProperty::post(nif); BSShaderLightingProperty::post(nif);
textureSet.post(nif);
mTextureSet.post(nif);
} }
void BSShaderNoLightingProperty::read(NIFStream* nif) void BSShaderNoLightingProperty::read(NIFStream* nif)
{ {
BSShaderLightingProperty::read(nif); BSShaderLightingProperty::read(nif);
filename = nif->getSizedString();
mFilename = nif->getSizedString();
if (nif->getBethVersion() >= 27) if (nif->getBethVersion() >= 27)
falloffParams = nif->getVector4(); nif->read(mFalloffParams);
} }
void BSSPLuminanceParams::read(NIFStream* nif)
{
nif->read(mLumEmittance);
nif->read(mExposureOffset);
nif->read(mFinalExposureMin);
nif->read(mFinalExposureMax);
};
void BSSPWetnessParams::read(NIFStream* nif)
{
nif->read(mSpecScale);
nif->read(mSpecPower);
nif->read(mMinVar);
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_FO4)
nif->read(mEnvMapScale);
nif->read(mFresnelPower);
nif->read(mMetalness);
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO4)
nif->skip(4); // Unknown
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
nif->skip(4); // Unknown
};
void BSSPMLParallaxParams::read(NIFStream* nif)
{
nif->read(mInnerLayerThickness);
nif->read(mRefractionScale);
nif->read(mInnerLayerTextureScale);
nif->read(mEnvMapScale);
};
void BSSPTranslucencyParams::read(NIFStream* nif)
{
nif->read(mSubsurfaceColor);
nif->read(mTransmissiveScale);
nif->read(mTurbulence);
nif->read(mThickObject);
nif->read(mMixAlbedo);
};
void BSLightingShaderProperty::read(NIFStream* nif) void BSLightingShaderProperty::read(NIFStream* nif)
{ {
type = nif->getUInt(); if (nif->getBethVersion() <= 139)
nif->read(mType);
BSShaderProperty::read(nif); BSShaderProperty::read(nif);
flags1 = nif->getUInt();
flags2 = nif->getUInt(); if (nif->getBethVersion() <= 130)
nif->skip(8); // UV offset {
nif->skip(8); // UV scale nif->read(mShaderFlags1);
nif->read(mShaderFlags2);
}
else if (nif->getBethVersion() >= 132)
{
uint32_t numShaderFlags1 = 0, numShaderFlags2 = 0;
nif->read(numShaderFlags1);
if (nif->getBethVersion() >= 152)
nif->read(numShaderFlags2);
nif->readVector(mShaderFlags1Hashes, numShaderFlags1);
nif->readVector(mShaderFlags2Hashes, numShaderFlags2);
}
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
nif->read(mType);
nif->read(mUVOffset);
nif->read(mUVScale);
mTextureSet.read(nif); mTextureSet.read(nif);
mEmissive = nif->getVector3(); nif->read(mEmissive);
mEmissiveMult = nif->getFloat(); nif->read(mEmissiveMult);
mClamp = nif->getUInt();
mAlpha = nif->getFloat(); if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4)
nif->getFloat(); // Refraction strength nif->read(mRootMaterial);
mGlossiness = nif->getFloat();
mSpecular = nif->getVector3(); if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF)
mSpecStrength = nif->getFloat(); nif->skip(4); // Unknown float
nif->skip(8); // Lighting effects
switch (static_cast<BSLightingShaderType>(type)) nif->read(mClamp);
nif->read(mAlpha);
nif->read(mRefractionStrength);
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
nif->read(mGlossiness);
else
nif->read(mSmoothness);
nif->read(mSpecular);
nif->read(mSpecStrength);
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
nif->readArray(mLightingEffects);
else if (nif->getBethVersion() <= 139)
{
nif->read(mSubsurfaceRolloff);
nif->read(mRimlightPower);
if (mRimlightPower == std::numeric_limits<float>::max())
nif->read(mBacklightPower);
}
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4)
{
nif->read(mGrayscaleToPaletteScale);
nif->read(mFresnelPower);
mWetness.read(nif);
}
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF)
mLuminance.read(nif);
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76)
{
nif->read(mDoTranslucency);
if (mDoTranslucency)
mTranslucency.read(nif);
if (nif->get<uint8_t>() != 0)
{
mTextureArrays.resize(nif->get<uint32_t>());
for (std::vector<std::string>& textureArray : mTextureArrays)
nif->getSizedStrings(textureArray, nif->get<uint32_t>());
}
}
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF)
{
nif->skip(4); // Unknown
nif->skip(4); // Unknown
nif->skip(2); // Unknown
}
// TODO: consider separating this switch for pre-FO76 and FO76+
switch (static_cast<BSLightingShaderType>(mType))
{ {
case BSLightingShaderType::ShaderType_EnvMap: case BSLightingShaderType::ShaderType_EnvMap:
nif->skip(4); // Environment map scale if (nif->getBethVersion() <= 139)
nif->read(mEnvMapScale);
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4)
{
nif->read(mUseSSR);
nif->read(mWetnessUseSSR);
}
break;
case BSLightingShaderType::ShaderType_FaceTint:
// Skin tint shader in FO76+
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
nif->read(mSkinTintColor);
break; break;
case BSLightingShaderType::ShaderType_SkinTint: case BSLightingShaderType::ShaderType_SkinTint:
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
nif->read(mHairTintColor);
else if (nif->getBethVersion() <= 130)
mSkinTintColor = { nif->get<osg::Vec3f>(), 1.f };
else if (nif->getBethVersion() <= 139)
nif->read(mSkinTintColor);
// Hair tint shader in FO76+
else if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
nif->read(mHairTintColor);
break;
case BSLightingShaderType::ShaderType_HairTint: case BSLightingShaderType::ShaderType_HairTint:
nif->skip(12); // Tint color if (nif->getBethVersion() <= 139)
nif->read(mHairTintColor);
break; break;
case BSLightingShaderType::ShaderType_ParallaxOcc: case BSLightingShaderType::ShaderType_ParallaxOcc:
nif->skip(4); // Max passes mParallax.read(nif);
nif->skip(4); // Scale
break; break;
case BSLightingShaderType::ShaderType_MultiLayerParallax: case BSLightingShaderType::ShaderType_MultiLayerParallax:
nif->skip(4); // Inner layer thickness mMultiLayerParallax.read(nif);
nif->skip(4); // Refraction scale
nif->skip(8); // Inner layer texture scale
nif->skip(4); // Environment map strength
break; break;
case BSLightingShaderType::ShaderType_SparkleSnow: case BSLightingShaderType::ShaderType_SparkleSnow:
nif->skip(16); // Sparkle parameters nif->read(mSparkle);
break; break;
case BSLightingShaderType::ShaderType_EyeEnvmap: case BSLightingShaderType::ShaderType_EyeEnvmap:
nif->skip(4); // Cube map scale nif->read(mCubeMapScale);
nif->skip(12); // Left eye cube map offset nif->read(mLeftEyeReflectionCenter);
nif->skip(12); // Right eye cube map offset nif->read(mRightEyeReflectionCenter);
break; break;
default: default:
break; break;
@ -201,31 +346,80 @@ namespace Nif
void BSLightingShaderProperty::post(Reader& nif) void BSLightingShaderProperty::post(Reader& nif)
{ {
BSShaderProperty::post(nif); BSShaderProperty::post(nif);
mTextureSet.post(nif); mTextureSet.post(nif);
} }
void BSEffectShaderProperty::read(NIFStream* nif) void BSEffectShaderProperty::read(NIFStream* nif)
{ {
BSShaderProperty::read(nif); BSShaderProperty::read(nif);
flags1 = nif->getUInt();
flags2 = nif->getUInt(); if (nif->getBethVersion() <= 130)
mUVOffset = nif->getVector2(); {
mUVScale = nif->getVector2(); nif->read(mShaderFlags1);
nif->read(mShaderFlags2);
}
else if (nif->getBethVersion() >= 132)
{
uint32_t numShaderFlags1 = 0, numShaderFlags2 = 0;
nif->read(numShaderFlags1);
if (nif->getBethVersion() >= 152)
nif->read(numShaderFlags2);
nif->readVector(mShaderFlags1Hashes, numShaderFlags1);
nif->readVector(mShaderFlags2Hashes, numShaderFlags2);
}
nif->read(mUVOffset);
nif->read(mUVScale);
mSourceTexture = nif->getSizedString(); mSourceTexture = nif->getSizedString();
unsigned int miscParams = nif->getUInt();
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF)
nif->skip(4); // Unknown
uint32_t miscParams = nif->get<uint32_t>();
mClamp = miscParams & 0xFF; mClamp = miscParams & 0xFF;
mLightingInfluence = (miscParams >> 8) & 0xFF; mLightingInfluence = (miscParams >> 8) & 0xFF;
mEnvMapMinLOD = (miscParams >> 16) & 0xFF; mEnvMapMinLOD = (miscParams >> 16) & 0xFF;
mFalloffParams = nif->getVector4(); nif->read(mFalloffParams);
mBaseColor = nif->getVector4();
mBaseColorScale = nif->getFloat(); if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76)
mFalloffDepth = nif->getFloat(); nif->read(mRefractionPower);
nif->read(mBaseColor);
nif->read(mBaseColorScale);
nif->read(mFalloffDepth);
mGreyscaleTexture = nif->getSizedString(); mGreyscaleTexture = nif->getSizedString();
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4)
{
mEnvMapTexture = nif->getSizedString();
mNormalTexture = nif->getSizedString();
mEnvMaskTexture = nif->getSizedString();
nif->read(mEnvMapScale);
}
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
{
nif->read(mRefractionPower);
mReflectanceTexture = nif->getSizedString();
mLightingTexture = nif->getSizedString();
nif->read(mEmittanceColor);
mEmitGradientTexture = nif->getSizedString();
mLuminance.read(nif);
}
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF)
{
nif->skip(7); // Unknown bytes
nif->skip(6 * sizeof(float)); // Unknown floats
nif->skip(1); // Unknown byte
}
} }
void NiFogProperty::read(NIFStream* nif) void NiFogProperty::read(NIFStream* nif)
{ {
Property::read(nif); Property::read(nif);
mFlags = nif->getUShort(); mFlags = nif->getUShort();
mFogDepth = nif->getFloat(); mFogDepth = nif->getFloat();
mColour = nif->getVector3(); mColour = nif->getVector3();
@ -249,6 +443,7 @@ namespace Nif
void NiVertexColorProperty::read(NIFStream* nif) void NiVertexColorProperty::read(NIFStream* nif)
{ {
Property::read(nif); Property::read(nif);
mFlags = nif->getUShort(); mFlags = nif->getUShort();
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
{ {

@ -1,26 +1,3 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: https://openmw.org/
This file (property.h) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
https://www.gnu.org/licenses/ .
*/
#ifndef OPENMW_COMPONENTS_NIF_PROPERTY_HPP #ifndef OPENMW_COMPONENTS_NIF_PROPERTY_HPP
#define OPENMW_COMPONENTS_NIF_PROPERTY_HPP #define OPENMW_COMPONENTS_NIF_PROPERTY_HPP
@ -109,19 +86,18 @@ namespace Nif
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
// These contain no other data than the 'flags' field
struct NiShadeProperty : public Property struct NiShadeProperty : public Property
{ {
unsigned short flags{ 0u }; uint16_t mFlags{ 0u };
void read(NIFStream* nif) override void read(NIFStream* nif) override
{ {
Property::read(nif); Property::read(nif);
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
flags = nif->getUShort(); nif->read(mFlags);
} }
}; };
enum class BSShaderType : unsigned int enum class BSShaderType : uint32_t
{ {
ShaderType_TallGrass = 0, ShaderType_TallGrass = 0,
ShaderType_Default = 1, ShaderType_Default = 1,
@ -133,42 +109,55 @@ namespace Nif
ShaderType_NoLighting = 33 ShaderType_NoLighting = 33
}; };
enum BSShaderFlags1
{
BSSFlag1_Specular = 0x00000001,
BSSFlag1_Decal = 0x04000000,
};
struct BSSPParallaxParams
{
float mMaxPasses;
float mScale;
void read(NIFStream* nif);
};
struct BSSPRefractionParams
{
float mStrength;
int32_t mPeriod;
void read(NIFStream* nif);
};
struct BSShaderProperty : public NiShadeProperty struct BSShaderProperty : public NiShadeProperty
{ {
unsigned int type{ 0u }, flags1{ 0u }, flags2{ 0u }; uint32_t mType{ 0u }, mShaderFlags1{ 0u }, mShaderFlags2{ 0u };
float envMapIntensity{ 0.f }; float mEnvMapScale{ 0.f };
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
bool specular() const { return flags1 & 1; } // These flags are shared between BSShader and BSLightingShader
bool doubleSided() const { return (flags2 >> 4) & 1; } // Shader-specific flag methods must be handled on per-record basis
bool treeAnim() const { return (flags2 >> 29) & 1; } bool specular() const { return mShaderFlags1 & BSSFlag1_Specular; }
bool decal() const { return (flags1 >> 26) & 1; } bool decal() const { return mShaderFlags1 & BSSFlag1_Decal; }
}; };
struct BSShaderLightingProperty : public BSShaderProperty struct BSShaderLightingProperty : public BSShaderProperty
{ {
unsigned int clamp{ 0u }; unsigned int mClamp{ 0u };
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
bool wrapT() const { return clamp & 1; } bool wrapT() const { return mClamp & 1; }
bool wrapS() const { return (clamp >> 1) & 1; } bool wrapS() const { return mClamp & 2; }
}; };
struct BSShaderPPLightingProperty : public BSShaderLightingProperty struct BSShaderPPLightingProperty : public BSShaderLightingProperty
{ {
BSShaderTextureSetPtr textureSet; BSShaderTextureSetPtr mTextureSet;
struct RefractionSettings BSSPRefractionParams mRefraction;
{ BSSPParallaxParams mParallax;
float strength{ 0.f };
int period{ 0 };
};
struct ParallaxSettings
{
float passes{ 0.f };
float scale{ 0.f };
};
RefractionSettings refraction;
ParallaxSettings parallax;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;
@ -176,13 +165,13 @@ namespace Nif
struct BSShaderNoLightingProperty : public BSShaderLightingProperty struct BSShaderNoLightingProperty : public BSShaderLightingProperty
{ {
std::string filename; std::string mFilename;
osg::Vec4f falloffParams; osg::Vec4f mFalloffParams;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
enum class BSLightingShaderType : unsigned int enum class BSLightingShaderType : uint32_t
{ {
ShaderType_Default = 0, ShaderType_Default = 0,
ShaderType_EnvMap = 1, ShaderType_EnvMap = 1,
@ -207,43 +196,146 @@ namespace Nif
ShaderType_Dismemberment = 20 ShaderType_Dismemberment = 20
}; };
enum BSLightingShaderFlags1
{
BSLSFlag1_Falloff = 0x00000040,
};
enum BSLightingShaderFlags2
{
BSLSFlag2_DoubleSided = 0x00000010,
BSLSFlag2_TreeAnim = 0x20000000,
};
struct BSSPLuminanceParams
{
float mLumEmittance;
float mExposureOffset;
float mFinalExposureMin, mFinalExposureMax;
void read(NIFStream* nif);
};
struct BSSPWetnessParams
{
float mSpecScale;
float mSpecPower;
float mMinVar;
float mEnvMapScale;
float mFresnelPower;
float mMetalness;
void read(NIFStream* nif);
};
struct BSSPMLParallaxParams
{
float mInnerLayerThickness;
float mRefractionScale;
osg::Vec2f mInnerLayerTextureScale;
float mEnvMapScale;
void read(NIFStream* nif);
};
struct BSSPTranslucencyParams
{
osg::Vec3f mSubsurfaceColor;
float mTransmissiveScale;
float mTurbulence;
bool mThickObject;
bool mMixAlbedo;
void read(NIFStream* nif);
};
struct BSLightingShaderProperty : public BSShaderProperty struct BSLightingShaderProperty : public BSShaderProperty
{ {
std::vector<uint32_t> mShaderFlags1Hashes, mShaderFlags2Hashes;
osg::Vec2f mUVOffset, mUVScale;
BSShaderTextureSetPtr mTextureSet; BSShaderTextureSetPtr mTextureSet;
unsigned int mClamp{ 0u }; osg::Vec3f mEmissive;
float mEmissiveMult;
std::string mRootMaterial;
uint32_t mClamp;
float mAlpha; float mAlpha;
float mGlossiness; float mRefractionStrength;
osg::Vec3f mEmissive, mSpecular; float mGlossiness{ 80.f };
float mEmissiveMult, mSpecStrength; float mSmoothness{ 1.f };
osg::Vec3f mSpecular;
float mSpecStrength;
std::array<float, 2> mLightingEffects;
float mSubsurfaceRolloff;
float mRimlightPower;
float mBacklightPower;
float mGrayscaleToPaletteScale{ 1.f };
float mFresnelPower{ 5.f };
BSSPWetnessParams mWetness;
bool mDoTranslucency{ false };
BSSPTranslucencyParams mTranslucency;
std::vector<std::vector<std::string>> mTextureArrays;
BSSPLuminanceParams mLuminance;
bool mUseSSR;
bool mWetnessUseSSR;
osg::Vec4f mSkinTintColor;
osg::Vec3f mHairTintColor;
BSSPParallaxParams mParallax;
BSSPMLParallaxParams mMultiLayerParallax;
osg::Vec4f mSparkle;
float mCubeMapScale;
osg::Vec3f mLeftEyeReflectionCenter;
osg::Vec3f mRightEyeReflectionCenter;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;
bool doubleSided() const { return mShaderFlags2 & BSLSFlag2_DoubleSided; }
bool treeAnim() const { return mShaderFlags2 & BSLSFlag2_TreeAnim; }
}; };
struct BSEffectShaderProperty : public BSShaderProperty struct BSEffectShaderProperty : public BSShaderProperty
{ {
std::vector<uint32_t> mShaderFlags1Hashes, mShaderFlags2Hashes;
osg::Vec2f mUVOffset, mUVScale; osg::Vec2f mUVOffset, mUVScale;
std::string mSourceTexture; std::string mSourceTexture;
unsigned char mClamp; uint8_t mClamp;
unsigned char mLightingInfluence; uint8_t mLightingInfluence;
unsigned char mEnvMapMinLOD; uint8_t mEnvMapMinLOD;
osg::Vec4f mFalloffParams; osg::Vec4f mFalloffParams;
float mRefractionPower;
osg::Vec4f mBaseColor; osg::Vec4f mBaseColor;
float mBaseColorScale; float mBaseColorScale;
float mFalloffDepth; float mFalloffDepth;
std::string mGreyscaleTexture; std::string mGreyscaleTexture;
std::string mEnvMapTexture;
std::string mNormalTexture;
std::string mEnvMaskTexture;
float mEnvMapScale;
std::string mReflectanceTexture;
std::string mLightingTexture;
osg::Vec3f mEmittanceColor;
std::string mEmitGradientTexture;
BSSPLuminanceParams mLuminance;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
bool useFalloff() const { return (flags >> 6) & 1; } bool useFalloff() const { return mShaderFlags1 & BSLSFlag1_Falloff; }
bool doubleSided() const { return mShaderFlags2 & BSLSFlag2_DoubleSided; }
bool treeAnim() const { return mShaderFlags2 & BSLSFlag2_TreeAnim; }
}; };
struct NiDitherProperty : public Property struct NiDitherProperty : public Property
{ {
unsigned short flags; unsigned short flags;
void read(NIFStream* nif) override void read(NIFStream* nif) override
{ {
Property::read(nif); Property::read(nif);
flags = nif->getUShort(); flags = nif->getUShort();
} }
}; };
@ -252,9 +344,11 @@ namespace Nif
{ {
unsigned short flags; unsigned short flags;
unsigned int testFunction; unsigned int testFunction;
void read(NIFStream* nif) override void read(NIFStream* nif) override
{ {
Property::read(nif); Property::read(nif);
flags = nif->getUShort(); flags = nif->getUShort();
testFunction = (flags >> 2) & 0x7; testFunction = (flags >> 2) & 0x7;
if (nif->getVersion() >= NIFStream::generateVersion(4, 1, 0, 12) if (nif->getVersion() >= NIFStream::generateVersion(4, 1, 0, 12)
@ -264,15 +358,17 @@ namespace Nif
bool depthTest() const { return flags & 1; } bool depthTest() const { return flags & 1; }
bool depthWrite() const { return (flags >> 1) & 1; } bool depthWrite() const { return flags & 2; }
}; };
struct NiSpecularProperty : public Property struct NiSpecularProperty : public Property
{ {
unsigned short flags; unsigned short flags;
void read(NIFStream* nif) override void read(NIFStream* nif) override
{ {
Property::read(nif); Property::read(nif);
flags = nif->getUShort(); flags = nif->getUShort();
} }
@ -282,9 +378,11 @@ namespace Nif
struct NiWireframeProperty : public Property struct NiWireframeProperty : public Property
{ {
unsigned short flags; unsigned short flags;
void read(NIFStream* nif) override void read(NIFStream* nif) override
{ {
Property::read(nif); Property::read(nif);
flags = nif->getUShort(); flags = nif->getUShort();
} }
@ -301,6 +399,7 @@ namespace Nif
void read(NIFStream* nif) override void read(NIFStream* nif) override
{ {
Property::read(nif); Property::read(nif);
flags = nif->getUShort(); flags = nif->getUShort();
data.read(nif); data.read(nif);
} }
@ -400,12 +499,19 @@ namespace Nif
struct NiAlphaProperty : public StructPropT<S_AlphaProperty> struct NiAlphaProperty : public StructPropT<S_AlphaProperty>
{ {
bool useAlphaBlending() const { return flags & 1; } enum Flags
{
Flag_Blending = 0x0001,
Flag_Testing = 0x0200,
Flag_NoSorter = 0x2000,
};
bool useAlphaBlending() const { return flags & Flag_Blending; }
bool useAlphaTesting() const { return flags & Flag_Testing; }
bool noSorter() const { return flags & Flag_NoSorter; }
int sourceBlendMode() const { return (flags >> 1) & 0xF; } int sourceBlendMode() const { return (flags >> 1) & 0xF; }
int destinationBlendMode() const { return (flags >> 5) & 0xF; } int destinationBlendMode() const { return (flags >> 5) & 0xF; }
bool noSorter() const { return (flags >> 13) & 1; }
bool useAlphaTesting() const { return (flags >> 9) & 1; }
int alphaTestMode() const { return (flags >> 10) & 0x7; } int alphaTestMode() const { return (flags >> 10) & 0x7; }
}; };
@ -460,5 +566,5 @@ namespace Nif
} }
}; };
} // Namespace }
#endif #endif

@ -2202,18 +2202,16 @@ namespace NifOsg
{ {
auto texprop = static_cast<const Nif::BSShaderPPLightingProperty*>(property); auto texprop = static_cast<const Nif::BSShaderPPLightingProperty*>(property);
bool shaderRequired = true; bool shaderRequired = true;
node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->type))); node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->mType)));
node->setUserValue("shaderRequired", shaderRequired); node->setUserValue("shaderRequired", shaderRequired);
osg::StateSet* stateset = node->getOrCreateStateSet(); osg::StateSet* stateset = node->getOrCreateStateSet();
if (!texprop->textureSet.empty()) if (!texprop->mTextureSet.empty())
{ {
auto textureSet = texprop->textureSet.getPtr(); auto textureSet = texprop->mTextureSet.getPtr();
handleTextureSet( handleTextureSet(
textureSet, texprop->clamp, node->getName(), stateset, imageManager, boundTextures); textureSet, texprop->mClamp, node->getName(), stateset, imageManager, boundTextures);
} }
handleTextureControllers(texprop, composite, imageManager, stateset, animflags); handleTextureControllers(texprop, composite, imageManager, stateset, animflags);
if (texprop->doubleSided())
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
break; break;
} }
case Nif::RC_BSShaderNoLightingProperty: case Nif::RC_BSShaderNoLightingProperty:
@ -2221,10 +2219,10 @@ namespace NifOsg
auto texprop = static_cast<const Nif::BSShaderNoLightingProperty*>(property); auto texprop = static_cast<const Nif::BSShaderNoLightingProperty*>(property);
bool shaderRequired = true; bool shaderRequired = true;
bool useFalloff = false; bool useFalloff = false;
node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->type))); node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->mType)));
node->setUserValue("shaderRequired", shaderRequired); node->setUserValue("shaderRequired", shaderRequired);
osg::StateSet* stateset = node->getOrCreateStateSet(); osg::StateSet* stateset = node->getOrCreateStateSet();
if (!texprop->filename.empty()) if (!texprop->mFilename.empty())
{ {
if (!boundTextures.empty()) if (!boundTextures.empty())
{ {
@ -2233,7 +2231,7 @@ namespace NifOsg
boundTextures.clear(); boundTextures.clear();
} }
std::string filename std::string filename
= Misc::ResourceHelpers::correctTexturePath(texprop->filename, imageManager->getVFS()); = Misc::ResourceHelpers::correctTexturePath(texprop->mFilename, imageManager->getVFS());
osg::ref_ptr<osg::Image> image = imageManager->getImage(filename); osg::ref_ptr<osg::Image> image = imageManager->getImage(filename);
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image); osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
texture2d->setName("diffuseMap"); texture2d->setName("diffuseMap");
@ -2247,20 +2245,18 @@ namespace NifOsg
if (mBethVersion >= 27) if (mBethVersion >= 27)
{ {
useFalloff = true; useFalloff = true;
stateset->addUniform(new osg::Uniform("falloffParams", texprop->falloffParams)); stateset->addUniform(new osg::Uniform("falloffParams", texprop->mFalloffParams));
} }
} }
stateset->addUniform(new osg::Uniform("useFalloff", useFalloff)); stateset->addUniform(new osg::Uniform("useFalloff", useFalloff));
handleTextureControllers(texprop, composite, imageManager, stateset, animflags); handleTextureControllers(texprop, composite, imageManager, stateset, animflags);
if (texprop->doubleSided())
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
break; break;
} }
case Nif::RC_BSLightingShaderProperty: case Nif::RC_BSLightingShaderProperty:
{ {
auto texprop = static_cast<const Nif::BSLightingShaderProperty*>(property); auto texprop = static_cast<const Nif::BSLightingShaderProperty*>(property);
bool shaderRequired = true; bool shaderRequired = true;
node->setUserValue("shaderPrefix", std::string(getBSLightingShaderPrefix(texprop->type))); node->setUserValue("shaderPrefix", std::string(getBSLightingShaderPrefix(texprop->mType)));
node->setUserValue("shaderRequired", shaderRequired); node->setUserValue("shaderRequired", shaderRequired);
osg::StateSet* stateset = node->getOrCreateStateSet(); osg::StateSet* stateset = node->getOrCreateStateSet();
if (!texprop->mTextureSet.empty()) if (!texprop->mTextureSet.empty())

Loading…
Cancel
Save