forked from townforge/townforge
game: fancy clouds
This commit is contained in:
parent
289d9c134b
commit
b857530615
@ -135,7 +135,7 @@ void PS() {
|
||||
|
||||
vec3 color = vec3(spot*mieCollected + mieFactor*mieCollected + rayleighFactor*rayleighCollected);
|
||||
vec4 daySky = vec4(color, 1.0) + mix(vec4(0.0, 0.0, 0.0, 1.0), vec4(0.1, 0.2, 0.4, 1.0), interp);
|
||||
vec4 nightSky = textureCube(sDiffCubeMap, eyeDir);
|
||||
vec4 nightSky = textureCube(sDiffCubeMap, eyeDir) * .25;
|
||||
|
||||
gl_FragColor = mix(nightSky, daySky, interp);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ target_link_libraries(game_util
|
||||
|
||||
set(game_sources
|
||||
citymesh-urho3d.cc
|
||||
cloud-cover.cc
|
||||
free-camera.cc
|
||||
game-wallet.cc
|
||||
main-urho3d.cc
|
||||
@ -77,6 +78,7 @@ set(game_sources
|
||||
set(game_headers
|
||||
camera-controller.h
|
||||
citymesh-urho3d.h
|
||||
cloud-cover.h
|
||||
game-wallet.h
|
||||
map.h
|
||||
free-camera.h
|
||||
|
234
src/game/cloud-cover.cc
Normal file
234
src/game/cloud-cover.cc
Normal file
@ -0,0 +1,234 @@
|
||||
#include <Urho3D/Resource/ResourceCache.h>
|
||||
#include <Urho3D/Core/Context.h>
|
||||
#include <Urho3D/Graphics/Model.h>
|
||||
#include <Urho3D/Graphics/StaticModel.h>
|
||||
#include <Urho3D/Graphics/Material.h>
|
||||
#include <Urho3D/Graphics/Octree.h>
|
||||
#include <Urho3D/Graphics/OctreeQuery.h>
|
||||
#include <Urho3D/Graphics/Texture2D.h>
|
||||
#include <Urho3D/Resource/Image.h>
|
||||
#include "cloud-cover.h"
|
||||
|
||||
using namespace Urho3D;
|
||||
|
||||
#define DOME_HEIGHT 2000.0f
|
||||
#define DOME_HORIZON 10000.0f
|
||||
#define DOME_RADIUS 250.0f
|
||||
#define HEIGHT_BIAS -20.0f
|
||||
|
||||
static const float HORIZON_ANGLE = acosf((DOME_RADIUS - 1.0f) / DOME_RADIUS);
|
||||
|
||||
static float rnd(float modulus)
|
||||
{
|
||||
uint32_t r = rand() >> 8;
|
||||
r &= 1023;
|
||||
return (r - 512.0f) / 512.0f * modulus;
|
||||
}
|
||||
|
||||
CloudCover::CloudCover():
|
||||
wind(Vector3::ZERO),
|
||||
jitter(Vector3::ZERO),
|
||||
n_clouds(0)
|
||||
{
|
||||
}
|
||||
|
||||
void CloudCover::SetPositionAndRotation(Node *node, float angle, float distance, float dh, const Vector3 &direction, bool rotation_only)
|
||||
{
|
||||
// sphere with radius 10 * distance, and origin -9 * distance
|
||||
// flattened dome (/-----\ shape)
|
||||
const float alpha = distance / DOME_HORIZON * HORIZON_ANGLE;
|
||||
const float height = (DOME_HEIGHT + dh) * cosf(M_PI / 2 * alpha / HORIZON_ANGLE);
|
||||
Vector3 pos(distance * cosf(angle), height + HEIGHT_BIAS, distance * sinf(angle));
|
||||
if (rotation_only)
|
||||
{
|
||||
Vector3 cpos = node->GetPosition();
|
||||
pos.x_ = cpos.x_;
|
||||
pos.z_ = cpos.z_;
|
||||
}
|
||||
node->SetPosition(pos);
|
||||
float t = distance / DOME_HORIZON;
|
||||
Vector3 normal((pos - Vector3(0.0f, DOME_HEIGHT * (1 - DOME_RADIUS), 0.0f)).Normalized());
|
||||
Quaternion q;
|
||||
if (!q.FromLookRotation(-normal, direction))
|
||||
printf("warning: quaternion construction failed\n");
|
||||
Quaternion more;
|
||||
more.FromRotationTo(Vector3::FORWARD, Vector3::DOWN);
|
||||
q = q * more;
|
||||
node->SetRotation(q);
|
||||
}
|
||||
|
||||
void CloudCover::Init(Scene *scene, const Urho3D::Vector3 &cameraPos)
|
||||
{
|
||||
Context *context = scene->GetContext();
|
||||
ResourceCache* cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
cloudsNode = scene->CreateChild("clouds");
|
||||
|
||||
for (unsigned i = 0; i < n_clouds; ++i)
|
||||
AddCloud(true);
|
||||
|
||||
prevCameraPos = cameraPos;
|
||||
}
|
||||
|
||||
void CloudCover::SetWind(const Vector3 &velocity, const Vector3 &jitter)
|
||||
{
|
||||
wind = velocity;
|
||||
this->jitter = jitter;
|
||||
}
|
||||
|
||||
void CloudCover::SetClouds(unsigned n)
|
||||
{
|
||||
n_clouds = n;
|
||||
}
|
||||
|
||||
void CloudCover::AddCloud(bool init)
|
||||
{
|
||||
Context *context = cloudsNode->GetContext();
|
||||
ResourceCache* cache = context->GetSubsystem<ResourceCache>();
|
||||
|
||||
auto plane = cache->GetResource<Model>("Models/Plane.mdl");
|
||||
auto material = cache->GetResource<Material>("Materials/Cloud.xml");
|
||||
|
||||
SharedPtr<Node> node(cloudsNode->CreateChild("cloud"));
|
||||
auto model = node->CreateComponent<StaticModel>();
|
||||
model->SetModel(plane);
|
||||
model->SetMaterial(material);
|
||||
model->SetLightMask(LIGHT_MASK_CLOUDS);
|
||||
model->SetCastShadows(false);
|
||||
|
||||
Vector3 velocity(rnd(jitter.x_), 0.0f, rnd(jitter.z_));
|
||||
float x, y, distance, angle;
|
||||
|
||||
if (init)
|
||||
{
|
||||
x = rnd(DOME_HORIZON);
|
||||
y = rnd(DOME_HORIZON);
|
||||
distance = sqrt(x * x + y * y);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = rnd(80);
|
||||
Quaternion q;
|
||||
q.FromAngleAxis(angle, Vector3::UP);
|
||||
Vector3 target = q * - wind.Normalized() * DOME_HORIZON * .999f;
|
||||
distance = DOME_HORIZON * .999f;
|
||||
x = target.x_;
|
||||
y = target.z_;
|
||||
}
|
||||
|
||||
if (y > 0)
|
||||
angle = Vector3(1.0f, 0.0f, 0.0f).Angle(Vector3(x, 0.0f, y)) * M_PI / 180.0f;
|
||||
else
|
||||
angle = 2 * M_PI - Vector3(1.0f, 0.0f, 0.0f).Angle(Vector3(x, 0.0f, y)) * M_PI / 180.0f;
|
||||
|
||||
SetPositionAndRotation(node, angle, distance, clouds.size() * 100.0f, wind+velocity);
|
||||
node->SetScale(DOME_HEIGHT * (1.4f + rnd(2.6f)));
|
||||
|
||||
clouds.push_back({node, velocity, wind.Normalized(), clouds.size() * 100.0f});
|
||||
}
|
||||
|
||||
void CloudCover::Update(float timeStep, const Urho3D::Vector3 &cameraPos)
|
||||
{
|
||||
const Vector3 dpos = cameraPos - prevCameraPos;
|
||||
size_t i;
|
||||
for (size_t i = 0; i < clouds.size(); ++i)
|
||||
{
|
||||
auto &cloud = clouds[i];
|
||||
Vector3 pos = cloud.node->GetPosition();
|
||||
pos.y_ = 0.0f;
|
||||
pos += (cloud.velocity + wind) * timeStep + dpos;
|
||||
const float angle = Vector3(1.0f, 0.0f, 0.0f).Angle(pos) * M_PI / 180.0f;
|
||||
const float distance = pos.DistanceToPoint(Vector3::ZERO);
|
||||
if (distance > DOME_HORIZON)
|
||||
{
|
||||
cloud.node->Remove();
|
||||
if (i != clouds.size() - 1)
|
||||
cloud = std::move(clouds.back());
|
||||
--i;
|
||||
clouds.pop_back();
|
||||
continue;
|
||||
}
|
||||
cloud.node->SetPosition(pos);
|
||||
SetPositionAndRotation(cloud.node, angle, distance, cloud.dh, cloud.original_direction, true);
|
||||
}
|
||||
if (clouds.size() < n_clouds)
|
||||
AddCloud(false);
|
||||
prevCameraPos = cameraPos;
|
||||
}
|
||||
|
||||
float CloudCover::GetCover(const Urho3D::Vector3 &position, const Urho3D::Vector3 &direction) const
|
||||
{
|
||||
static const float delta = 1.811927f;
|
||||
static const float deltas[5][2] = {
|
||||
{ -delta, 0.0f },
|
||||
{ delta, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, -delta },
|
||||
{ 0.0f, delta },
|
||||
};
|
||||
|
||||
float overall_alpha = 0.0f;
|
||||
for (const auto &delta: deltas)
|
||||
{
|
||||
float alpha = 0.0;
|
||||
Vector3 ray_direction = direction;
|
||||
Quaternion qx, qy;
|
||||
qx.FromAngleAxis(delta[0], Vector3::FORWARD);
|
||||
qy.FromAngleAxis(delta[1], Vector3::RIGHT);
|
||||
ray_direction = qx * qy * ray_direction;
|
||||
Ray ray(position, ray_direction);
|
||||
PODVector<RayQueryResult> results;
|
||||
RayOctreeQuery query(results, ray, RAY_TRIANGLE_UV, 100000, DRAWABLE_GEOMETRY);
|
||||
for (const auto &cloud: clouds)
|
||||
{
|
||||
Drawable *drawable = cloud.node->GetComponent<StaticModel>();
|
||||
if (drawable)
|
||||
drawable->ProcessRayQuery(query, query.result_);
|
||||
}
|
||||
for (const auto &result: results)
|
||||
{
|
||||
const Drawable *d = result.drawable_;
|
||||
if (!d)
|
||||
continue;
|
||||
const StaticModel *model = dynamic_cast<const StaticModel*>(d);
|
||||
if (!model)
|
||||
continue;
|
||||
const Material *material = model->GetMaterial();
|
||||
if (!material)
|
||||
continue;
|
||||
const Texture *texture = material->GetTexture(TU_DIFFUSE);
|
||||
if (!texture)
|
||||
continue;
|
||||
const Texture2D *texture2d = dynamic_cast<const Texture2D*>(texture);
|
||||
if (!texture2d)
|
||||
continue;
|
||||
SharedPtr<Image> image = texture2d->GetImage();
|
||||
if (!image)
|
||||
continue;
|
||||
int x = result.textureUV_.x_ * image->GetWidth();
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
if (x >= image->GetWidth())
|
||||
x = image->GetWidth() - 1;
|
||||
int y = result.textureUV_.y_ * image->GetHeight();
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (y >= image->GetHeight())
|
||||
y = image->GetHeight() - 1;
|
||||
const Color color = image->GetPixel(x, y);
|
||||
alpha = 1.0f - (1.0f - alpha) * (1.0f - color.a_);
|
||||
}
|
||||
overall_alpha += alpha;
|
||||
}
|
||||
|
||||
return overall_alpha / 5;
|
||||
}
|
||||
|
||||
void CloudCover::RemoveAll()
|
||||
{
|
||||
for (auto &cloud: clouds)
|
||||
{
|
||||
cloud.node->Remove();
|
||||
}
|
||||
clouds.clear();
|
||||
}
|
43
src/game/cloud-cover.h
Normal file
43
src/game/cloud-cover.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <Urho3D/Container/Ptr.h>
|
||||
#include <Urho3D/Scene/Scene.h>
|
||||
#include <Urho3D/Scene/Node.h>
|
||||
#include <Urho3D/Graphics/Octree.h>
|
||||
#include <Urho3D/Graphics/OctreeQuery.h>
|
||||
|
||||
#define DRAWABLE_USER_CLOUD 16
|
||||
#define LIGHT_MASK_CLOUDS 0x10000
|
||||
|
||||
class CloudCover
|
||||
{
|
||||
public:
|
||||
CloudCover();
|
||||
void Init(Urho3D::Scene *scene, const Urho3D::Vector3 &cameraPos);
|
||||
void Update(float timeStep, const Urho3D::Vector3 &cameraPos);
|
||||
float GetCover(const Urho3D::Vector3 &position, const Urho3D::Vector3 &direction) const;
|
||||
void SetWind(const Urho3D::Vector3 &velocity, const Urho3D::Vector3 &jitter = Urho3D::Vector3::ZERO);
|
||||
void SetClouds(unsigned n);
|
||||
void RemoveAll();
|
||||
size_t GetNumActiveClouds() const { return clouds.size(); }
|
||||
|
||||
private:
|
||||
struct Cloud
|
||||
{
|
||||
Urho3D::SharedPtr<Urho3D::Node> node;
|
||||
Urho3D::Vector3 velocity;
|
||||
Urho3D::Vector3 original_direction;
|
||||
float dh;
|
||||
};
|
||||
|
||||
void SetPositionAndRotation(Urho3D::Node *node, float angle, float distance, float dh, const Urho3D::Vector3 &direction, bool rotation_only = false);
|
||||
void AddCloud(bool init);
|
||||
|
||||
Urho3D::SharedPtr<Urho3D::Node> cloudsNode;
|
||||
std::vector<Cloud> clouds;
|
||||
Urho3D::Vector3 prevCameraPos;
|
||||
Urho3D::Vector3 wind;
|
||||
Urho3D::Vector3 jitter;
|
||||
unsigned n_clouds;
|
||||
};
|
@ -42,6 +42,7 @@
|
||||
#include "camera-controller.h"
|
||||
#include "free-camera.h"
|
||||
#include "walker-camera.h"
|
||||
#include "cloud-cover.h"
|
||||
|
||||
#define USE_PROC_SKY
|
||||
|
||||
@ -49,8 +50,12 @@ using namespace Urho3D;
|
||||
|
||||
const float TOUCH_SENSITIVITY = 2.0f;
|
||||
|
||||
#define CLOUDS_LIGHT_DISTANCE 12000.0f
|
||||
|
||||
#define CONFIG_SHADOWS "shadows"
|
||||
#define DEFAULT_SHADOWS false
|
||||
#define DEFAULT_SHADOWS true
|
||||
#define CONFIG_CLOUDS "clouds"
|
||||
#define DEFAULT_CLOUDS false
|
||||
#define CONFIG_DYNAMIC_SKY "dynamic-sky"
|
||||
#define DEFAULT_DYNAMIC_SKY true
|
||||
#define CONFIG_TIME_OF_DAY "time-of-day"
|
||||
@ -151,6 +156,7 @@ public:
|
||||
void HandleResearch(StringHash eventType, VariantMap& eventData);
|
||||
void HandleResized(StringHash eventType, VariantMap& eventData);
|
||||
void HandleEnableShadows(StringHash eventType, VariantMap& eventData);
|
||||
void HandleEnableClouds(StringHash eventType, VariantMap& eventData);
|
||||
void HandleEnableDynamicSky(StringHash eventType, VariantMap& eventData);
|
||||
void HandleTimeOfDay(StringHash eventType, VariantMap& eventData);
|
||||
|
||||
@ -195,6 +201,7 @@ private:
|
||||
void RemoveBlock(bool use_selection);
|
||||
Vector<Pair<SharedPtr<Texture>, unsigned int>> LoadImage(const String &filename);
|
||||
void EnableShadows(bool enable);
|
||||
void EnableClouds(bool enable);
|
||||
void EnableDynamicSky(bool enable);
|
||||
void SetTimeOfDay(float t);
|
||||
void UpdateSky();
|
||||
@ -208,6 +215,7 @@ private:
|
||||
|
||||
SharedPtr<Scene> scene_;
|
||||
SharedPtr<Node> cameraNode_;
|
||||
SharedPtr<Node> cloudsLightNode_;
|
||||
SharedPtr<CameraController> camera_;
|
||||
SharedPtr<Viewport> viewport;
|
||||
|
||||
@ -250,6 +258,7 @@ private:
|
||||
UIConsole console;
|
||||
Urho3D::SharedPtr<Node> mainLightNode;
|
||||
Urho3D::SharedPtr<Node> procskyNode;
|
||||
CloudCover clouds;
|
||||
};
|
||||
|
||||
CryptoCityUrho3D::CryptoCityUrho3D(Context *ctx):
|
||||
@ -614,6 +623,7 @@ void CryptoCityUrho3D::SetupUI()
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_CHAT, URHO3D_HANDLER(CryptoCityUrho3D, HandleChat));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_RESEARCH, URHO3D_HANDLER(CryptoCityUrho3D, HandleResearch));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_ENABLE_SHADOWS, URHO3D_HANDLER(CryptoCityUrho3D, HandleEnableShadows));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_ENABLE_CLOUDS, URHO3D_HANDLER(CryptoCityUrho3D, HandleEnableClouds));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_ENABLE_DYNAMIC_SKY, URHO3D_HANDLER(CryptoCityUrho3D, HandleEnableDynamicSky));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_TIME_OF_DAY, URHO3D_HANDLER(CryptoCityUrho3D, HandleTimeOfDay));
|
||||
SubscribeToEvent(&gameState, E_CRYPTOCITY_REQUEST_PLAYER_DATA, URHO3D_HANDLER(CryptoCityUrho3D, HandleRequestPlayerData));
|
||||
@ -813,6 +823,28 @@ void CryptoCityUrho3D::EnableShadows(bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::EnableClouds(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
if (clouds.GetNumActiveClouds() == 0)
|
||||
{
|
||||
clouds.SetWind(Vector3(10, 0, 4), Vector3(6, 0, 3));
|
||||
clouds.SetClouds(40);
|
||||
clouds.Init(scene_, cameraNode_->GetPosition());
|
||||
}
|
||||
if (cloudsLightNode_)
|
||||
scene_->AddChild(cloudsLightNode_);
|
||||
}
|
||||
else
|
||||
{
|
||||
clouds.SetClouds(0);
|
||||
clouds.RemoveAll();
|
||||
if (cloudsLightNode_)
|
||||
scene_->RemoveChild(cloudsLightNode_);
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::EnableDynamicSky(bool enable)
|
||||
{
|
||||
auto* cache = GetSubsystem<ResourceCache>();
|
||||
@ -879,15 +911,36 @@ void CryptoCityUrho3D::CreateScene()
|
||||
// Create a Zone for ambient light & fog control
|
||||
Node* zoneNode = scene_->CreateChild("Zone");
|
||||
auto* zone = zoneNode->CreateComponent<Zone>();
|
||||
zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f));
|
||||
zone->SetBoundingBox(BoundingBox(Vector3(-2000.0f, -1.0f, -2000.0f), Vector3(2000.0f, 999.0f, 2000.0f)));
|
||||
zone->SetAmbientColor(Color(0.7f, 0.7f, 0.7f));
|
||||
zone->SetFogColor(Color(0.2f, 0.2f, 0.2f));
|
||||
zone->SetFogStart(2000.0f);
|
||||
zone->SetFogEnd(2500.0f);
|
||||
zone->SetFogStart(1750.0f);
|
||||
zone->SetFogEnd(2000.0f);
|
||||
zone->SetPriority(100);
|
||||
|
||||
// Create a Zone for clouds only
|
||||
Node* cloudsZoneNode = scene_->CreateChild("CloudsZone");
|
||||
auto* cloudsZone = cloudsZoneNode->CreateComponent<Zone>();
|
||||
cloudsZone->SetBoundingBox(BoundingBox(Vector3(-200000.0f, -1000.0f, -200000.0f), Vector3(200000.0f, 2000000.0f, 200000.0f)));
|
||||
cloudsZone->SetLightMask(0xffff | LIGHT_MASK_CLOUDS);
|
||||
cloudsZone->SetFogStart(2000000.0f);
|
||||
cloudsZone->SetFogEnd(2500000.0f);
|
||||
cloudsZone->SetPriority(20);
|
||||
|
||||
// Create a node for the directional light, UpdateSky will take care of the rest
|
||||
mainLightNode = scene_->CreateChild("DirectionalLight");
|
||||
|
||||
// A light just for clouds
|
||||
cloudsLightNode_ = scene_->CreateChild("CloudsLight");
|
||||
Light *cloudsLight = cloudsLightNode_->CreateComponent<Light>();
|
||||
cloudsLight->SetLightMask(LIGHT_MASK_CLOUDS);
|
||||
cloudsLight->SetLightType(LIGHT_POINT);
|
||||
cloudsLight->SetColor(Color(1.0f, .0f, .0f, 1.0f));
|
||||
cloudsLight->SetSpecularIntensity(0.0f);
|
||||
cloudsLight->SetRange(CLOUDS_LIGHT_DISTANCE * 0.95f);
|
||||
cloudsLight->SetCastShadows(false);
|
||||
cloudsLight->SetPerVertex(true);
|
||||
|
||||
#define FIRST_CITY_X ((uint32_t)466920160)
|
||||
#define FIRST_CITY_Y ((uint32_t)2502907875)
|
||||
const uint32_t ox = FIRST_CITY_X, oy = FIRST_CITY_Y;
|
||||
@ -942,6 +995,7 @@ printf("%d plots, origin %u %u\n", plots, ox, oy);
|
||||
camera_ = new FreeCamera(cameraNode_);
|
||||
|
||||
EnableShadows(GetConfigValue(CONFIG_SHADOWS, DEFAULT_SHADOWS));
|
||||
EnableClouds(GetConfigValue(CONFIG_CLOUDS, DEFAULT_CLOUDS));
|
||||
EnableDynamicSky(GetConfigValue(CONFIG_DYNAMIC_SKY, DEFAULT_DYNAMIC_SKY));
|
||||
SetTimeOfDay(GetConfigValue(CONFIG_TIME_OF_DAY, DEFAULT_TIME_OF_DAY));
|
||||
}
|
||||
@ -957,7 +1011,7 @@ void CryptoCityUrho3D::SetupViewport()
|
||||
cameraNode_->SetPosition(Vector3(0.0f, 10.0f, -100.0f));
|
||||
cameraNode_->LookAt(Vector3(0.0f, cameraNode_->GetPosition().y_, 0.0f));
|
||||
auto* camera = cameraNode_->CreateComponent<Camera>();
|
||||
camera->SetFarClip(2600.0f);
|
||||
camera->SetFarClip(260000.0f);
|
||||
}
|
||||
|
||||
// Set up a viewport to the Renderer subsystem so that the 3D scene can be seen
|
||||
@ -1050,6 +1104,7 @@ void CryptoCityUrho3D::UpdateSky()
|
||||
{
|
||||
const bool realtime_sky = GetConfigValue(CONFIG_TIME_OF_DAY, DEFAULT_TIME_OF_DAY) == -1.0f;
|
||||
time_t now = time(NULL);
|
||||
bool disable_procsky = true;
|
||||
|
||||
if (realtime_sky)
|
||||
{
|
||||
@ -1063,8 +1118,10 @@ void CryptoCityUrho3D::UpdateSky()
|
||||
|
||||
float sin_timeOfDay = sin(timeOfDay);
|
||||
float interp = fmax(sin_timeOfDay, 0.0f);
|
||||
float evening = fmax(cos(M_PI * .65f + timeOfDay), 0);
|
||||
evening = std::min(evening, (interp - 0.0f) * 12.0f);
|
||||
float evening = fmax(cos(M_PI * .55f + timeOfDay), 0);
|
||||
float clouds_reddening = 4 * fmax((cos(M_PI * 1.0f + timeOfDay) - .75f), 0.0f);
|
||||
clouds_reddening *= clouds_reddening * clouds_reddening * clouds_reddening;
|
||||
clouds_reddening *= clouds_reddening * clouds_reddening * clouds_reddening;
|
||||
|
||||
Color DARK_SUN(0.0, 0.0, 0.0);
|
||||
//Color LIGHT_SUN(1, .9, .9);
|
||||
@ -1075,15 +1132,20 @@ void CryptoCityUrho3D::UpdateSky()
|
||||
Color LIGHT_AMBIENT(.75, .6, .675, 1);
|
||||
//Color LIGHT_AMBIENT(1, .8, .9, 5);
|
||||
Color EVENING_AMBIENT_INFLUENCE(.9, .2, .3, 1);
|
||||
Color EVENING_CLOUDS_AMBIENT(1.1, .0, .0, 1);
|
||||
|
||||
Node *zoneNode = scene_->GetChild("Zone");
|
||||
Zone* zone = zoneNode->GetComponent<Zone>();
|
||||
Node *cloudsZoneNode = scene_->GetChild("CloudsZone");
|
||||
Zone* cloudsZone = cloudsZoneNode->GetComponent<Zone>();
|
||||
Light* sun = mainLightNode->GetComponent<Light>();
|
||||
Light* cameraLight = cameraNode_->GetComponent<Light>();
|
||||
Light* cloudsLight = cloudsLightNode_->GetComponent<Light>();
|
||||
|
||||
Color ambient = DARK_AMBIENT.Lerp(LIGHT_AMBIENT, interp);
|
||||
zone->SetAmbientColor(ambient);
|
||||
zone->SetFogColor(DARK_FOG.Lerp(LIGHT_FOG, interp));
|
||||
Color cloudsColor = EVENING_CLOUDS_AMBIENT * clouds_reddening;
|
||||
Color sunColor = DARK_SUN.Lerp(LIGHT_SUN, interp).Lerp(EVENING_AMBIENT_INFLUENCE, evening);
|
||||
|
||||
if (interp == 0.0f)
|
||||
@ -1104,9 +1166,13 @@ void CryptoCityUrho3D::UpdateSky()
|
||||
}
|
||||
}
|
||||
|
||||
const float cloud_cover = clouds.GetCover(cameraNode_->GetPosition(), mainLightNode->GetRotation() * - Vector3::FORWARD);
|
||||
|
||||
if (sun)
|
||||
{
|
||||
sun->SetColor(sunColor);
|
||||
sun->SetBrightness(1.0f - cloud_cover / 2);
|
||||
sun->SetShadowIntensity(0.35f + cloud_cover * (1.0f - 0.35f));
|
||||
sun->SetShadowCascade(CascadeParameters(25.0f, 100.0f, 400.0f, 0.0f, 0.8f));
|
||||
}
|
||||
|
||||
@ -1138,7 +1204,7 @@ void CryptoCityUrho3D::UpdateSky()
|
||||
Quaternion newRot((timeOfDay / M_PI) * 180, Vector3(1, 0.3f, 0));
|
||||
mainLightNode->SetRotation(-newRot); //inverted since we are looking at direction from sun
|
||||
|
||||
if (procskyNode)
|
||||
if (procskyNode && needSkyUpdate_)
|
||||
{
|
||||
auto procsky = procskyNode->GetComponent<ProcSky>();
|
||||
if (procsky)
|
||||
@ -1146,8 +1212,21 @@ void CryptoCityUrho3D::UpdateSky()
|
||||
viewport->GetRenderPath()->SetEnabled("ProcSky", true);
|
||||
procsky->SetTimeOfDay(timeOfDay);
|
||||
procsky->Update();
|
||||
needSkyUpdate_ = false;
|
||||
disable_procsky = false;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 cloudsLightPosition = newRot * - Vector3::FORWARD * CLOUDS_LIGHT_DISTANCE;
|
||||
cloudsLightPosition.y_ -= 1000;
|
||||
cloudsLightNode_->SetPosition(cloudsLightPosition);
|
||||
cloudsLight->SetColor(cloudsColor);
|
||||
float cloudsInterp = std::max(0.0f, std::min(1.0f, (sin_timeOfDay + .1f) * 6));
|
||||
Color cloudsAmbient = Color::BLACK.Lerp(Color::WHITE, cloudsInterp);
|
||||
cloudsZone->SetAmbientColor(cloudsAmbient);
|
||||
|
||||
if (disable_procsky)
|
||||
viewport->GetRenderPath()->SetEnabled("ProcSky", false);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
|
||||
@ -1164,13 +1243,7 @@ void CryptoCityUrho3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
|
||||
cityMesh->Update(timeStep, mark_new_block);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
|
||||
if (needSkyUpdate_)
|
||||
{
|
||||
UpdateSky();
|
||||
needSkyUpdate_ = false;
|
||||
}
|
||||
else
|
||||
viewport->GetRenderPath()->SetEnabled("ProcSky", false);
|
||||
UpdateSky();
|
||||
|
||||
auto* input = GetSubsystem<Input>();
|
||||
|
||||
@ -1201,6 +1274,8 @@ void CryptoCityUrho3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
|
||||
// Move the camera, scale movement with time step
|
||||
MoveCamera(timeStep);
|
||||
|
||||
clouds.Update(timeStep, cameraNode_->GetPosition());
|
||||
|
||||
ui->Update(mouse_x, mouse_y, selection.x0, selection.y0, selection.x1, selection.y1, cityMesh->getDisplayMode() == DisplayModeShowFlags, flagUnderConstruction != boost::none, console.GetNumUnreadLines(), wallet);
|
||||
mark_new_block = false;
|
||||
|
||||
@ -2239,6 +2314,14 @@ void CryptoCityUrho3D::HandleEnableShadows(StringHash eventType, VariantMap& eve
|
||||
eventData[EnableShadows::P_ENABLE] = GetConfigValue(CONFIG_SHADOWS, DEFAULT_SHADOWS);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleEnableClouds(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
if (eventData.Contains(EnableClouds::P_ENABLE))
|
||||
EnableClouds(SetConfigValue(CONFIG_CLOUDS, eventData[EnableClouds::P_ENABLE].GetBool()));
|
||||
else
|
||||
eventData[EnableClouds::P_ENABLE] = GetConfigValue(CONFIG_CLOUDS, DEFAULT_CLOUDS);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleEnableDynamicSky(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
if (eventData.Contains(EnableDynamicSky::P_ENABLE))
|
||||
|
@ -100,6 +100,18 @@ UIOptionsDialog::UIOptionsDialog(Context *ctx):
|
||||
row->AddChild(shadowsWidget);
|
||||
shadowsWidget->SetStyleAuto(style);
|
||||
|
||||
// clouds
|
||||
row = new UIElement(context_);
|
||||
row->SetStyleAuto(style);
|
||||
row->SetLayout(LM_HORIZONTAL, 6, IntRect(0, 0, 0, 0));
|
||||
window->AddChild(row);
|
||||
|
||||
AddText(row, "Clouds");
|
||||
cloudsWidget = new CheckBox(context_);
|
||||
cloudsWidget->SetName("CloudsWidget");
|
||||
row->AddChild(cloudsWidget);
|
||||
cloudsWidget->SetStyleAuto(style);
|
||||
|
||||
// dynamic sky
|
||||
row = new UIElement(context_);
|
||||
row->SetStyleAuto(style);
|
||||
@ -166,6 +178,7 @@ UIOptionsDialog::UIOptionsDialog(Context *ctx):
|
||||
SubscribeToEvent(buttonCancel, E_RELEASED, URHO3D_HANDLER(UIOptionsDialog, HandleCancel));
|
||||
SubscribeToEvent(buttonClose, E_RELEASED, URHO3D_HANDLER(UIOptionsDialog, HandleCancel));
|
||||
SubscribeToEvent(shadowsWidget, E_TOGGLED, URHO3D_HANDLER(UIOptionsDialog, HandleShadowsChanged));
|
||||
SubscribeToEvent(cloudsWidget, E_TOGGLED, URHO3D_HANDLER(UIOptionsDialog, HandleCloudsChanged));
|
||||
SubscribeToEvent(dynamicSkyWidget, E_TOGGLED, URHO3D_HANDLER(UIOptionsDialog, HandleDynamicSkyChanged));
|
||||
SubscribeToEvent(timeOfDayWidget, E_TEXTCHANGED, URHO3D_HANDLER(UIOptionsDialog, HandleTimeOfDayChanged));
|
||||
|
||||
@ -189,6 +202,10 @@ void UIOptionsDialog::Configure()
|
||||
SendEvent(E_OPTIONS_ENABLE_SHADOWS, newEventData);
|
||||
shadowsWidget->SetChecked(newEventData[OptionsEnableShadows::P_ENABLE].GetBool());
|
||||
|
||||
newEventData = {};
|
||||
SendEvent(E_OPTIONS_ENABLE_CLOUDS, newEventData);
|
||||
cloudsWidget->SetChecked(newEventData[OptionsEnableClouds::P_ENABLE].GetBool());
|
||||
|
||||
newEventData = {};
|
||||
SendEvent(E_OPTIONS_ENABLE_DYNAMIC_SKY, newEventData);
|
||||
dynamicSkyWidget->SetChecked(newEventData[OptionsEnableDynamicSky::P_ENABLE].GetBool());
|
||||
@ -205,6 +222,13 @@ void UIOptionsDialog::HandleShadowsChanged(StringHash eventType, VariantMap& eve
|
||||
SendEvent(E_OPTIONS_ENABLE_SHADOWS, newEventData);
|
||||
}
|
||||
|
||||
void UIOptionsDialog::HandleCloudsChanged(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap newEventData;
|
||||
newEventData[OptionsEnableClouds::P_ENABLE] = cloudsWidget->IsChecked();
|
||||
SendEvent(E_OPTIONS_ENABLE_CLOUDS, newEventData);
|
||||
}
|
||||
|
||||
void UIOptionsDialog::HandleDynamicSkyChanged(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap newEventData;
|
||||
|
@ -21,6 +21,7 @@ URHO3D_EVENT(E_OPTIONS_OKAYED, OptionsOkayed) { }
|
||||
URHO3D_EVENT(E_OPTIONS_CANCELLED, OptionsCancelled) {}
|
||||
|
||||
URHO3D_EVENT(E_OPTIONS_ENABLE_SHADOWS, OptionsEnableShadows) { URHO3D_PARAM(P_ENABLE, Enable); }
|
||||
URHO3D_EVENT(E_OPTIONS_ENABLE_CLOUDS, OptionsEnableClouds) { URHO3D_PARAM(P_ENABLE, Enable); }
|
||||
URHO3D_EVENT(E_OPTIONS_ENABLE_DYNAMIC_SKY, OptionsEnableDynamicSky) { URHO3D_PARAM(P_ENABLE, Enable); }
|
||||
URHO3D_EVENT(E_OPTIONS_TIME_OF_DAY, OptionsTimeOfDay) { URHO3D_PARAM(P_TIME_OF_DAY, TimeOfDay); }
|
||||
|
||||
@ -43,12 +44,14 @@ private:
|
||||
void HandleCancel(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
|
||||
void HandleShadowsChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleCloudsChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleDynamicSkyChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleTimeOfDayChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
|
||||
private:
|
||||
Urho3D::SharedPtr<Urho3D::Window> window;
|
||||
Urho3D::SharedPtr<Urho3D::CheckBox> shadowsWidget;
|
||||
Urho3D::SharedPtr<Urho3D::CheckBox> cloudsWidget;
|
||||
Urho3D::SharedPtr<Urho3D::CheckBox> dynamicSkyWidget;
|
||||
Urho3D::SharedPtr<Urho3D::LineEdit> timeOfDayWidget;
|
||||
};
|
||||
|
@ -1125,6 +1125,9 @@ void UIUrho3D::HandleOptions(StringHash eventType, VariantMap& eventData)
|
||||
SubscribeToEvent(optionsDialog, E_OPTIONS_ENABLE_SHADOWS, [this](StringHash eventType, VariantMap& eventData) {
|
||||
SendEvent(E_CRYPTOCITY_ENABLE_SHADOWS, eventData);
|
||||
});
|
||||
SubscribeToEvent(optionsDialog, E_OPTIONS_ENABLE_CLOUDS, [this](StringHash eventType, VariantMap& eventData) {
|
||||
SendEvent(E_CRYPTOCITY_ENABLE_CLOUDS, eventData);
|
||||
});
|
||||
SubscribeToEvent(optionsDialog, E_OPTIONS_ENABLE_DYNAMIC_SKY, [this](StringHash eventType, VariantMap& eventData) {
|
||||
SendEvent(E_CRYPTOCITY_ENABLE_DYNAMIC_SKY, eventData);
|
||||
});
|
||||
|
@ -61,6 +61,7 @@ URHO3D_EVENT(E_CRYPTOCITY_DEMOLISH_FLAG, DemolishFlag) { }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_CHAT, Chat) { }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_RESEARCH, Research) { URHO3D_PARAM(P_DISCOVERY, Discovery); URHO3D_PARAM(P_AMOUNT, Amount); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_ENABLE_SHADOWS, EnableShadows) { URHO3D_PARAM(P_ENABLE, Enable); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_ENABLE_CLOUDS, EnableClouds) { URHO3D_PARAM(P_ENABLE, Enable); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_ENABLE_DYNAMIC_SKY, EnableDynamicSky) { URHO3D_PARAM(P_ENABLE, Enable); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_TIME_OF_DAY, TimeOfDay) { URHO3D_PARAM(P_TIME_OF_DAY, TimeOfDay); }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user