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:
commit
bdf7370b7c
6 changed files with 116 additions and 18 deletions
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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…
Reference in a new issue