introduce sky shaders

pull/3204/head
glassmancody.info 3 years ago
parent 41318a585f
commit 1e40d27318

@ -11,6 +11,8 @@
Bug #4602: Robert's Bodies: crash inside createInstance()
Bug #4700: Editor: Incorrect command implementation
Bug #4744: Invisible particles must still be processed
Bug #4752: UpdateCellCommand doesn't undo properly
Bug #5088: Sky abruptly changes direction during certain weather transitions
Bug #5100: Persuasion doesn't always clamp the resulting disposition
Bug #5120: Scripted object spawning updates physics system
Bug #5207: Loose summons can be present in scene
@ -40,6 +42,7 @@
Bug #6133: Cannot reliably sneak or steal in the sight of the NPCs siding with player
Bug #6143: Capturing a screenshot makes engine to be a temporary unresponsive
Bug #6165: Paralyzed player character can pickup items when the inventory is open
Bug #6168: Weather particles flicker for a frame at start of storms
Bug #6172: Some creatures can't open doors
Bug #6174: Spellmaking and Enchanting sliders differences from vanilla
Bug #6184: Command and Calm and Demoralize and Frenzy and Rally magic effects inconsistencies with vanilla
@ -73,6 +76,7 @@
Feature #6017: Separate persistent and temporary cell references when saving
Feature #6032: Reverse-z depth buffer
Feature #6078: First person should not clear depth buffer
Feature #6161: Refactor Sky to use shaders and GLES/GL3 friendly
Feature #6162: Refactor GUI to use shaders and to be GLES and GL3+ friendly
Feature #6199: Support FBO Rendering
Feature #6249: Alpha testing support for Collada

@ -19,7 +19,7 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
actors objects renderingmanager animation rotatecontroller sky skyutil npcanimation vismask
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager
bulletdebugdraw globalmap characterpreview camera viewovershoulder localmap water terrainstorage ripplesimulation
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover postprocessor

File diff suppressed because it is too large Load Diff

@ -8,10 +8,7 @@
#include <osg/ref_ptr>
#include <osg/Vec4f>
namespace osg
{
class Camera;
}
#include "skyutil.hpp"
namespace osg
{
@ -19,6 +16,7 @@ namespace osg
class Node;
class Material;
class PositionAttitudeTransform;
class Camera;
}
namespace osgParticle
@ -45,80 +43,6 @@ namespace MWRender
class AlphaFader;
class UnderwaterSwitchCallback;
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;
};
struct MoonState
{
enum class Phase
{
Full = 0,
WaningGibbous,
ThirdQuarter,
WaningCrescent,
New,
WaxingCrescent,
FirstQuarter,
WaxingGibbous,
Unspecified
};
float mRotationFromHorizon;
float mRotationFromNorth;
Phase mPhase;
float mShadowBlend;
float mMoonAlpha;
};
///@brief The SkyManager handles rendering of the sky domes, celestial bodies as well as other objects that need to be rendered
/// relative to the camera (e.g. weather particle effects)
class SkyManager
@ -162,7 +86,7 @@ namespace MWRender
void setRainSpeed(float speed);
void setStormDirection(const osg::Vec3f& direction);
void setStormParticleDirection(const osg::Vec3f& direction);
void setSunDirection(const osg::Vec3f& direction);
@ -203,12 +127,12 @@ namespace MWRender
osg::ref_ptr<osg::Node> mParticleEffect;
osg::ref_ptr<UnderwaterSwitchCallback> mUnderwaterSwitch;
osg::ref_ptr<osg::PositionAttitudeTransform> mCloudNode;
osg::ref_ptr<osg::Group> mCloudNode;
osg::ref_ptr<CloudUpdater> mCloudUpdater;
osg::ref_ptr<CloudUpdater> mCloudUpdater2;
osg::ref_ptr<osg::Node> mCloudMesh;
osg::ref_ptr<osg::Node> mCloudMesh2;
osg::ref_ptr<CloudUpdater> mNextCloudUpdater;
osg::ref_ptr<osg::PositionAttitudeTransform> mCloudMesh;
osg::ref_ptr<osg::PositionAttitudeTransform> mNextCloudMesh;
osg::ref_ptr<osg::Node> mAtmosphereDay;
@ -239,7 +163,10 @@ namespace MWRender
float mRainTimer;
// particle system rotation is independent of cloud rotation internally
osg::Vec3f mStormParticleDirection;
osg::Vec3f mStormDirection;
osg::Vec3f mNextStormDirection;
// remember some settings so we don't have to apply them again if they didn't change
std::string mClouds;
@ -275,4 +202,4 @@ namespace MWRender
};
}
#endif // GAME_RENDER_SKY_H
#endif

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

@ -115,6 +115,8 @@ namespace MWWorld
class Weather
{
public:
static osg::Vec3f defaultDirection();
Weather(const std::string& name,
float stormWindSpeed,
float rainSpeed,
@ -189,6 +191,8 @@ namespace MWWorld
std::string mRainEffect;
osg::Vec3f mStormDirection;
// Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature
// is broken in the vanilla game and was disabled.

@ -516,6 +516,10 @@ namespace Shader
// We could fall back to a texture size uniform if EXT_gpu_shader4 is missing
}
bool simpleLighting = false;
node.getUserValue("simpleLighting", simpleLighting);
defineMap["simpleLighting"] = simpleLighting ? "1" : "0";
if (writableStateSet->getMode(GL_ALPHA_TEST) != osg::StateAttribute::INHERIT && !previousAddedState->hasMode(GL_ALPHA_TEST))
removedState->setMode(GL_ALPHA_TEST, writableStateSet->getMode(GL_ALPHA_TEST));
// This disables the deprecated fixed-function alpha test

@ -36,6 +36,9 @@ set(SHADER_FILES
gui_fragment.glsl
debug_vertex.glsl
debug_fragment.glsl
sky_vertex.glsl
sky_fragment.glsl
skypasses.glsl
)
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_SHADERS_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")

@ -87,6 +87,16 @@ void doLighting(vec3 viewPos, vec3 viewNormal, out vec3 diffuseLight, out vec3 a
}
}
// Simplest lighting which only takes into account sun and ambient. Currently used for our weather particle systems.
void doSimpleLighting(vec3 viewPos, vec3 viewNormal, out vec3 diffuseLight, out vec3 ambientLight)
{
vec3 ambientOut, diffuseOut;
perLightSun(diffuseOut, viewPos, viewNormal);
ambientLight = gl_LightModel.ambient.xyz;
diffuseLight = diffuseOut;
}
vec3 getSpecular(vec3 viewNormal, vec3 viewDirection, float shininess, vec3 matSpec)
{
vec3 lightDir = normalize(lcalcPosition(0));

@ -63,7 +63,7 @@ uniform bool simpleWater;
varying float euclideanDepth;
varying float linearDepth;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
#define PER_PIXEL_LIGHTING ((@normalMap || @forcePPL) && !@simpleLighting)
#if !PER_PIXEL_LIGHTING
centroid varying vec3 passLighting;
@ -170,6 +170,9 @@ void main()
#endif
float shadowing = unshadowedLightRatio(linearDepth);
#if @simpleLighting
gl_FragData[0].xyz *= passLighting;
#else
vec3 lighting;
#if !PER_PIXEL_LIGHTING
lighting = passLighting + shadowDiffuseLighting * shadowing;
@ -180,8 +183,8 @@ void main()
lighting = diffuseColor.xyz * diffuseLight + getAmbientColor().xyz * ambientLight + emission;
clampLightingResult(lighting);
#endif
gl_FragData[0].xyz *= lighting;
#endif
#if @envMap && !@preLightEnv
gl_FragData[0].xyz += texture2D(envMap, envTexCoordGen).xyz * envMapColor.xyz * envLuma;
@ -207,6 +210,7 @@ void main()
#endif
gl_FragData[0].xyz += getSpecular(normalize(viewNormal), normalize(passViewPos.xyz), shininess, matSpec) * shadowing;
}
#if @radialFog
float depth;
// For the less detailed mesh of simple water we need to recalculate depth on per-pixel basis

@ -50,7 +50,7 @@ varying vec2 specularMapUV;
varying float euclideanDepth;
varying float linearDepth;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
#define PER_PIXEL_LIGHTING ((@normalMap || @forcePPL) && !@simpleLighting)
#if !PER_PIXEL_LIGHTING
centroid varying vec3 passLighting;
@ -126,7 +126,11 @@ void main(void)
#if !PER_PIXEL_LIGHTING
vec3 diffuseLight, ambientLight;
doLighting(viewPos.xyz, viewNormal, diffuseLight, ambientLight, shadowDiffuseLighting);
#if @simpleLighting
doSimpleLighting(passViewPos, viewNormal, diffuseLight, ambientLight);
#else
doLighting(passViewPos, viewNormal, diffuseLight, ambientLight, shadowDiffuseLighting);
#endif
vec3 emission = getEmissionColor().xyz * emissiveMult;
passLighting = getDiffuseColor().xyz * diffuseLight + getAmbientColor().xyz * ambientLight + emission;
clampLightingResult(passLighting);

@ -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…
Cancel
Save