forked from mirror/openmw-tes3mp
implemented weather transitions (currently only blends the clouds)
This commit is contained in:
parent
4efc5bc1f2
commit
41a8b22ebd
7 changed files with 199 additions and 16 deletions
|
@ -64,6 +64,10 @@ RenderingManager::~RenderingManager ()
|
||||||
delete mSkyManager;
|
delete mSkyManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWRender::SkyManager* RenderingManager::getSkyManager()
|
||||||
|
{
|
||||||
|
return mSkyManager;
|
||||||
|
}
|
||||||
|
|
||||||
MWRender::Objects& RenderingManager::getObjects(){
|
MWRender::Objects& RenderingManager::getObjects(){
|
||||||
return mObjects;
|
return mObjects;
|
||||||
|
|
|
@ -62,6 +62,8 @@ class RenderingManager: private RenderingInterface {
|
||||||
/// MWWorld::Player has been rewritten to not need access
|
/// MWWorld::Player has been rewritten to not need access
|
||||||
/// to internal details of the rendering system anymore
|
/// to internal details of the rendering system anymore
|
||||||
|
|
||||||
|
SkyManager* getSkyManager();
|
||||||
|
|
||||||
void toggleLight();
|
void toggleLight();
|
||||||
bool toggleRenderMode(int mode);
|
bool toggleRenderMode(int mode);
|
||||||
|
|
||||||
|
@ -111,7 +113,9 @@ class RenderingManager: private RenderingInterface {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void setAmbientMode();
|
void setAmbientMode();
|
||||||
|
|
||||||
SkyManager* mSkyManager;
|
SkyManager* mSkyManager;
|
||||||
|
|
||||||
OEngine::Render::OgreRenderer &mRendering;
|
OEngine::Render::OgreRenderer &mRendering;
|
||||||
|
|
||||||
MWRender::Objects mObjects;
|
MWRender::Objects mObjects;
|
||||||
|
|
|
@ -44,6 +44,11 @@ void CelestialBody::setPosition(const Vector3& pPosition)
|
||||||
mNode->setPosition(finalPosition);
|
mNode->setPosition(finalPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CelestialBody::setColour(const ColourValue& pColour)
|
||||||
|
{
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
||||||
|
}
|
||||||
|
|
||||||
void CelestialBody::init(const String& textureName,
|
void CelestialBody::init(const String& textureName,
|
||||||
const unsigned int initialSize,
|
const unsigned int initialSize,
|
||||||
const Vector3& pInitialPosition,
|
const Vector3& pInitialPosition,
|
||||||
|
@ -68,7 +73,7 @@ void CelestialBody::init(const String& textureName,
|
||||||
mNode->attachObject(bbSet);
|
mNode->attachObject(bbSet);
|
||||||
bbSet->createBillboard(0,0,0);
|
bbSet->createBillboard(0,0,0);
|
||||||
|
|
||||||
mMaterial = MaterialManager::getSingleton().create("CelestialBody"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||||
mMaterial->removeAllTechniques();
|
mMaterial->removeAllTechniques();
|
||||||
Pass* p = mMaterial->createTechnique()->createPass();
|
Pass* p = mMaterial->createTechnique()->createPass();
|
||||||
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
@ -78,7 +83,7 @@ void CelestialBody::init(const String& textureName,
|
||||||
p->setDiffuse(0.0,0.0,0.0,1.0);
|
p->setDiffuse(0.0,0.0,0.0,1.0);
|
||||||
p->setAmbient(0.0,0.0,0.0);
|
p->setAmbient(0.0,0.0,0.0);
|
||||||
p->createTextureUnitState(textureName);
|
p->createTextureUnitState(textureName);
|
||||||
bbSet->setMaterialName("CelestialBody"+StringConverter::toString(bodyCount));
|
bbSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
|
||||||
|
|
||||||
bodyCount++;
|
bodyCount++;
|
||||||
}
|
}
|
||||||
|
@ -152,6 +157,8 @@ void Moon::setType(const Moon::Type& type)
|
||||||
mType = type;
|
mType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// \todo the moon phase rendering is not correct - the dark part of the moon does not occlude the stars
|
||||||
void Moon::setPhase(const Moon::Phase& phase)
|
void Moon::setPhase(const Moon::Phase& phase)
|
||||||
{
|
{
|
||||||
Ogre::String textureName = "textures\\tx_";
|
Ogre::String textureName = "textures\\tx_";
|
||||||
|
@ -199,12 +206,6 @@ void Moon::setVisibility(const float pVisibility)
|
||||||
mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("visibilityFactor", Real(pVisibility));
|
mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("visibilityFactor", Real(pVisibility));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Moon::setColour(const ColourValue& pColour)
|
|
||||||
{
|
|
||||||
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
||||||
{
|
{
|
||||||
// Get the vertex colour buffer of this mesh
|
// Get the vertex colour buffer of this mesh
|
||||||
|
@ -367,14 +368,16 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
|
||||||
" out float4 oColor : COLOR, \n"
|
" out float4 oColor : COLOR, \n"
|
||||||
" in float4 color : TEXCOORD1, \n"
|
" in float4 color : TEXCOORD1, \n"
|
||||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
|
" uniform sampler2D secondTexture : TEXUNIT1, \n"
|
||||||
|
" uniform float transitionFactor, \n"
|
||||||
" uniform float time, \n"
|
" uniform float time, \n"
|
||||||
" uniform float opacity, \n"
|
" uniform float opacity, \n"
|
||||||
" uniform float4 emissive \n"
|
" uniform float4 emissive \n"
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" uv += float2(1,1) * time * "<<CLOUD_SPEED<<"; \n" // Scroll in x,y direction
|
" uv += float2(1,1) * time * "<<CLOUD_SPEED<<"; \n" // Scroll in x,y direction
|
||||||
" float4 tex = tex2D(texture, uv); \n"
|
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
||||||
" oColor = color * float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,opacity); \n"
|
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
|
||||||
"}";
|
"}";
|
||||||
mCloudFragmentShader->setSource(outStream2.str());
|
mCloudFragmentShader->setSource(outStream2.str());
|
||||||
mCloudFragmentShader->load();
|
mCloudFragmentShader->load();
|
||||||
|
@ -400,6 +403,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
|
||||||
}
|
}
|
||||||
|
|
||||||
SkyManager::~SkyManager()
|
SkyManager::~SkyManager()
|
||||||
|
@ -437,6 +442,7 @@ void SkyManager::disable()
|
||||||
|
|
||||||
void SkyManager::setMoonColour (bool red)
|
void SkyManager::setMoonColour (bool red)
|
||||||
{
|
{
|
||||||
|
/// \todo tweak these colors
|
||||||
mSecunda->setColour( red ? ColourValue(1.0, 0.0, 0.0)
|
mSecunda->setColour( red ? ColourValue(1.0, 0.0, 0.0)
|
||||||
: ColourValue(1.0, 1.0, 1.0));
|
: ColourValue(1.0, 1.0, 1.0));
|
||||||
}
|
}
|
||||||
|
@ -445,3 +451,31 @@ void SkyManager::setCloudsOpacity(float opacity)
|
||||||
{
|
{
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
||||||
|
{
|
||||||
|
if (mClouds != weather.mCloudTexture)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("textures\\"+weather.mCloudTexture);
|
||||||
|
mClouds = weather.mCloudTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mNextClouds != weather.mNextCloudTexture)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("textures\\"+weather.mNextCloudTexture);
|
||||||
|
mNextClouds = weather.mNextCloudTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCloudBlendFactor != weather.mCloudBlendFactor)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("transitionFactor", Real(weather.mCloudBlendFactor));
|
||||||
|
mCloudBlendFactor = weather.mCloudBlendFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCloudOpacity != weather.mCloudOpacity)
|
||||||
|
{
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(weather.mCloudOpacity));
|
||||||
|
mCloudOpacity = weather.mCloudOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <OgreHighLevelGpuProgram.h>
|
#include <OgreHighLevelGpuProgram.h>
|
||||||
|
|
||||||
#include "sky.hpp"
|
#include "sky.hpp"
|
||||||
|
#include "../mwworld/weather.hpp"
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
@ -31,6 +32,7 @@ namespace MWRender
|
||||||
);
|
);
|
||||||
CelestialBody();
|
CelestialBody();
|
||||||
|
|
||||||
|
void setColour(const Ogre::ColourValue& pColour);
|
||||||
void setPosition(const Ogre::Vector3& pPosition);
|
void setPosition(const Ogre::Vector3& pPosition);
|
||||||
void setVisible(const bool visible);
|
void setVisible(const bool visible);
|
||||||
|
|
||||||
|
@ -60,8 +62,6 @@ namespace MWRender
|
||||||
void setVisibility(const float pVisibility);
|
void setVisibility(const float pVisibility);
|
||||||
///< set the transparency factor for this moon
|
///< set the transparency factor for this moon
|
||||||
|
|
||||||
void setColour(const Ogre::ColourValue& pColour);
|
|
||||||
|
|
||||||
enum Phase
|
enum Phase
|
||||||
{
|
{
|
||||||
Phase_New = 0,
|
Phase_New = 0,
|
||||||
|
@ -123,6 +123,8 @@ namespace MWRender
|
||||||
void setCloudsOpacity(float opacity);
|
void setCloudsOpacity(float opacity);
|
||||||
///< change opacity of the clouds
|
///< change opacity of the clouds
|
||||||
|
|
||||||
|
void setWeather(const MWWorld::WeatherResult& weather);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CelestialBody* mSun;
|
CelestialBody* mSun;
|
||||||
Moon* mMasser;
|
Moon* mMasser;
|
||||||
|
@ -137,6 +139,14 @@ namespace MWRender
|
||||||
|
|
||||||
Ogre::HighLevelGpuProgramPtr mCloudFragmentShader;
|
Ogre::HighLevelGpuProgramPtr mCloudFragmentShader;
|
||||||
|
|
||||||
|
// remember the cloud texture names used right now, so we don't have to set the texture names if they didnt change
|
||||||
|
Ogre::String mClouds;
|
||||||
|
Ogre::String mNextClouds;
|
||||||
|
float mCloudBlendFactor;
|
||||||
|
float mCloudOpacity;
|
||||||
|
|
||||||
|
float mRemainingTransitionTime;
|
||||||
|
|
||||||
void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType);
|
void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,99 @@
|
||||||
|
|
||||||
#include "../mwrender/renderingmanager.hpp"
|
#include "../mwrender/renderingmanager.hpp"
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
using namespace MWWorld;
|
using namespace MWWorld;
|
||||||
|
|
||||||
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering)
|
#define TRANSITION_TIME 10
|
||||||
|
|
||||||
|
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering) :
|
||||||
|
mCurrentWeather("clear")
|
||||||
{
|
{
|
||||||
mRendering = rendering;
|
mRendering = rendering;
|
||||||
|
|
||||||
|
/// \todo read these from Morrowind.ini
|
||||||
|
Weather clear;
|
||||||
|
clear.mCloudTexture = "tx_sky_clear.dds";
|
||||||
|
clear.mCloudsMaximumPercent = 0.75;
|
||||||
|
mWeatherSettings["clear"] = clear;
|
||||||
|
|
||||||
|
Weather cloudy;
|
||||||
|
cloudy.mCloudTexture = "tx_sky_cloudy.dds";
|
||||||
|
cloudy.mCloudsMaximumPercent = 0.9;
|
||||||
|
mWeatherSettings["cloudy"] = cloudy;
|
||||||
|
|
||||||
|
Weather overcast;
|
||||||
|
overcast.mCloudTexture = "tx_sky_overcast.dds";
|
||||||
|
overcast.mCloudsMaximumPercent = 1.0;
|
||||||
|
mWeatherSettings["overcast"] = overcast;
|
||||||
|
|
||||||
|
setWeather("clear", true);
|
||||||
|
setWeather("cloudy", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::setWeather(const String& weather, bool instant)
|
||||||
|
{
|
||||||
|
if (instant)
|
||||||
|
{
|
||||||
|
mNextWeather = "";
|
||||||
|
mCurrentWeather = weather;
|
||||||
|
}
|
||||||
|
else if (weather != mCurrentWeather)
|
||||||
|
{
|
||||||
|
mNextWeather = weather;
|
||||||
|
mRemainingTransitionTime = TRANSITION_TIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherResult WeatherManager::getResult()
|
||||||
|
{
|
||||||
|
const Weather& current = mWeatherSettings[mCurrentWeather];
|
||||||
|
WeatherResult result;
|
||||||
|
|
||||||
|
result.mCloudTexture = current.mCloudTexture;
|
||||||
|
result.mCloudBlendFactor = 0;
|
||||||
|
result.mCloudOpacity = current.mCloudsMaximumPercent;
|
||||||
|
/// \todo
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherResult WeatherManager::transition(const Weather& other, float factor)
|
||||||
|
{
|
||||||
|
const Weather& current = mWeatherSettings[mCurrentWeather];
|
||||||
|
WeatherResult result;
|
||||||
|
|
||||||
|
result.mCloudTexture = current.mCloudTexture;
|
||||||
|
result.mNextCloudTexture = other.mCloudTexture;
|
||||||
|
result.mCloudBlendFactor = factor;
|
||||||
|
|
||||||
|
#define lerp(x, y) (x * (1-factor) + y * factor)
|
||||||
|
|
||||||
|
result.mCloudOpacity = lerp(current.mCloudsMaximumPercent, other.mCloudsMaximumPercent);
|
||||||
|
|
||||||
|
/// \todo
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::update(float duration)
|
||||||
|
{
|
||||||
|
WeatherResult result;
|
||||||
|
|
||||||
|
if (mNextWeather != "")
|
||||||
|
{
|
||||||
|
mRemainingTransitionTime -= duration;
|
||||||
|
if (mRemainingTransitionTime < 0)
|
||||||
|
{
|
||||||
|
mCurrentWeather = mNextWeather;
|
||||||
|
mNextWeather = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mNextWeather != "")
|
||||||
|
result = transition(mWeatherSettings[mNextWeather], 1-(mRemainingTransitionTime/TRANSITION_TIME));
|
||||||
|
else
|
||||||
|
result = getResult();
|
||||||
|
|
||||||
|
mRendering->getSkyManager()->setWeather(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,35 @@ namespace MWRender
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
/// Defines the actual weather that results from weather setting (see below), time of day and weather transition
|
||||||
|
struct WeatherResult
|
||||||
|
{
|
||||||
|
Ogre::String mCloudTexture;
|
||||||
|
Ogre::String mNextCloudTexture;
|
||||||
|
float mCloudBlendFactor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mFogColor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mAmbientColor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mSunColor;
|
||||||
|
|
||||||
|
Ogre::ColourValue mSunDiscColor;
|
||||||
|
|
||||||
|
float mFogDepth;
|
||||||
|
|
||||||
|
float mWindSpeed;
|
||||||
|
|
||||||
|
float mCloudSpeed;
|
||||||
|
|
||||||
|
float mCloudOpacity;
|
||||||
|
|
||||||
|
float mGlareView;
|
||||||
|
|
||||||
|
Ogre::String mAmbientLoopSoundID;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Defines a single weather setting
|
/// Defines a single weather setting
|
||||||
struct Weather
|
struct Weather
|
||||||
{
|
{
|
||||||
|
@ -83,7 +112,7 @@ namespace MWWorld
|
||||||
* @param instant
|
* @param instant
|
||||||
* if true, the weather changes instantly. if false, it slowly starts transitioning.
|
* if true, the weather changes instantly. if false, it slowly starts transitioning.
|
||||||
*/
|
*/
|
||||||
void setWeather(const Weather& weather, bool instant=false);
|
void setWeather(const Ogre::String& weather, bool instant=false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per-frame update
|
* Per-frame update
|
||||||
|
@ -93,6 +122,16 @@ namespace MWWorld
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MWRender::RenderingManager* mRendering;
|
MWRender::RenderingManager* mRendering;
|
||||||
|
|
||||||
|
std::map<Ogre::String, Weather> mWeatherSettings;
|
||||||
|
|
||||||
|
Ogre::String mCurrentWeather;
|
||||||
|
Ogre::String mNextWeather;
|
||||||
|
|
||||||
|
float mRemainingTransitionTime;
|
||||||
|
|
||||||
|
WeatherResult transition(const Weather& other, const float factor);
|
||||||
|
WeatherResult getResult();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -693,6 +693,8 @@ namespace MWWorld
|
||||||
void World::update (float duration)
|
void World::update (float duration)
|
||||||
{
|
{
|
||||||
mWorldScene->update (duration);
|
mWorldScene->update (duration);
|
||||||
|
|
||||||
|
mWeatherManager->update (duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
OEngine::Render::Fader* World::getFader()
|
OEngine::Render::Fader* World::getFader()
|
||||||
|
|
Loading…
Reference in a new issue