1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-04-01 04:36:41 +00:00

Merge branch 'effectshader' into 'master'

Handle BSEffectShaderProperty

See merge request OpenMW/openmw!2751
This commit is contained in:
psi29a 2023-02-19 23:45:48 +00:00
commit bdf7370b7c
6 changed files with 116 additions and 18 deletions

View file

@ -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> },

View file

@ -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);

View file

@ -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;

View file

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

View file

@ -10,6 +10,7 @@
#include <osg/Sequence>
#include <osg/Switch>
#include <osg/TexGen>
#include <osg/TexMat>
#include <osg/ValueObject>
// resource
@ -502,6 +503,12 @@ namespace NifOsg
return image;
}
void handleTextureWrapping(osg::Texture2D* texture, bool wrapS, bool wrapT)
{
texture->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
}
bool handleEffect(const Nif::Node* nifNode, osg::StateSet* stateset, Resource::ImageManager* imageManager)
{
if (nifNode->recType != Nif::RC_NiTextureEffect)
@ -547,10 +554,7 @@ namespace NifOsg
if (image)
texture2d->setTextureSize(image->s(), image->t());
texture2d->setName("envMap");
texture2d->setWrap(
osg::Texture::WRAP_S, textureEffect->wrapS() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(
osg::Texture::WRAP_T, textureEffect->wrapT() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
handleTextureWrapping(texture2d, textureEffect->wrapS(), textureEffect->wrapT());
int texUnit = 3; // FIXME
@ -1809,10 +1813,7 @@ namespace NifOsg
else
texture2d = new osg::Texture2D;
texture2d->setWrap(
osg::Texture::WRAP_S, tex.wrapS() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(
osg::Texture::WRAP_T, tex.wrapT() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
handleTextureWrapping(texture2d, tex.wrapS(), tex.wrapT());
uvSet = tex.uvSet;
}
@ -1820,8 +1821,7 @@ namespace NifOsg
{
// Texture only comes from NiFlipController, so tex is ignored, set defaults
texture2d = new osg::Texture2D;
texture2d->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
texture2d->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
handleTextureWrapping(texture2d, true, true);
uvSet = 0;
}
@ -1966,10 +1966,7 @@ namespace NifOsg
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
if (image)
texture2d->setTextureSize(image->s(), image->t());
bool wrapT = clamp & 0x1;
bool wrapS = (clamp >> 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);
handleTextureWrapping(texture2d, (clamp >> 1) & 0x1, clamp & 0x1);
unsigned int texUnit = boundTextures.size();
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
// BSShaderTextureSet presence means there's no need for FFP support for the affected node
@ -2174,10 +2171,7 @@ namespace NifOsg
texture2d->setName("diffuseMap");
if (image)
texture2d->setTextureSize(image->s(), image->t());
texture2d->setWrap(osg::Texture::WRAP_S,
texprop->wrapS() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_T,
texprop->wrapT() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
handleTextureWrapping(texture2d, texprop->wrapS(), texprop->wrapT());
const unsigned int texUnit = 0;
const unsigned int uvSet = 0;
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
@ -2208,6 +2202,56 @@ 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());
handleTextureWrapping(texture2d, (texprop->mClamp >> 1) & 0x1, texprop->mClamp & 0x1);
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 +2437,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 +2453,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;
}

View file

@ -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