mirror of https://github.com/OpenMW/openmw.git
introduce sky shaders
parent
41318a585f
commit
1e40d27318
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,343 @@
|
||||
#ifndef OPENMW_MWRENDER_SKYUTIL_H
|
||||
#define OPENMW_MWRENDER_SKYUTIL_H
|
||||
|
||||
#include <osg/Vec4f>
|
||||
#include <osg/Matrixf>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Transform>
|
||||
#include <osg/Material>
|
||||
|
||||
#include <osgParticle/Shooter>
|
||||
#include <osgParticle/ConstantRateCounter>
|
||||
|
||||
#include <components/sceneutil/statesetupdater.hpp>
|
||||
#include <components/sceneutil/nodecallback.hpp>
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
class ImageManager;
|
||||
class SceneManager;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
struct MoonUpdater;
|
||||
class SunUpdater;
|
||||
class SunFlashCallback;
|
||||
class SunGlareCallback;
|
||||
|
||||
struct WeatherResult
|
||||
{
|
||||
std::string mCloudTexture;
|
||||
std::string mNextCloudTexture;
|
||||
float mCloudBlendFactor;
|
||||
|
||||
osg::Vec4f mFogColor;
|
||||
|
||||
osg::Vec4f mAmbientColor;
|
||||
|
||||
osg::Vec4f mSkyColor;
|
||||
|
||||
// sun light color
|
||||
osg::Vec4f mSunColor;
|
||||
|
||||
// alpha is the sun transparency
|
||||
osg::Vec4f mSunDiscColor;
|
||||
|
||||
float mFogDepth;
|
||||
|
||||
float mDLFogFactor;
|
||||
float mDLFogOffset;
|
||||
|
||||
float mWindSpeed;
|
||||
float mBaseWindSpeed;
|
||||
float mCurrentWindSpeed;
|
||||
float mNextWindSpeed;
|
||||
|
||||
float mCloudSpeed;
|
||||
|
||||
float mGlareView;
|
||||
|
||||
bool mNight; // use night skybox
|
||||
float mNightFade; // fading factor for night skybox
|
||||
|
||||
bool mIsStorm;
|
||||
|
||||
std::string mAmbientLoopSoundID;
|
||||
float mAmbientSoundVolume;
|
||||
|
||||
std::string mParticleEffect;
|
||||
std::string mRainEffect;
|
||||
float mPrecipitationAlpha;
|
||||
|
||||
float mRainDiameter;
|
||||
float mRainMinHeight;
|
||||
float mRainMaxHeight;
|
||||
float mRainSpeed;
|
||||
float mRainEntranceSpeed;
|
||||
int mRainMaxRaindrops;
|
||||
|
||||
osg::Vec3f mStormDirection;
|
||||
osg::Vec3f mNextStormDirection;
|
||||
};
|
||||
|
||||
struct MoonState
|
||||
{
|
||||
enum class Phase
|
||||
{
|
||||
Full,
|
||||
WaningGibbous,
|
||||
ThirdQuarter,
|
||||
WaningCrescent,
|
||||
New,
|
||||
WaxingCrescent,
|
||||
FirstQuarter,
|
||||
WaxingGibbous,
|
||||
Unspecified
|
||||
};
|
||||
|
||||
float mRotationFromHorizon;
|
||||
float mRotationFromNorth;
|
||||
Phase mPhase;
|
||||
float mShadowBlend;
|
||||
float mMoonAlpha;
|
||||
};
|
||||
|
||||
osg::ref_ptr<osg::Material> createAlphaTrackingUnlitMaterial();
|
||||
osg::ref_ptr<osg::Material> createUnlitMaterial();
|
||||
|
||||
class OcclusionCallback
|
||||
{
|
||||
public:
|
||||
OcclusionCallback(osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible, osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal);
|
||||
|
||||
protected:
|
||||
float getVisibleRatio (osg::Camera* camera);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryVisiblePixels;
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryTotalPixels;
|
||||
|
||||
std::map<osg::observer_ptr<osg::Camera>, float> mLastRatio;
|
||||
};
|
||||
|
||||
class AtmosphereUpdater : public SceneUtil::StateSetUpdater
|
||||
{
|
||||
public:
|
||||
void setEmissionColor(const osg::Vec4f& emissionColor);
|
||||
|
||||
protected:
|
||||
void setDefaults(osg::StateSet* stateset) override;
|
||||
void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override;
|
||||
|
||||
private:
|
||||
osg::Vec4f mEmissionColor;
|
||||
};
|
||||
|
||||
class AtmosphereNightUpdater : public SceneUtil::StateSetUpdater
|
||||
{
|
||||
public:
|
||||
AtmosphereNightUpdater(Resource::ImageManager* imageManager, bool forceShaders);
|
||||
|
||||
void setFade(float fade);
|
||||
|
||||
protected:
|
||||
void setDefaults(osg::StateSet* stateset) override;
|
||||
|
||||
void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override;
|
||||
|
||||
private:
|
||||
osg::Vec4f mColor;
|
||||
osg::ref_ptr<osg::Texture2D> mTexture;
|
||||
bool mForceShaders;
|
||||
};
|
||||
|
||||
class CloudUpdater : public SceneUtil::StateSetUpdater
|
||||
{
|
||||
public:
|
||||
CloudUpdater(bool forceShaders);
|
||||
|
||||
void setTexture(osg::ref_ptr<osg::Texture2D> texture);
|
||||
|
||||
void setEmissionColor(const osg::Vec4f& emissionColor);
|
||||
void setOpacity(float opacity);
|
||||
void setTextureCoord(float timer);
|
||||
|
||||
protected:
|
||||
void setDefaults(osg::StateSet *stateset) override;
|
||||
void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) override;
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Texture2D> mTexture;
|
||||
osg::Vec4f mEmissionColor;
|
||||
float mOpacity;
|
||||
bool mForceShaders;
|
||||
osg::Matrixf mTexMat;
|
||||
};
|
||||
|
||||
/// Transform that removes the eyepoint of the modelview matrix,
|
||||
/// i.e. its children are positioned relative to the camera.
|
||||
class CameraRelativeTransform : public osg::Transform
|
||||
{
|
||||
public:
|
||||
CameraRelativeTransform();
|
||||
|
||||
CameraRelativeTransform(const CameraRelativeTransform& copy, const osg::CopyOp& copyop);
|
||||
|
||||
META_Node(MWRender, CameraRelativeTransform)
|
||||
|
||||
const osg::Vec3f& getLastViewPoint() const;
|
||||
|
||||
bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const override;
|
||||
|
||||
osg::BoundingSphere computeBound() const override;
|
||||
|
||||
private:
|
||||
// viewPoint for the current frame
|
||||
mutable osg::Vec3f mViewPoint;
|
||||
};
|
||||
|
||||
/// @brief Hides the node subgraph if the eye point is below water.
|
||||
/// @note Must be added as cull callback.
|
||||
/// @note Meant to be used on a node that is child of a CameraRelativeTransform.
|
||||
/// The current view point must be retrieved by the CameraRelativeTransform since we can't get it anymore once we are in camera-relative space.
|
||||
class UnderwaterSwitchCallback : public SceneUtil::NodeCallback<UnderwaterSwitchCallback>
|
||||
{
|
||||
public:
|
||||
UnderwaterSwitchCallback(CameraRelativeTransform* cameraRelativeTransform);
|
||||
bool isUnderwater();
|
||||
|
||||
void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
void setEnabled(bool enabled);
|
||||
void setWaterLevel(float waterLevel);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<CameraRelativeTransform> mCameraRelativeTransform;
|
||||
bool mEnabled;
|
||||
float mWaterLevel;
|
||||
};
|
||||
|
||||
/// A base class for the sun and moons.
|
||||
class CelestialBody
|
||||
{
|
||||
public:
|
||||
CelestialBody(osg::Group* parentNode, float scaleFactor, int numUvSets, unsigned int visibleMask=~0u);
|
||||
|
||||
virtual ~CelestialBody() = default;
|
||||
|
||||
virtual void adjustTransparency(const float ratio) = 0;
|
||||
|
||||
void setVisible(bool visible);
|
||||
|
||||
protected:
|
||||
unsigned int mVisibleMask;
|
||||
static const float mDistance;
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> mTransform;
|
||||
osg::ref_ptr<osg::Geometry> mGeom;
|
||||
};
|
||||
|
||||
class Sun : public CelestialBody
|
||||
{
|
||||
public:
|
||||
Sun(osg::Group* parentNode, Resource::ImageManager& imageManager);
|
||||
|
||||
~Sun();
|
||||
|
||||
void setColor(const osg::Vec4f& color);
|
||||
void adjustTransparency(const float ratio) override;
|
||||
|
||||
void setDirection(const osg::Vec3f& direction);
|
||||
void setGlareTimeOfDayFade(float val);
|
||||
|
||||
private:
|
||||
/// @param queryVisible If true, queries the amount of visible pixels. If false, queries the total amount of pixels.
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> createOcclusionQueryNode(osg::Group* parent, bool queryVisible);
|
||||
|
||||
void createSunFlash(Resource::ImageManager& imageManager);
|
||||
void destroySunFlash();
|
||||
|
||||
void createSunGlare();
|
||||
void destroySunGlare();
|
||||
|
||||
osg::ref_ptr<SunUpdater> mUpdater;
|
||||
osg::ref_ptr<osg::Node> mSunFlashNode;
|
||||
osg::ref_ptr<osg::Node> mSunGlareNode;
|
||||
osg::ref_ptr<SunFlashCallback> mSunFlashCallback;
|
||||
osg::ref_ptr<SunGlareCallback> mSunGlareCallback;
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryVisiblePixels;
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryTotalPixels;
|
||||
};
|
||||
|
||||
class Moon : public CelestialBody
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Type_Masser = 0,
|
||||
Type_Secunda
|
||||
};
|
||||
|
||||
Moon(osg::Group* parentNode, Resource::SceneManager& sceneManager, float scaleFactor, Type type);
|
||||
|
||||
~Moon();
|
||||
|
||||
void adjustTransparency(const float ratio) override;
|
||||
void setState(const MoonState state);
|
||||
void setAtmosphereColor(const osg::Vec4f& color);
|
||||
void setColor(const osg::Vec4f& color);
|
||||
|
||||
unsigned int getPhaseInt() const;
|
||||
|
||||
private:
|
||||
Type mType;
|
||||
MoonState::Phase mPhase;
|
||||
osg::ref_ptr<MoonUpdater> mUpdater;
|
||||
|
||||
void setPhase(const MoonState::Phase& phase);
|
||||
};
|
||||
|
||||
class RainCounter : public osgParticle::ConstantRateCounter
|
||||
{
|
||||
public:
|
||||
int numParticlesToCreate(double dt) const override;
|
||||
};
|
||||
|
||||
class RainShooter : public osgParticle::Shooter
|
||||
{
|
||||
public:
|
||||
RainShooter();
|
||||
|
||||
osg::Object* cloneType() const override;
|
||||
|
||||
osg::Object* clone(const osg::CopyOp &) const override;
|
||||
|
||||
void shoot(osgParticle::Particle* particle) const override;
|
||||
|
||||
void setVelocity(const osg::Vec3f& velocity);
|
||||
void setAngle(float angle);
|
||||
|
||||
private:
|
||||
osg::Vec3f mVelocity;
|
||||
float mAngle;
|
||||
};
|
||||
|
||||
class ModVertexAlphaVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
enum MeshType
|
||||
{
|
||||
Atmosphere,
|
||||
Stars,
|
||||
Clouds
|
||||
};
|
||||
|
||||
ModVertexAlphaVisitor(MeshType type);
|
||||
|
||||
void apply(osg::Geometry& geometry) override;
|
||||
|
||||
private:
|
||||
MeshType mType;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,84 @@
|
||||
#version 120
|
||||
|
||||
#include "skypasses.glsl"
|
||||
|
||||
uniform int pass;
|
||||
uniform sampler2D diffuseMap;
|
||||
uniform sampler2D maskMap; // PASS_MOON
|
||||
uniform float opacity; // PASS_CLOUDS, PASS_ATMOSPHERE_NIGHT
|
||||
uniform vec4 moonBlend; // PASS_MOON
|
||||
uniform vec4 atmosphereFade; // PASS_MOON
|
||||
|
||||
varying vec2 diffuseMapUV;
|
||||
varying vec4 passColor;
|
||||
|
||||
void paintAtmosphere(inout vec4 color)
|
||||
{
|
||||
color = gl_FrontMaterial.emission;
|
||||
color.a *= passColor.a;
|
||||
}
|
||||
|
||||
void paintAtmosphereNight(inout vec4 color)
|
||||
{
|
||||
color = texture2D(diffuseMap, diffuseMapUV);
|
||||
color.a *= passColor.a * opacity;
|
||||
}
|
||||
|
||||
void paintClouds(inout vec4 color)
|
||||
{
|
||||
color = texture2D(diffuseMap, diffuseMapUV);
|
||||
color.a *= passColor.a * opacity;
|
||||
color.xyz = clamp(color.xyz * gl_FrontMaterial.emission.xyz, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void paintMoon(inout vec4 color)
|
||||
{
|
||||
vec4 phase = texture2D(diffuseMap, diffuseMapUV);
|
||||
vec4 mask = texture2D(maskMap, diffuseMapUV);
|
||||
|
||||
vec4 blendedLayer = phase * moonBlend;
|
||||
color = vec4(blendedLayer.xyz + atmosphereFade.xyz, atmosphereFade.a * mask.a);
|
||||
}
|
||||
|
||||
void paintSun(inout vec4 color)
|
||||
{
|
||||
color = texture2D(diffuseMap, diffuseMapUV);
|
||||
color.a *= gl_FrontMaterial.diffuse.a;
|
||||
}
|
||||
|
||||
void paintSunflashQuery(inout vec4 color)
|
||||
{
|
||||
const float threshold = 0.8;
|
||||
|
||||
color = texture2D(diffuseMap, diffuseMapUV);
|
||||
if (color.a <= threshold)
|
||||
discard;
|
||||
}
|
||||
|
||||
void paintSunglare(inout vec4 color)
|
||||
{
|
||||
color = gl_FrontMaterial.emission;
|
||||
color.a = gl_FrontMaterial.diffuse.a;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
if (pass == PASS_ATMOSPHERE)
|
||||
paintAtmosphere(color);
|
||||
else if (pass == PASS_ATMOSPHERE_NIGHT)
|
||||
paintAtmosphereNight(color);
|
||||
else if (pass == PASS_CLOUDS)
|
||||
paintClouds(color);
|
||||
else if (pass == PASS_MOON)
|
||||
paintMoon(color);
|
||||
else if (pass == PASS_SUN)
|
||||
paintSun(color);
|
||||
else if (pass == PASS_SUNFLASH_QUERY)
|
||||
paintSunflashQuery(color);
|
||||
else if (pass == PASS_SUNGLARE)
|
||||
paintSunglare(color);
|
||||
|
||||
gl_FragData[0] = color;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#version 120
|
||||
|
||||
#include "skypasses.glsl"
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform int pass;
|
||||
|
||||
varying vec4 passColor;
|
||||
varying vec2 diffuseMapUV;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
passColor = gl_Color;
|
||||
|
||||
if (pass == PASS_CLOUDS)
|
||||
diffuseMapUV = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||
else
|
||||
diffuseMapUV = gl_MultiTexCoord0.xy;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
#define PASS_ATMOSPHERE 0
|
||||
#define PASS_ATMOSPHERE_NIGHT 1
|
||||
#define PASS_CLOUDS 2
|
||||
#define PASS_MOON 3
|
||||
#define PASS_SUN 4
|
||||
#define PASS_SUNFLASH_QUERY 5
|
||||
#define PASS_SUNGLARE 6
|
Loading…
Reference in New Issue