mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 06:35:30 +00:00
implemented weather transitions (currently only blends the clouds)
This commit is contained in:
parent
4efc5bc1f2
commit
41a8b22ebd
@ -64,6 +64,10 @@ RenderingManager::~RenderingManager ()
|
||||
delete mSkyManager;
|
||||
}
|
||||
|
||||
MWRender::SkyManager* RenderingManager::getSkyManager()
|
||||
{
|
||||
return mSkyManager;
|
||||
}
|
||||
|
||||
MWRender::Objects& RenderingManager::getObjects(){
|
||||
return mObjects;
|
||||
|
@ -62,6 +62,8 @@ class RenderingManager: private RenderingInterface {
|
||||
/// MWWorld::Player has been rewritten to not need access
|
||||
/// to internal details of the rendering system anymore
|
||||
|
||||
SkyManager* getSkyManager();
|
||||
|
||||
void toggleLight();
|
||||
bool toggleRenderMode(int mode);
|
||||
|
||||
@ -111,7 +113,9 @@ class RenderingManager: private RenderingInterface {
|
||||
private:
|
||||
|
||||
void setAmbientMode();
|
||||
|
||||
SkyManager* mSkyManager;
|
||||
|
||||
OEngine::Render::OgreRenderer &mRendering;
|
||||
|
||||
MWRender::Objects mObjects;
|
||||
|
@ -44,6 +44,11 @@ void CelestialBody::setPosition(const Vector3& pPosition)
|
||||
mNode->setPosition(finalPosition);
|
||||
}
|
||||
|
||||
void CelestialBody::setColour(const ColourValue& pColour)
|
||||
{
|
||||
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
||||
}
|
||||
|
||||
void CelestialBody::init(const String& textureName,
|
||||
const unsigned int initialSize,
|
||||
const Vector3& pInitialPosition,
|
||||
@ -68,7 +73,7 @@ void CelestialBody::init(const String& textureName,
|
||||
mNode->attachObject(bbSet);
|
||||
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();
|
||||
Pass* p = mMaterial->createTechnique()->createPass();
|
||||
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->setAmbient(0.0,0.0,0.0);
|
||||
p->createTextureUnitState(textureName);
|
||||
bbSet->setMaterialName("CelestialBody"+StringConverter::toString(bodyCount));
|
||||
bbSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
|
||||
|
||||
bodyCount++;
|
||||
}
|
||||
@ -152,6 +157,8 @@ void Moon::setType(const Moon::Type& 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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
void Moon::setColour(const ColourValue& pColour)
|
||||
{
|
||||
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
||||
}
|
||||
|
||||
|
||||
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
||||
{
|
||||
// Get the vertex colour buffer of this mesh
|
||||
@ -367,14 +368,16 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" in float4 color : TEXCOORD1, \n"
|
||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||
" uniform sampler2D secondTexture : TEXUNIT1, \n"
|
||||
" uniform float transitionFactor, \n"
|
||||
" uniform float time, \n"
|
||||
" uniform float opacity, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" uv += float2(1,1) * time * "<<CLOUD_SPEED<<"; \n" // Scroll in x,y direction
|
||||
" float4 tex = tex2D(texture, uv); \n"
|
||||
" oColor = color * float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,opacity); \n"
|
||||
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
||||
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
|
||||
"}";
|
||||
mCloudFragmentShader->setSource(outStream2.str());
|
||||
mCloudFragmentShader->load();
|
||||
@ -400,6 +403,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
|
||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||
mAtmosphereMaterial->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()
|
||||
@ -437,6 +442,7 @@ void SkyManager::disable()
|
||||
|
||||
void SkyManager::setMoonColour (bool red)
|
||||
{
|
||||
/// \todo tweak these colors
|
||||
mSecunda->setColour( red ? ColourValue(1.0, 0.0, 0.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));
|
||||
}
|
||||
|
||||
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 "sky.hpp"
|
||||
#include "../mwworld/weather.hpp"
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
@ -30,7 +31,8 @@ namespace MWRender
|
||||
Ogre::SceneNode* pRootNode
|
||||
);
|
||||
CelestialBody();
|
||||
|
||||
|
||||
void setColour(const Ogre::ColourValue& pColour);
|
||||
void setPosition(const Ogre::Vector3& pPosition);
|
||||
void setVisible(const bool visible);
|
||||
|
||||
@ -59,9 +61,7 @@ namespace MWRender
|
||||
|
||||
void setVisibility(const float pVisibility);
|
||||
///< set the transparency factor for this moon
|
||||
|
||||
void setColour(const Ogre::ColourValue& pColour);
|
||||
|
||||
|
||||
enum Phase
|
||||
{
|
||||
Phase_New = 0,
|
||||
@ -123,6 +123,8 @@ namespace MWRender
|
||||
void setCloudsOpacity(float opacity);
|
||||
///< change opacity of the clouds
|
||||
|
||||
void setWeather(const MWWorld::WeatherResult& weather);
|
||||
|
||||
private:
|
||||
CelestialBody* mSun;
|
||||
Moon* mMasser;
|
||||
@ -137,6 +139,14 @@ namespace MWRender
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
@ -2,9 +2,99 @@
|
||||
|
||||
#include "../mwrender/renderingmanager.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWWorld;
|
||||
|
||||
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering)
|
||||
#define TRANSITION_TIME 10
|
||||
|
||||
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering) :
|
||||
mCurrentWeather("clear")
|
||||
{
|
||||
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
|
||||
{
|
||||
/// 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
|
||||
struct Weather
|
||||
{
|
||||
@ -83,7 +112,7 @@ namespace MWWorld
|
||||
* @param instant
|
||||
* 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
|
||||
@ -93,6 +122,16 @@ namespace MWWorld
|
||||
|
||||
private:
|
||||
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)
|
||||
{
|
||||
mWorldScene->update (duration);
|
||||
|
||||
mWeatherManager->update (duration);
|
||||
}
|
||||
|
||||
OEngine::Render::Fader* World::getFader()
|
||||
|
Loading…
x
Reference in New Issue
Block a user