Implement the basics of BSEffectShaderProperty

pull/3229/head
Alexei Kotov 2 years ago
parent 0790a94159
commit 2de81738c1

@ -169,6 +169,7 @@ namespace Nif
{ "bhkRigidBody", &construct<bhkRigidBody, RC_bhkRigidBody> },
{ "bhkRigidBodyT", &construct<bhkRigidBody, RC_bhkRigidBodyT> },
{ "BSLightingShaderProperty", &construct<BSLightingShaderProperty, RC_BSLightingShaderProperty> },
{ "BSEffectShaderProperty", &construct<BSEffectShaderProperty, RC_BSEffectShaderProperty> },
{ "NiSortAdjustNode", &construct<NiSortAdjustNode, RC_NiSortAdjustNode> },
{ "NiClusterAccumulator", &construct<NiClusterAccumulator, RC_NiClusterAccumulator> },
{ "NiAlphaAccumulator", &construct<NiAlphaAccumulator, RC_NiAlphaAccumulator> },

@ -204,6 +204,25 @@ namespace Nif
mTextureSet.post(nif);
}
void BSEffectShaderProperty::read(NIFStream* nif)
{
BSShaderProperty::read(nif);
flags1 = nif->getUInt();
flags2 = nif->getUInt();
mUVOffset = nif->getVector2();
mUVScale = nif->getVector2();
mSourceTexture = nif->getSizedString();
unsigned int miscParams = nif->getUInt();
mClamp = miscParams & 0xFF;
mLightingInfluence = (miscParams >> 8) & 0xFF;
mEnvMapMinLOD = (miscParams >> 16) & 0xFF;
mFalloffParams = nif->getVector4();
mBaseColor = nif->getVector4();
mBaseColorScale = nif->getFloat();
mFalloffDepth = nif->getFloat();
mGreyscaleTexture = nif->getSizedString();
}
void NiFogProperty::read(NIFStream* nif)
{
Property::read(nif);

@ -215,6 +215,22 @@ namespace Nif
void post(Reader& nif) override;
};
struct BSEffectShaderProperty : public BSShaderProperty
{
osg::Vec2f mUVOffset, mUVScale;
std::string mSourceTexture;
unsigned char mClamp;
unsigned char mLightingInfluence;
unsigned char mEnvMapMinLOD;
osg::Vec4f mFalloffParams;
osg::Vec4f mBaseColor;
float mBaseColorScale;
float mFalloffDepth;
std::string mGreyscaleTexture;
void read(NIFStream* nif) override;
};
struct NiDitherProperty : public Property
{
unsigned short flags;

@ -145,6 +145,7 @@ namespace Nif
RC_bhkRigidBody,
RC_bhkRigidBodyT,
RC_BSLightingShaderProperty,
RC_BSEffectShaderProperty,
RC_NiClusterAccumulator,
RC_NiAlphaAccumulator,
RC_NiSortAdjustNode,

@ -10,6 +10,7 @@
#include <osg/Sequence>
#include <osg/Switch>
#include <osg/TexGen>
#include <osg/TexMat>
#include <osg/ValueObject>
// resource
@ -2208,6 +2209,61 @@ namespace NifOsg
handleTextureControllers(texprop, composite, imageManager, stateset, animflags);
break;
}
case Nif::RC_BSEffectShaderProperty:
{
auto texprop = static_cast<const Nif::BSEffectShaderProperty*>(property);
bool shaderRequired = true;
node->setUserValue("shaderPrefix", std::string("nv_nolighting"));
node->setUserValue("shaderRequired", shaderRequired);
osg::StateSet* stateset = node->getOrCreateStateSet();
if (!texprop->mSourceTexture.empty())
{
if (!boundTextures.empty())
{
for (unsigned int i = 0; i < boundTextures.size(); ++i)
stateset->setTextureMode(i, GL_TEXTURE_2D, osg::StateAttribute::OFF);
boundTextures.clear();
}
std::string filename = Misc::ResourceHelpers::correctTexturePath(
texprop->mSourceTexture, imageManager->getVFS());
osg::ref_ptr<osg::Image> image = imageManager->getImage(filename);
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
texture2d->setName("diffuseMap");
if (image)
texture2d->setTextureSize(image->s(), image->t());
bool wrapT = texprop->mClamp & 0x1;
bool wrapS = (texprop->mClamp >> 1) & 0x1;
texture2d->setWrap(osg::Texture::WRAP_S,
wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_T,
wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
const unsigned int texUnit = 0;
const unsigned int uvSet = 0;
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
boundTextures.push_back(uvSet);
{
osg::ref_ptr<osg::TexMat> texMat(new osg::TexMat);
// This handles 20.2.0.7 UV settings like 4.0.0.2 UV settings (see NifOsg::UVController)
// TODO: verify
osg::Vec3f uvOrigin(0.5f, 0.5f, 0.f);
osg::Vec3f uvScale(texprop->mUVScale.x(), texprop->mUVScale.y(), 1.f);
osg::Vec3f uvTrans(-texprop->mUVOffset.x(), -texprop->mUVOffset.y(), 0.f);
osg::Matrixf mat = osg::Matrixf::translate(uvOrigin);
mat.preMultScale(uvScale);
mat.preMultTranslate(-uvOrigin);
mat.setTrans(mat.getTrans() + uvTrans);
texMat->setMatrix(mat);
stateset->setTextureAttributeAndModes(texUnit, texMat, osg::StateAttribute::ON);
}
}
stateset->addUniform(new osg::Uniform("useFalloff", true)); // Should use the shader flag
stateset->addUniform(new osg::Uniform("falloffParams", texprop->mFalloffParams));
handleTextureControllers(texprop, composite, imageManager, stateset, animflags);
break;
}
// unused by mw
case Nif::RC_NiShadeProperty:
case Nif::RC_NiDitherProperty:
@ -2393,6 +2449,11 @@ namespace NifOsg
}
break;
}
case Nif::RC_BSShaderNoLightingProperty:
{
mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f));
break;
}
case Nif::RC_BSLightingShaderProperty:
{
auto shaderprop = static_cast<const Nif::BSLightingShaderProperty*>(property);
@ -2404,6 +2465,13 @@ namespace NifOsg
specStrength = shaderprop->mSpecStrength;
break;
}
case Nif::RC_BSEffectShaderProperty:
{
auto shaderprop = static_cast<const Nif::BSEffectShaderProperty*>(property);
mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(shaderprop->mBaseColor));
emissiveMult = shaderprop->mBaseColorScale;
break;
}
default:
break;
}

@ -15,6 +15,7 @@ varying float linearDepth;
uniform bool useFalloff;
uniform vec2 screenRes;
uniform float emissiveMult;
varying float passFalloff;
@ -36,6 +37,10 @@ void main()
if (useFalloff)
gl_FragData[0].a *= passFalloff;
vec4 emissionColor = getEmissionColor();
gl_FragData[0].rgb *= emissionColor.rgb * emissiveMult;
gl_FragData[0].a *= emissionColor.a * emissionColor.a; // sic
alphaTest();
#if defined(FORCE_OPAQUE) && FORCE_OPAQUE

Loading…
Cancel
Save