From 50b90a594d6016f170b44ec622d5515a2c1281f9 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Thu, 8 Oct 2020 03:39:27 +0300 Subject: [PATCH] Loading and basic handling of BSLightingShaderProperty --- components/nif/niffile.cpp | 1 + components/nif/property.cpp | 56 ++++++++++++++++++++ components/nif/property.hpp | 63 +++++++++++++++++----- components/nif/record.hpp | 3 +- components/nifosg/nifloader.cpp | 93 +++++++++++++++++++++++++++------ 5 files changed, 186 insertions(+), 30 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 82dab3bcee..f11b75d218 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -152,6 +152,7 @@ static std::map makeFactory() factory["bhkListShape"] = {&construct , RC_bhkListShape }; factory["bhkRigidBody"] = {&construct , RC_bhkRigidBody }; factory["bhkRigidBodyT"] = {&construct , RC_bhkRigidBodyT }; + factory["BSLightingShaderProperty"] = {&construct , RC_BSLightingShaderProperty }; return factory; } diff --git a/components/nif/property.cpp b/components/nif/property.cpp index 1d2dd885d4..70acbb82ae 100644 --- a/components/nif/property.cpp +++ b/components/nif/property.cpp @@ -146,6 +146,62 @@ void BSShaderNoLightingProperty::read(NIFStream *nif) falloffParams = nif->getVector4(); } +void BSLightingShaderProperty::read(NIFStream *nif) +{ + type = nif->getUInt(); + BSShaderProperty::read(nif); + flags1 = nif->getUInt(); + flags2 = nif->getUInt(); + nif->skip(8); // UV offset + nif->skip(8); // UV scale + mTextureSet.read(nif); + mEmissive = nif->getVector3(); + mEmissiveMult = nif->getFloat(); + mClamp = nif->getUInt(); + mAlpha = nif->getFloat(); + nif->getFloat(); // Refraction strength + mGlossiness = nif->getFloat(); + mSpecular = nif->getVector3(); + mSpecStrength = nif->getFloat(); + nif->skip(8); // Lighting effects + switch (static_cast(type)) + { + case BSLightingShaderType::ShaderType_EnvMap: + nif->skip(4); // Environment map scale + break; + case BSLightingShaderType::ShaderType_SkinTint: + case BSLightingShaderType::ShaderType_HairTint: + nif->skip(12); // Tint color + break; + case BSLightingShaderType::ShaderType_ParallaxOcc: + nif->skip(4); // Max passes + nif->skip(4); // Scale + break; + case BSLightingShaderType::ShaderType_MultiLayerParallax: + nif->skip(4); // Inner layer thickness + nif->skip(4); // Refraction scale + nif->skip(4); // Inner layer texture scale + nif->skip(4); // Environment map strength + break; + case BSLightingShaderType::ShaderType_SparkleSnow: + nif->skip(16); // Sparkle parameters + break; + case BSLightingShaderType::ShaderType_EyeEnvmap: + nif->skip(4); // Cube map scale + nif->skip(12); // Left eye cube map offset + nif->skip(12); // Right eye cube map offset + break; + default: + break; + } +} + +void BSLightingShaderProperty::post(NIFFile *nif) +{ + BSShaderProperty::post(nif); + mTextureSet.post(nif); +} + void NiFogProperty::read(NIFStream *nif) { Property::read(nif); diff --git a/components/nif/property.hpp b/components/nif/property.hpp index 9c76f6d6ec..a428d6a7e1 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -116,20 +116,21 @@ struct NiShadeProperty : public Property } }; -struct BSShaderProperty : public NiShadeProperty + +enum class BSShaderType : unsigned int { - enum BSShaderType - { - SHADER_TALL_GRASS = 0, - SHADER_DEFAULT = 1, - SHADER_SKY = 10, - SHADER_SKIN = 14, - SHADER_WATER = 17, - SHADER_LIGHTING30 = 29, - SHADER_TILE = 32, - SHADER_NOLIGHTING = 33 - }; + ShaderType_TallGrass = 0, + ShaderType_Default = 1, + ShaderType_Sky = 10, + ShaderType_Skin = 14, + ShaderType_Water = 17, + ShaderType_Lighting30 = 29, + ShaderType_Tile = 32, + ShaderType_NoLighting = 33 +}; +struct BSShaderProperty : public NiShadeProperty +{ unsigned int type{0u}, flags1{0u}, flags2{0u}; float envMapIntensity{0.f}; void read(NIFStream *nif) override; @@ -169,6 +170,44 @@ struct BSShaderNoLightingProperty : public BSShaderLightingProperty void read(NIFStream *nif) override; }; +enum class BSLightingShaderType : unsigned int +{ + ShaderType_Default = 0, + ShaderType_EnvMap = 1, + ShaderType_Glow = 2, + ShaderType_Parallax = 3, + ShaderType_FaceTint = 4, + ShaderType_SkinTint = 5, + ShaderType_HairTint = 6, + ShaderType_ParallaxOcc = 7, + ShaderType_MultitexLand = 8, + ShaderType_LODLand = 9, + ShaderType_Snow = 10, + ShaderType_MultiLayerParallax = 11, + ShaderType_TreeAnim = 12, + ShaderType_LODObjects = 13, + ShaderType_SparkleSnow = 14, + ShaderType_LODObjectsHD = 15, + ShaderType_EyeEnvmap = 16, + ShaderType_Cloud = 17, + ShaderType_LODNoise = 18, + ShaderType_MultitexLandLODBlend = 19, + ShaderType_Dismemberment = 20 +}; + +struct BSLightingShaderProperty : public BSShaderProperty +{ + BSShaderTextureSetPtr mTextureSet; + unsigned int mClamp{0u}; + float mAlpha; + float mGlossiness; + osg::Vec3f mEmissive, mSpecular; + float mEmissiveMult, mSpecStrength; + + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + struct NiDitherProperty : public Property { unsigned short flags; diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 5fb50a05e5..b38186bd04 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -139,7 +139,8 @@ enum RecordType RC_bhkBoxShape, RC_bhkListShape, RC_bhkRigidBody, - RC_bhkRigidBodyT + RC_bhkRigidBodyT, + RC_BSLightingShaderProperty }; /// Base class for all records diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 2fa533518c..90046ecff1 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1721,28 +1721,64 @@ namespace NifOsg } } - const std::string& getNVShaderPrefix(unsigned int type) const + const std::string& getBSShaderPrefix(unsigned int type) const { - static const std::map mapping = - { - {Nif::BSShaderProperty::SHADER_TALL_GRASS, std::string()}, - {Nif::BSShaderProperty::SHADER_DEFAULT, "nv_default"}, - {Nif::BSShaderProperty::SHADER_SKY, std::string()}, - {Nif::BSShaderProperty::SHADER_SKIN, std::string()}, - {Nif::BSShaderProperty::SHADER_WATER, std::string()}, - {Nif::BSShaderProperty::SHADER_LIGHTING30, std::string()}, - {Nif::BSShaderProperty::SHADER_TILE, std::string()}, - {Nif::BSShaderProperty::SHADER_NOLIGHTING, "nv_nolighting"}, + static const std::unordered_map mapping = + { + {Nif::BSShaderType::ShaderType_TallGrass, std::string()}, + {Nif::BSShaderType::ShaderType_Default, "nv_default"}, + {Nif::BSShaderType::ShaderType_Sky, std::string()}, + {Nif::BSShaderType::ShaderType_Skin, std::string()}, + {Nif::BSShaderType::ShaderType_Water, std::string()}, + {Nif::BSShaderType::ShaderType_Lighting30, std::string()}, + {Nif::BSShaderType::ShaderType_Tile, std::string()}, + {Nif::BSShaderType::ShaderType_NoLighting, "nv_nolighting"}, }; - auto prefix = mapping.find(type); + auto prefix = mapping.find(static_cast(type)); if (prefix == mapping.end()) - Log(Debug::Warning) << "Unknown shader type " << type << " in " << mFilename; + Log(Debug::Warning) << "Unknown BSShaderType " << type << " in " << mFilename; else if (prefix->second.empty()) - Log(Debug::Warning) << "Unhandled shader type " << type << " in " << mFilename; + Log(Debug::Warning) << "Unhandled BSShaderType " << type << " in " << mFilename; else return prefix->second; - return mapping.at(Nif::BSShaderProperty::SHADER_DEFAULT); + return mapping.at(Nif::BSShaderType::ShaderType_Default); + } + + const std::string& getBSLightingShaderPrefix(unsigned int type) const + { + static const std::unordered_map mapping = + { + {Nif::BSLightingShaderType::ShaderType_Default, "nv_default"}, + {Nif::BSLightingShaderType::ShaderType_EnvMap, std::string()}, + {Nif::BSLightingShaderType::ShaderType_Glow, std::string()}, + {Nif::BSLightingShaderType::ShaderType_Parallax, std::string()}, + {Nif::BSLightingShaderType::ShaderType_FaceTint, std::string()}, + {Nif::BSLightingShaderType::ShaderType_HairTint, std::string()}, + {Nif::BSLightingShaderType::ShaderType_ParallaxOcc, std::string()}, + {Nif::BSLightingShaderType::ShaderType_MultitexLand, std::string()}, + {Nif::BSLightingShaderType::ShaderType_LODLand, std::string()}, + {Nif::BSLightingShaderType::ShaderType_Snow, std::string()}, + {Nif::BSLightingShaderType::ShaderType_MultiLayerParallax, std::string()}, + {Nif::BSLightingShaderType::ShaderType_TreeAnim, std::string()}, + {Nif::BSLightingShaderType::ShaderType_LODObjects, std::string()}, + {Nif::BSLightingShaderType::ShaderType_SparkleSnow, std::string()}, + {Nif::BSLightingShaderType::ShaderType_LODObjectsHD, std::string()}, + {Nif::BSLightingShaderType::ShaderType_EyeEnvmap, std::string()}, + {Nif::BSLightingShaderType::ShaderType_Cloud, std::string()}, + {Nif::BSLightingShaderType::ShaderType_LODNoise, std::string()}, + {Nif::BSLightingShaderType::ShaderType_MultitexLandLODBlend, std::string()}, + {Nif::BSLightingShaderType::ShaderType_Dismemberment, std::string()} + }; + auto prefix = mapping.find(static_cast(type)); + if (prefix == mapping.end()) + Log(Debug::Warning) << "Unknown BSLightingShaderType " << type << " in " << mFilename; + else if (prefix->second.empty()) + Log(Debug::Warning) << "Unhandled BSLightingShaderType " << type << " in " << mFilename; + else + return prefix->second; + + return mapping.at(Nif::BSLightingShaderType::ShaderType_Default); } void handleProperty(const Nif::Property *property, @@ -1834,7 +1870,7 @@ namespace NifOsg { auto texprop = static_cast(property); bool shaderRequired = true; - node->setUserValue("shaderPrefix", getNVShaderPrefix(texprop->type)); + node->setUserValue("shaderPrefix", getBSShaderPrefix(texprop->type)); node->setUserValue("shaderRequired", shaderRequired); osg::StateSet* stateset = node->getOrCreateStateSet(); if (!texprop->textureSet.empty()) @@ -1849,7 +1885,7 @@ namespace NifOsg { auto texprop = static_cast(property); bool shaderRequired = true; - node->setUserValue("shaderPrefix", getNVShaderPrefix(texprop->type)); + node->setUserValue("shaderPrefix", getBSShaderPrefix(texprop->type)); node->setUserValue("shaderRequired", shaderRequired); osg::StateSet* stateset = node->getOrCreateStateSet(); if (!texprop->filename.empty()) @@ -1887,6 +1923,18 @@ namespace NifOsg handleTextureControllers(texprop, composite, imageManager, stateset, animflags); break; } + case Nif::RC_BSLightingShaderProperty: + { + auto texprop = static_cast(property); + bool shaderRequired = true; + node->setUserValue("shaderPrefix", getBSLightingShaderPrefix(texprop->type)); + node->setUserValue("shaderRequired", shaderRequired); + osg::StateSet* stateset = node->getOrCreateStateSet(); + if (!texprop->mTextureSet.empty()) + handleTextureSet(texprop->mTextureSet.getPtr(), texprop->mClamp, node->getName(), stateset, imageManager, boundTextures); + handleTextureControllers(texprop, composite, imageManager, stateset, animflags); + break; + } // unused by mw case Nif::RC_NiShadeProperty: case Nif::RC_NiDitherProperty: @@ -2035,6 +2083,17 @@ namespace NifOsg } break; } + case Nif::RC_BSLightingShaderProperty: + { + auto shaderprop = static_cast(property); + mat->setAlpha(osg::Material::FRONT_AND_BACK, shaderprop->mAlpha); + mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(shaderprop->mEmissive, 1.f)); + mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(shaderprop->mSpecular, 1.f)); + mat->setShininess(osg::Material::FRONT_AND_BACK, shaderprop->mGlossiness); + emissiveMult = shaderprop->mEmissiveMult; + specStrength = shaderprop->mSpecStrength; + break; + } } }