Handle NiFogProperty (feature #5173)

macos_ci_fix
Alexei Kotov 1 year ago
parent 102d2c4b43
commit 9cdaf2c29b

@ -104,6 +104,7 @@
Bug #7675: Successful lock spell doesn't produce a sound
Bug #7679: Scene luminance value flashes when toggling shaders
Feature #3537: Shader-based water ripples
Feature #5173: Support for NiFogProperty
Feature #5492: Let rain and snow collide with statics
Feature #6149: Dehardcode Lua API_REVISION
Feature #6152: Playing music via lua scripts

@ -130,7 +130,7 @@ add_component_dir (nif
)
add_component_dir (nifosg
nifloader controller particle matrixtransform
nifloader controller particle matrixtransform fog
)
add_component_dir (nifbullet

@ -461,11 +461,22 @@ namespace Nif
struct NiFogProperty : NiProperty
{
enum Flags : uint16_t
{
Enabled = 0x02,
Radial = 0x08,
VertexAlpha = 0x10,
};
uint16_t mFlags;
float mFogDepth;
osg::Vec3f mColour;
void read(NIFStream* nif) override;
bool enabled() const { return mFlags & Flags::Enabled; }
bool radial() const { return mFlags & Flags::Radial; }
bool vertexAlpha() const { return mFlags & Flags::VertexAlpha; }
};
struct NiMaterialProperty : NiProperty

@ -0,0 +1,31 @@
#include "fog.hpp"
#include <osg/Matrix>
#include <osg/State>
namespace NifOsg
{
Fog::Fog()
: osg::Fog()
{
}
Fog::Fog(const Fog& copy, const osg::CopyOp& copyop)
: osg::Fog(copy, copyop)
, mDepth(copy.mDepth)
{
}
void Fog::apply(osg::State& state) const
{
osg::Fog::apply(state);
#ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE
float fov, aspect, near, far;
state.getProjectionMatrix().getPerspective(fov, aspect, near, far);
glFogf(GL_FOG_START, near * mDepth + far * (1.f - mDepth));
glFogf(GL_FOG_END, far);
#endif
}
}

@ -0,0 +1,29 @@
#ifndef OPENMW_COMPONENTS_NIFOSG_FOG_H
#define OPENMW_COMPONENTS_NIFOSG_FOG_H
#include <osg/Fog>
namespace NifOsg
{
// osg::Fog-based wrapper for NiFogProperty that autocalculates the fog start and end distance.
class Fog : public osg::Fog
{
public:
Fog();
Fog(const Fog& copy, const osg::CopyOp& copyop);
META_StateAttribute(NifOsg, Fog, FOG)
void setDepth(float depth) { mDepth = depth; }
float getDepth() const { return mDepth; }
void apply(osg::State& state) const override;
private:
float mDepth{ 1.f };
};
}
#endif

@ -56,6 +56,7 @@
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/skeleton.hpp>
#include "fog.hpp"
#include "matrixtransform.hpp"
#include "particle.hpp"
@ -2495,10 +2496,35 @@ namespace NifOsg
handleDepthFlags(stateset, texprop->depthTest(), texprop->depthWrite());
break;
}
case Nif::RC_NiFogProperty:
{
const Nif::NiFogProperty* fogprop = static_cast<const Nif::NiFogProperty*>(property);
osg::StateSet* stateset = node->getOrCreateStateSet();
// Vertex alpha mode appears to be broken
if (!fogprop->vertexAlpha() && fogprop->enabled())
{
osg::ref_ptr<NifOsg::Fog> fog = new NifOsg::Fog;
fog->setMode(osg::Fog::LINEAR);
fog->setColor(osg::Vec4f(fogprop->mColour, 1.f));
fog->setDepth(fogprop->mFogDepth);
stateset->setAttributeAndModes(fog, osg::StateAttribute::ON);
// Intentionally ignoring radial fog flag
// We don't really want to override the global setting
}
else
{
osg::ref_ptr<osg::Fog> fog = new osg::Fog;
// Shaders don't respect glDisable(GL_FOG)
fog->setMode(osg::Fog::LINEAR);
fog->setStart(10000000);
fog->setEnd(10000000);
stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
}
break;
}
// unused by mw
case Nif::RC_NiShadeProperty:
case Nif::RC_NiDitherProperty:
case Nif::RC_NiFogProperty:
{
break;
}

@ -3,6 +3,7 @@
#include <osgDB/ObjectWrapper>
#include <osgDB/Registry>
#include <components/nifosg/fog.hpp>
#include <components/nifosg/matrixtransform.hpp>
#include <components/sceneutil/morphgeometry.hpp>
@ -123,6 +124,19 @@ namespace SceneUtil
}
};
class FogSerializer : public osgDB::ObjectWrapper
{
public:
FogSerializer()
: osgDB::ObjectWrapper(
createInstanceFunc<osg::Fog>, "NifOsg::Fog", "osg::Object osg::StateAttribute osg::Fog NifOsg::Fog")
{
addSerializer(new osgDB::PropByValSerializer<NifOsg::Fog, float>(
"Depth", 1.f, &NifOsg::Fog::getDepth, &NifOsg::Fog::setDepth),
osgDB::BaseSerializer::RW_FLOAT);
}
};
osgDB::ObjectWrapper* makeDummySerializer(const std::string& classname)
{
return new osgDB::ObjectWrapper(createInstanceFunc<osg::DummyObject>, classname, "osg::Object");
@ -153,6 +167,7 @@ namespace SceneUtil
mgr->addWrapper(new LightManagerSerializer);
mgr->addWrapper(new CameraRelativeTransformSerializer);
mgr->addWrapper(new MatrixTransformSerializer);
mgr->addWrapper(new FogSerializer);
// Don't serialize Geometry data as we are more interested in the overall structure rather than tons of
// vertex data that would make the file large and hard to read.

Loading…
Cancel
Save