1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-30 16:20:21 +00:00

add overwriteLighting a toggle option for addVfx

This commit is contained in:
Sebastian Fieber 2024-12-31 01:57:09 +00:00 committed by Alexei Kotov
parent 63b8e636f3
commit 5cb6da4b02
15 changed files with 63 additions and 38 deletions

View File

@ -82,7 +82,7 @@ message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 49) set(OPENMW_VERSION_MINOR 49)
set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_LUA_API_REVISION 68) set(OPENMW_LUA_API_REVISION 69)
set(OPENMW_POSTPROCESSING_API_REVISION 2) set(OPENMW_POSTPROCESSING_API_REVISION 2)
set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_COMMITHASH "")

View File

@ -516,7 +516,7 @@ namespace MWBase
virtual void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0; virtual void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0;
virtual void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride, virtual void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride,
const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true) const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true, bool useAmbientLight = false)
= 0; = 0;
/// @see MWWorld::WeatherManager::isInStorm /// @see MWWorld::WeatherManager::isInStorm

View File

@ -267,10 +267,11 @@ namespace MWLua
[object = ObjectVariant(object), model = std::string(model), [object = ObjectVariant(object), model = std::string(model),
effectId = options->get_or<std::string>("vfxId", ""), loop = options->get_or("loop", false), effectId = options->get_or<std::string>("vfxId", ""), loop = options->get_or("loop", false),
boneName = options->get_or<std::string>("boneName", ""), boneName = options->get_or<std::string>("boneName", ""),
particleTexture = options->get_or<std::string>("particleTextureOverride", "")] { particleTexture = options->get_or<std::string>("particleTextureOverride", ""),
useAmbientLight = options->get_or("useAmbientLight", true)] {
MWRender::Animation* anim = getMutableAnimationOrThrow(ObjectVariant(object)); MWRender::Animation* anim = getMutableAnimationOrThrow(ObjectVariant(object));
anim->addEffect(model, effectId, loop, boneName, particleTexture); anim->addEffect(model, effectId, loop, boneName, particleTexture, useAmbientLight);
}, },
"addVfxAction"); "addVfxAction");
} }
@ -318,15 +319,20 @@ namespace MWLua
bool magicVfx = options->get_or("mwMagicVfx", true); bool magicVfx = options->get_or("mwMagicVfx", true);
std::string texture = options->get_or<std::string>("particleTextureOverride", ""); std::string texture = options->get_or<std::string>("particleTextureOverride", "");
float scale = options->get_or("scale", 1.f); float scale = options->get_or("scale", 1.f);
bool useAmbientLight = options->get_or("useAmbientLight", true);
context.mLuaManager->addAction( context.mLuaManager->addAction(
[world, model = VFS::Path::Normalized(model), texture = std::move(texture), worldPos, scale, [world, model = VFS::Path::Normalized(model), texture = std::move(texture), worldPos, scale,
magicVfx]() { world->spawnEffect(model, texture, worldPos, scale, magicVfx); }, magicVfx, useAmbientLight]() {
world->spawnEffect(model, texture, worldPos, scale, magicVfx, useAmbientLight);
},
"openmw.vfx.spawn"); "openmw.vfx.spawn");
} }
else else
{ {
context.mLuaManager->addAction([world, model = VFS::Path::Normalized(model), context.mLuaManager->addAction(
worldPos]() { world->spawnEffect(model, "", worldPos); }, [world, model = VFS::Path::Normalized(model), worldPos]() {
world->spawnEffect(model, "", worldPos, 1.f, true, true);
},
"openmw.vfx.spawn"); "openmw.vfx.spawn");
} }
}; };

View File

@ -389,22 +389,6 @@ namespace
std::string_view mEffectId; std::string_view mEffectId;
}; };
namespace
{
osg::ref_ptr<osg::LightModel> makeVFXLightModelInstance()
{
osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel;
lightModel->setAmbientIntensity({ 1, 1, 1, 1 });
return lightModel;
}
const osg::ref_ptr<osg::LightModel>& getVFXLightModelInstance()
{
static const osg::ref_ptr<osg::LightModel> lightModel = makeVFXLightModelInstance();
return lightModel;
}
}
void assignBoneBlendCallbackRecursive(MWRender::BoneAnimBlendController* controller, osg::Node* parent, bool isRoot) void assignBoneBlendCallbackRecursive(MWRender::BoneAnimBlendController* controller, osg::Node* parent, bool isRoot)
{ {
// Attempt to cast node to an osgAnimation::Bone // Attempt to cast node to an osgAnimation::Bone
@ -1725,7 +1709,7 @@ namespace MWRender
} }
void Animation::addEffect(std::string_view model, std::string_view effectId, bool loop, std::string_view bonename, void Animation::addEffect(std::string_view model, std::string_view effectId, bool loop, std::string_view bonename,
std::string_view texture) std::string_view texture, bool useAmbientLight)
{ {
if (!mObjectRoot.get()) if (!mObjectRoot.get())
return; return;
@ -1778,10 +1762,15 @@ namespace MWRender
osg::ref_ptr<osg::Node> node osg::ref_ptr<osg::Node> node
= mResourceSystem->getSceneManager()->getInstance(VFS::Path::toNormalized(model), trans); = mResourceSystem->getSceneManager()->getInstance(VFS::Path::toNormalized(model), trans);
// Morrowind has a white ambient light attached to the root VFX node of the scenegraph if (useAmbientLight)
node->getOrCreateStateSet()->setAttributeAndModes( {
getVFXLightModelInstance(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); // Morrowind has a white ambient light attached to the root VFX node of the scenegraph
node->getOrCreateStateSet()->setAttributeAndModes(
getVFXLightModelInstance(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
}
mResourceSystem->getSceneManager()->setUpNormalsRTForStateSet(node->getOrCreateStateSet(), false); mResourceSystem->getSceneManager()->setUpNormalsRTForStateSet(node->getOrCreateStateSet(), false);
SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor; SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor;
node->accept(findMaxLengthVisitor); node->accept(findMaxLengthVisitor);

View File

@ -342,10 +342,13 @@ namespace MWRender
* you need to remove it manually using removeEffect when the effect should end. * you need to remove it manually using removeEffect when the effect should end.
* @param bonename Bone to attach to, or empty string to use the scene node instead * @param bonename Bone to attach to, or empty string to use the scene node instead
* @param texture override the texture specified in the model's materials - if empty, do not override * @param texture override the texture specified in the model's materials - if empty, do not override
* @param useAmbientLight attach white ambient light to the root VFX node of the scenegraph (Morrowind
* default)
* @note Will not add an effect twice. * @note Will not add an effect twice.
*/ */
void addEffect(std::string_view model, std::string_view effectId, bool loop = false, void addEffect(std::string_view model, std::string_view effectId, bool loop = false,
std::string_view bonename = {}, std::string_view texture = {}); std::string_view bonename = {}, std::string_view texture = {}, bool useAmbientLight = true);
void removeEffect(std::string_view effectId); void removeEffect(std::string_view effectId);
void removeEffects(); void removeEffects();
std::vector<std::string_view> getLoopingEffects() const; std::vector<std::string_view> getLoopingEffects() const;

View File

@ -28,7 +28,7 @@ namespace MWRender
} }
void EffectManager::addEffect(VFS::Path::NormalizedView model, std::string_view textureOverride, void EffectManager::addEffect(VFS::Path::NormalizedView model, std::string_view textureOverride,
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX) const osg::Vec3f& worldPosition, float scale, bool isMagicVFX, bool useAmbientLight)
{ {
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model); osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model);
@ -58,6 +58,15 @@ namespace MWRender
mParentNode->addChild(trans); mParentNode->addChild(trans);
if (useAmbientLight)
{
// Morrowind has a white ambient light attached to the root VFX node of the scenegraph
node->getOrCreateStateSet()->setAttributeAndModes(
getVFXLightModelInstance(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
}
mResourceSystem->getSceneManager()->setUpNormalsRTForStateSet(node->getOrCreateStateSet(), false);
mEffects.push_back(std::move(effect)); mEffects.push_back(std::move(effect));
} }

View File

@ -35,7 +35,7 @@ namespace MWRender
/// Add an effect. When it's finished playing, it will be removed automatically. /// Add an effect. When it's finished playing, it will be removed automatically.
void addEffect(VFS::Path::NormalizedView model, std::string_view textureOverride, void addEffect(VFS::Path::NormalizedView model, std::string_view textureOverride,
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX = true); const osg::Vec3f& worldPosition, float scale, bool isMagicVFX = true, bool useAmbientLight = false);
void update(float dt); void update(float dt);

View File

@ -1248,9 +1248,9 @@ namespace MWRender
} }
void RenderingManager::spawnEffect(VFS::Path::NormalizedView model, std::string_view texture, void RenderingManager::spawnEffect(VFS::Path::NormalizedView model, std::string_view texture,
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX) const osg::Vec3f& worldPosition, float scale, bool isMagicVFX, bool useAmbientLight)
{ {
mEffectManager->addEffect(model, texture, worldPosition, scale, isMagicVFX); mEffectManager->addEffect(model, texture, worldPosition, scale, isMagicVFX, useAmbientLight);
} }
void RenderingManager::notifyWorldSpaceChanged() void RenderingManager::notifyWorldSpaceChanged()

View File

@ -195,7 +195,7 @@ namespace MWRender
SkyManager* getSkyManager(); SkyManager* getSkyManager();
void spawnEffect(VFS::Path::NormalizedView model, std::string_view texture, const osg::Vec3f& worldPosition, void spawnEffect(VFS::Path::NormalizedView model, std::string_view texture, const osg::Vec3f& worldPosition,
float scale = 1.f, bool isMagicVFX = true); float scale = 1.f, bool isMagicVFX = true, bool useAmbientLight = false);
/// Clear all savegame-specific data /// Clear all savegame-specific data
void clear(); void clear();

View File

@ -74,4 +74,16 @@ namespace MWRender
return Settings::shaders().mAntialiasAlphaTest && Settings::video().mAntialiasing > 1; return Settings::shaders().mAntialiasAlphaTest && Settings::video().mAntialiasing > 1;
} }
osg::ref_ptr<osg::LightModel> makeVFXLightModelInstance()
{
osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel;
lightModel->setAmbientIntensity({ 1, 1, 1, 1 });
return lightModel;
}
const osg::ref_ptr<osg::LightModel>& getVFXLightModelInstance()
{
static const osg::ref_ptr<osg::LightModel> lightModel = makeVFXLightModelInstance();
return lightModel;
}
} }

View File

@ -1,6 +1,7 @@
#ifndef OPENMW_MWRENDER_UTIL_H #ifndef OPENMW_MWRENDER_UTIL_H
#define OPENMW_MWRENDER_UTIL_H #define OPENMW_MWRENDER_UTIL_H
#include <osg/LightModel>
#include <osg/NodeCallback> #include <osg/NodeCallback>
#include <string_view> #include <string_view>
@ -35,6 +36,8 @@ namespace MWRender
}; };
bool shouldAddMSAAIntermediateTarget(); bool shouldAddMSAAIntermediateTarget();
const osg::ref_ptr<osg::LightModel>& getVFXLightModelInstance();
} }
#endif #endif

View File

@ -3689,9 +3689,9 @@ namespace MWWorld
} }
void World::spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride, void World::spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride,
const osg::Vec3f& worldPos, float scale, bool isMagicVFX) const osg::Vec3f& worldPos, float scale, bool isMagicVFX, bool useAmbientLight)
{ {
mRendering->spawnEffect(model, textureOverride, worldPos, scale, isMagicVFX); mRendering->spawnEffect(model, textureOverride, worldPos, scale, isMagicVFX, useAmbientLight);
} }
struct ResetActorsVisitor struct ResetActorsVisitor

View File

@ -603,7 +603,8 @@ namespace MWWorld
void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) override; void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) override;
void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride, void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride,
const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true) override; const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true,
bool useAmbientLight = false) override;
/// @see MWWorld::WeatherManager::isInStorm /// @see MWWorld::WeatherManager::isInStorm
bool isInStorm() const override; bool isInStorm() const override;

View File

@ -227,8 +227,9 @@
-- * `loop` - boolean, if true the effect will loop until removed (default: 0). -- * `loop` - boolean, if true the effect will loop until removed (default: 0).
-- * `boneName` - name of the bone to attach the vfx to. (default: "") -- * `boneName` - name of the bone to attach the vfx to. (default: "")
-- * `particleTextureOverride` - name of the particle texture to use. (default: "") -- * `particleTextureOverride` - name of the particle texture to use. (default: "")
-- * `vfxId` - a string ID that can be used to remove the effect later, using #removeVfx, and to avoid duplicate effects. The default value of "" can have duplicates. To avoid interaction with the engine, use unique identifiers unrelated to magic effect IDs. The engine uses this identifier to add and remove magic effects based on what effects are active on the actor. If this is set equal to the @{openmw.core#MagicEffectId} identifier of the magic effect being added, for example core.magic.EFFECT_TYPE.FireDamage, then the engine will remove it once the fire damage effect on the actor reaches 0. (Default: ""). -- * `vfxId` - a string ID that can be used to remove the effect later, using #removeVfx, and to avoid duplicate effects. The default value of "" can have duplicates. To avoid interaction with the engine, use unique identifiers unrelated to magic effect IDs. The engine uses this identifier to add and remove magic effects based on what effects are active on the actor. If this is set equal to the @{openmw.core#MagicEffectId} identifier of the magic effect being added, for example core.magic.EFFECT_TYPE.FireDamage, then the engine will remove it once the fire damage effect on the actor reaches 0. (Default: "").
-- -- * `useAmbientLighting` - boolean, vfx get a white ambient light attached in Morrowind. If false don't attach this. (default: 1)
--
-- @usage local mgef = core.magic.effects.records[myEffectName] -- @usage local mgef = core.magic.effects.records[myEffectName]
-- anim.addVfx(self, 'VFX_Hands', {boneName = 'Bip01 L Hand', particleTextureOverride = mgef.particle, loop = mgef.continuousVfx, vfxId = mgef.id..'_myuniquenamehere'}) -- anim.addVfx(self, 'VFX_Hands', {boneName = 'Bip01 L Hand', particleTextureOverride = mgef.particle, loop = mgef.continuousVfx, vfxId = mgef.id..'_myuniquenamehere'})
-- -- later: -- -- later:

View File

@ -193,6 +193,7 @@
-- * `mwMagicVfx` - Boolean that if true causes the textureOverride parameter to only affect nodes with the Nif::RC_NiTexturingProperty property set. (default: true). -- * `mwMagicVfx` - Boolean that if true causes the textureOverride parameter to only affect nodes with the Nif::RC_NiTexturingProperty property set. (default: true).
-- * `particleTextureOverride` - Name of a particle texture that should override this effect's default texture. (default: "") -- * `particleTextureOverride` - Name of a particle texture that should override this effect's default texture. (default: "")
-- * `scale` - A number that scales the size of the vfx (Default: 1) -- * `scale` - A number that scales the size of the vfx (Default: 1)
-- * `useAmbientLighting` - boolean, vfx get a white ambient light attached in Morrowind. If false don't attach this. (default: 1)
-- --
-- @usage -- Spawn a sanctuary effect near the player -- @usage -- Spawn a sanctuary effect near the player
-- local effect = core.magic.effects.records[core.magic.EFFECT_TYPE.Sanctuary] -- local effect = core.magic.effects.records[core.magic.EFFECT_TYPE.Sanctuary]