589 lines
18 KiB
C++
589 lines
18 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "stdpch.h"
|
|
|
|
|
|
/////////////
|
|
// INCLUDE //
|
|
/////////////
|
|
// 3D Interface
|
|
#include "nel/3d/u_instance.h"
|
|
#include "nel/3d/u_scene.h"
|
|
#include "nel/3d/u_water.h"
|
|
#include "nel/3d/u_landscape.h"
|
|
|
|
// Client.
|
|
#include "light_cycle_manager.h"
|
|
#include "client_cfg.h"
|
|
#include "ig_client.h"
|
|
#include "user_entity.h"
|
|
#include "pacs_client.h"
|
|
#include "world_database_manager.h"
|
|
#include "continent_manager.h"
|
|
#include "continent.h"
|
|
#include "ig_enum.h"
|
|
#include "ig_callback.h"
|
|
#include "pacs_client.h"
|
|
#include "sound_manager.h"
|
|
#include "weather_manager_client.h"
|
|
#include "misc.h"
|
|
#include "interface_v3/interface_manager.h"
|
|
|
|
//#include "sound_manager.h" // \todo GUIGUI : uncomment after new FE done and class modified
|
|
|
|
|
|
H_AUTO_DECL(RZ_LightCycleManager)
|
|
|
|
///////////
|
|
// USING //
|
|
///////////
|
|
using namespace NLMISC;
|
|
using namespace NL3D;
|
|
using namespace NLPACS;
|
|
using namespace std;
|
|
|
|
|
|
////////////
|
|
// EXTERN //
|
|
////////////
|
|
extern UDriver *Driver;
|
|
extern UScene *Scene;
|
|
extern UScene *SceneRoot;
|
|
|
|
extern EGSPD::CSeason::TSeason CurrSeason;
|
|
|
|
|
|
////////////
|
|
// EXTERN //
|
|
////////////
|
|
extern ULandscape *Landscape;
|
|
|
|
static uint diffColors(CRGBA c1, CRGBA c2)
|
|
{
|
|
return (uint) maxof(abs((sint) c1.R - c2.R), abs((sint) c1.G - c2.G), abs((sint) c1.B - c2.B));
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
float CLightCycleDesc::getNightTransitionLength() const
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
return NightTransitionEndHour >= NightTransitionStartHour ? NightTransitionEndHour - NightTransitionStartHour
|
|
: NightTransitionEndHour + NumHours - NightTransitionStartHour;
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
float CLightCycleDesc::getDawnTransitionLength() const
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
return DawnTransitionEndHour >= DawnTransitionStartHour ? DawnTransitionEndHour - DawnTransitionStartHour
|
|
: DawnTransitionEndHour + NumHours - DawnTransitionStartHour;
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
CLightCycleManager::CLightCycleManager() :
|
|
_Hour(0),
|
|
_Touched(true),
|
|
_ValidDesc(false),
|
|
_LightLevel(0),
|
|
_WeatherLighting(0),
|
|
_LastWeatherLighting(0),
|
|
_UpdateFreq(0),
|
|
_State(StateUnknown),
|
|
_PrevState(StateUnknown)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::getLandscapeLightColor(NLMISC::CRGBA &diffuse, NLMISC::CRGBA &ambiant)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
nlassert(_LightLevel >= 0 && _LightLevel <= 1.f);
|
|
|
|
if(ContinentMngr.cur())
|
|
{
|
|
switch(_State)
|
|
{
|
|
case DayToNight:
|
|
if (_LightLevel <= _Desc.DuskRatio)
|
|
{
|
|
// day->dusk
|
|
uint level = (uint) (256.f * (_Desc.DuskRatio != 0.f ? _LightLevel / _Desc.DuskRatio : 0.f));
|
|
diffuse.blendFromui(ContinentMngr.cur()->LandscapeLightDay.Diffuse, ContinentMngr.cur()->LandscapeLightDusk.Diffuse, level);
|
|
ambiant.blendFromui(ContinentMngr.cur()->LandscapeLightDay.Ambiant, ContinentMngr.cur()->LandscapeLightDusk.Ambiant, level);
|
|
}
|
|
else
|
|
{
|
|
// dusk->night
|
|
uint level = (uint) (256.f * (_Desc.DuskRatio != 1.f ? (_LightLevel - _Desc.DuskRatio) / (1.f - _Desc.DuskRatio) : 0.f));
|
|
diffuse.blendFromui(ContinentMngr.cur()->LandscapeLightDusk.Diffuse, ContinentMngr.cur()->LandscapeLightNight.Diffuse, level);
|
|
ambiant.blendFromui(ContinentMngr.cur()->LandscapeLightDusk.Ambiant, ContinentMngr.cur()->LandscapeLightNight.Ambiant, level);
|
|
}
|
|
break;
|
|
default:
|
|
uint level = (uint) (256.f * _LightLevel);
|
|
diffuse.blendFromui(ContinentMngr.cur()->LandscapeLightDay.Diffuse, ContinentMngr.cur()->LandscapeLightNight.Diffuse, level);
|
|
ambiant.blendFromui(ContinentMngr.cur()->LandscapeLightDay.Ambiant, ContinentMngr.cur()->LandscapeLightNight.Ambiant, level);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
bool CLightCycleManager::setLightDesc(const CLightCycleDesc &desc)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
if (desc.NightTransitionStartHour > desc.NumHours)
|
|
{
|
|
nlwarning ("NightTransitionStartHour (%d) > NumHours (%d)", desc.NightTransitionStartHour, desc.NumHours);
|
|
_State = StateUnknown;
|
|
return false;
|
|
}
|
|
|
|
if (desc.NightTransitionEndHour > desc.NumHours)
|
|
{
|
|
nlwarning ("NightTransitionEndHour (%d) > NumHours (%d)", desc.NightTransitionEndHour, desc.NumHours);
|
|
_State = StateUnknown;
|
|
return false;
|
|
}
|
|
//
|
|
if (desc.DawnTransitionStartHour > desc.NumHours)
|
|
{
|
|
nlwarning ("DawnTransitionStartHour (%d) > NumHours (%d)", desc.DawnTransitionStartHour, desc.NumHours);
|
|
_State = StateUnknown;
|
|
return false;
|
|
}
|
|
if (desc.DawnTransitionEndHour > desc.NumHours)
|
|
{
|
|
nlwarning ("DawnTransitionEndHour (%d) > NumHours (%d)", desc.DawnTransitionEndHour, desc.NumHours);
|
|
_State = StateUnknown;
|
|
return false;
|
|
}
|
|
//
|
|
// test if intervals are not overlapping
|
|
if (!(desc.DawnTransitionStartHour >= desc.NightTransitionEndHour
|
|
|| desc.DawnTransitionEndHour <= desc.NightTransitionStartHour
|
|
)
|
|
)
|
|
{
|
|
nlwarning("!(DawnTransitionStartHour (%d) >= NightTransitionEndHour (%d) || DawnTransitionEndHour (%d) <= NightTransitionStartHour (%d))",
|
|
desc.DawnTransitionStartHour, desc.NightTransitionEndHour, desc.DawnTransitionEndHour, desc.NightTransitionStartHour);
|
|
_State = StateUnknown;
|
|
return false;
|
|
}
|
|
//
|
|
|
|
//
|
|
_Desc = desc;
|
|
_ValidDesc = true;
|
|
_Hour = 0;
|
|
updateState();
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
float CLightCycleManager::getUpdateDuration() const
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
if (!_ValidDesc || _UpdateFreq == 0.f) return 0.f;
|
|
return (1.f / _UpdateFreq) / _Desc.RealDayLength * _Desc.NumHours;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
std::string CLightCycleManager::getStateString() const
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
switch(_State)
|
|
{
|
|
case NightToDay: return "night->day";
|
|
case DayToNight: return "day->night";
|
|
case Day: return "day";
|
|
case Night: return "night";
|
|
default:
|
|
return "???";
|
|
}
|
|
return "???";
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::updateState()
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
_PrevState = _State;
|
|
if(isInInterval(_Desc.DawnTransitionStartHour, _Desc.DawnTransitionEndHour, _Hour))
|
|
{
|
|
// night->day
|
|
_State = NightToDay;
|
|
return;
|
|
}
|
|
else if(isInInterval(_Desc.DawnTransitionEndHour, _Desc.NightTransitionStartHour, _Hour))
|
|
{
|
|
// day
|
|
_State = Day;
|
|
return;
|
|
}
|
|
else if(isInInterval(_Desc.NightTransitionStartHour, _Desc.NightTransitionEndHour, _Hour))
|
|
{
|
|
// day->night
|
|
_State = DayToNight;
|
|
return;
|
|
}
|
|
else if(isInInterval(_Desc.NightTransitionEndHour, _Desc.DawnTransitionStartHour, _Hour))
|
|
{
|
|
// night
|
|
if( _PrevState != Night && _PrevState != StateUnknown)
|
|
{
|
|
CInterfaceManager * pIM = CInterfaceManager::getInstance();
|
|
if( pIM )
|
|
{
|
|
pIM->runActionHandler("set",NULL,"dblink=UI:VARIABLES:NIGHT_WARNING_WANTED|value=1");
|
|
}
|
|
}
|
|
_State = Night;
|
|
return;
|
|
}
|
|
_State = StateUnknown;
|
|
return;
|
|
}
|
|
//
|
|
|
|
//-----------------------------------------------
|
|
bool CLightCycleManager::isInTransition() const
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
return isInInterval(_Desc.DawnTransitionStartHour, _Desc.DawnTransitionEndHour, _Hour)
|
|
|| isInInterval(_Desc.NightTransitionStartHour, _Desc.DawnTransitionEndHour, _Hour);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::setHour(float hour, const CWeatherManagerClient &wm, NLMISC::CRGBA lightningColor)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
if (!_ValidDesc) return;
|
|
if (hour < 0) hour = 0;
|
|
if (hour > _Desc.NumHours)
|
|
{
|
|
hour -= ::floorf(hour / _Desc.NumHours) * _Desc.NumHours;
|
|
}
|
|
float updateDuration = getUpdateDuration();
|
|
if (fabs(_Hour - hour) >= (4.f * updateDuration))
|
|
{
|
|
touch();
|
|
}
|
|
_Hour = hour;
|
|
_LightLevel = getLightLevel(hour);
|
|
clamp(_LightLevel, 0.f, 1.f); // should not be necessary, but we avoid imprecisions
|
|
updateState();
|
|
|
|
_WeatherLighting = wm.getCurrWeatherState().Lighting;
|
|
|
|
// Change water lighting
|
|
NL3D::UWaterHeightMapManager::setBlendFactor(Driver, _LightLevel);
|
|
|
|
if (_PrevState != _State)
|
|
{
|
|
if (_State == Night || _State == Day)
|
|
{
|
|
// a transiation has ended, so release textures used for the blend
|
|
NL3D::UWaterHeightMapManager::releaseBlendTextures();
|
|
}
|
|
}
|
|
|
|
// directionnal lights
|
|
// (override the global light by the light in the weather manager : during bad weather, the scene can be darker)
|
|
setupCanopyLight(_WeatherLighting);
|
|
setupMainLight(_WeatherLighting);
|
|
|
|
// landscape lighting
|
|
CRGBA diffuse, ambiant;
|
|
getLandscapeLightColor(diffuse, ambiant);
|
|
|
|
bool colorTouched = diffuse != _LastDiffuse || ambiant != _LastAmbient;
|
|
if (colorTouched)
|
|
{
|
|
_LastDiffuse = diffuse;
|
|
_LastAmbient = ambiant;
|
|
|
|
// change landscape
|
|
if (Landscape)
|
|
{
|
|
if(ContinentMngr.cur())
|
|
Landscape->setupStaticLight(diffuse, ambiant, ContinentMngr.cur()->StaticLightingFactor[CurrSeason]);
|
|
else
|
|
Landscape->setupStaticLight(diffuse, ambiant, 1.f);
|
|
_UpdateFreq = getLandscapePatchUpdateFreq();
|
|
if (_Touched)
|
|
{
|
|
Landscape->updateLightingAll();
|
|
Landscape->setUpdateLightingFrequency(0);
|
|
}
|
|
else
|
|
{
|
|
Landscape->setUpdateLightingFrequency(_UpdateFreq);
|
|
}
|
|
}
|
|
}
|
|
_Touched = false;
|
|
|
|
|
|
// Set the Sun color only if not indoor
|
|
if (ContinentMngr.cur()->Indoor)
|
|
{
|
|
Scene->setSunAmbient(CRGBA(150, 150, 150, 255));
|
|
}
|
|
else
|
|
{
|
|
CRGBA color;
|
|
color.add(_LastDiffuse, lightningColor);
|
|
Scene->setLightGroupColor (LightGroupDay, color);
|
|
float nightLevel = _LightLevel*255.f;
|
|
clamp (nightLevel, 0, 255);
|
|
color.set ((uint8)nightLevel, (uint8)nightLevel, (uint8)nightLevel);
|
|
Scene->setLightGroupColor (LightGroupNight, color);
|
|
}
|
|
|
|
if (Landscape)
|
|
{
|
|
if (!isInInterval(_Desc.DawnTransitionStartHour, _Desc.DawnTransitionEndHour + 4.f * updateDuration, hour)
|
|
&& !isInInterval(_Desc.NightTransitionStartHour, _Desc.NightTransitionEndHour + 4.f * updateDuration, hour)
|
|
)
|
|
{
|
|
Landscape->setUpdateLightingFrequency(0);
|
|
}
|
|
}
|
|
|
|
/* if (SoundMngr)
|
|
{
|
|
float ratio;
|
|
if(isInDayInterval(_Desc.DawnTransitionStartHour, _Desc.DawnTransitionEndHour, _Desc.NumHours, hour, ratio))
|
|
{
|
|
// night->day
|
|
SoundMngr->setDayNightRatio (1.0f-ratio);
|
|
}
|
|
else if(isInDayInterval(_Desc.DawnTransitionEndHour, _Desc.NightTransitionStartHour, _Desc.NumHours, hour, ratio))
|
|
{
|
|
// day
|
|
SoundMngr->setDayNightRatio (0.0f);
|
|
}
|
|
else if(isInDayInterval(_Desc.NightTransitionStartHour, _Desc.NightTransitionEndHour, _Desc.NumHours, hour, ratio))
|
|
{
|
|
// day->night
|
|
SoundMngr->setDayNightRatio (ratio);
|
|
}
|
|
else if(isInDayInterval(_Desc.NightTransitionEndHour, _Desc.DawnTransitionStartHour, _Desc.NumHours, hour, ratio))
|
|
{
|
|
// night
|
|
SoundMngr->setDayNightRatio (1.0f);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
// NB : interval can be reversed
|
|
bool CLightCycleManager::isInInterval(float start, float end, float value)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
return start <= end ? value >= start && value < end
|
|
: value >= start || value < end;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
// NB : interval can be reversed
|
|
bool CLightCycleManager::isInDayInterval(float startHour, float endHour, float dayDuration, float hour, float &ratio)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
if (startHour <= endHour)
|
|
{
|
|
if (hour >= startHour && hour < endHour)
|
|
{
|
|
ratio = startHour != endHour ? (hour - startHour) / (endHour - startHour)
|
|
: 0;
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (hour >= startHour || hour < endHour)
|
|
{
|
|
ratio = hour >= startHour ? (hour - startHour) / (dayDuration - startHour + endHour)
|
|
: (hour + dayDuration - startHour) / (dayDuration - startHour + endHour);
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
float CLightCycleManager::getLightLevel(float hour) const
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
float lightValue;
|
|
if (isInDayInterval(_Desc.NightTransitionStartHour, _Desc.NightTransitionEndHour, _Desc.NumHours, hour, lightValue))
|
|
return lightValue;
|
|
if (isInDayInterval(_Desc.DawnTransitionStartHour, _Desc.DawnTransitionEndHour, _Desc.NumHours, hour, lightValue))
|
|
return 1.f - lightValue;
|
|
|
|
// No transition, it is night or day
|
|
if (_Desc.DawnTransitionEndHour <= _Desc.NightTransitionStartHour)
|
|
{
|
|
return hour >= _Desc.DawnTransitionEndHour && hour < _Desc.NightTransitionStartHour ? 0.f : 1.f;
|
|
}
|
|
else
|
|
{
|
|
return hour >= _Desc.DawnTransitionEndHour || hour < _Desc.NightTransitionStartHour ? 0.f : 1.f;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::create()
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
Driver->enableLight(0, true);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::setDirLight(const CDirLightSetup &setup0, const CDirLightSetup &setup1, float level, float intensity,NL3D::UScene &scene)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
CDirLightSetup resultSetup;
|
|
resultSetup.blend(setup0, setup1, level);
|
|
resultSetup.modulate(intensity);
|
|
//
|
|
scene.setSunAmbient (resultSetup.Ambiant);
|
|
scene.setSunDiffuse (resultSetup.Diffuse);
|
|
scene.setSunSpecular (resultSetup.Specular);
|
|
scene.setSunDirection(resultSetup.Direction);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
float CLightCycleManager::getLandscapePatchUpdateFreq() const
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
if(!_ValidDesc)
|
|
return 0.f;
|
|
|
|
if(ContinentMngr.cur() == 0)
|
|
return 0.f;
|
|
|
|
// transition duration in seconds
|
|
float dt = std::min(_Desc.getDawnTransitionLength(), _Desc.getNightTransitionLength()) * _Desc.RealDayLength / _Desc.NumHours;
|
|
uint numStep = std::max(diffColors(ContinentMngr.cur()->LandscapeLightDay.Diffuse, ContinentMngr.cur()->LandscapeLightNight.Diffuse),
|
|
diffColors(ContinentMngr.cur()->LandscapeLightDay.Ambiant, ContinentMngr.cur()->LandscapeLightNight.Ambiant)
|
|
);
|
|
numStep = std::min(numStep, _Desc.MaxNumColorSteps);
|
|
return (float) numStep / dt;
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::touch()
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
_Touched = true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::instanceGroupAdded(NL3D::UInstanceGroup * /* ig */)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
}
|
|
|
|
|
|
//-----------------------------------------------
|
|
// rootLight :
|
|
// Set the light to render the root.
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::setupCanopyLight(float intensity)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
if(!SceneRoot)
|
|
return;
|
|
|
|
if(ContinentMngr.cur())
|
|
{
|
|
switch (_State)
|
|
{
|
|
case DayToNight: // blend form day to night with dusk transition
|
|
setupDayToNightLight(*SceneRoot, ContinentMngr.cur()->RootLightDay, ContinentMngr.cur()->RootLightDusk, ContinentMngr.cur()->RootLightNight, intensity);
|
|
break;
|
|
default: // blend from night to day with no other transition
|
|
setDirLight(ContinentMngr.cur()->RootLightDay, ContinentMngr.cur()->RootLightNight, _LightLevel, intensity, *SceneRoot);
|
|
break;
|
|
}
|
|
}
|
|
}// setupCanopyLight //
|
|
|
|
//-----------------------------------------------
|
|
// mainLight :
|
|
// Set the light to render the main scene
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::setupMainLight(float intensity)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
if(!Scene)
|
|
return;
|
|
if(ContinentMngr.cur())
|
|
{
|
|
switch (_State)
|
|
{
|
|
case DayToNight: // blend form day to night with dusk transition
|
|
setupDayToNightLight(*Scene, ContinentMngr.cur()->EntityLightDay, ContinentMngr.cur()->EntityLightDusk, ContinentMngr.cur()->EntityLightNight, intensity);
|
|
break;
|
|
default: // blend from night to day with no other transition
|
|
setDirLight(ContinentMngr.cur()->EntityLightDay, ContinentMngr.cur()->EntityLightNight, _LightLevel, intensity, *Scene);
|
|
break;
|
|
}
|
|
}
|
|
}// setupMainLight //
|
|
|
|
//-----------------------------------------------
|
|
void CLightCycleManager::setupDayToNightLight(NL3D::UScene &scene, const CDirLightSetup &dayLight, const CDirLightSetup &duskLight, const CDirLightSetup &nightLight, float lightIntensity)
|
|
{
|
|
H_AUTO_USE(RZ_LightCycleManager)
|
|
float blendFactor;
|
|
if (_LightLevel <= _Desc.DuskRatio)
|
|
{
|
|
blendFactor = _Desc.DuskRatio != 0 ? _LightLevel / _Desc.DuskRatio : 0.f;
|
|
setDirLight(dayLight,
|
|
duskLight,
|
|
blendFactor,
|
|
lightIntensity,
|
|
scene
|
|
);
|
|
}
|
|
else
|
|
{
|
|
blendFactor = _Desc.DuskRatio != 1.f ? (_LightLevel - _Desc.DuskRatio) / (1.f - _Desc.DuskRatio) : 0.f;
|
|
setDirLight(duskLight,
|
|
nightLight,
|
|
blendFactor,
|
|
lightIntensity,
|
|
scene
|
|
);
|
|
}
|
|
}
|