From cf8742c4fe4e378b6c7d219ae46f58fa5105c4bf Mon Sep 17 00:00:00 2001 From: tovjemam Date: Tue, 19 May 2026 19:11:53 +0200 Subject: [PATCH] World environment --- CMakeLists.txt | 2 + src/assets/model.cpp | 9 ++ src/game/openworld.cpp | 10 ++ src/game/openworld.hpp | 5 + src/game/player.cpp | 14 ++ src/game/player.hpp | 2 + src/game/world.hpp | 3 + src/gameview/client_session.cpp | 6 +- src/gameview/draw_args.hpp | 5 +- src/gameview/worldenv.cpp | 233 ++++++++++++++++++++++++++++++++ src/gameview/worldenv.hpp | 56 ++++++++ src/gameview/worldview.cpp | 57 +++++++- src/gameview/worldview.hpp | 12 +- src/gfx/renderer.cpp | 21 ++- src/gfx/renderer.hpp | 6 +- src/gfx/shader.cpp | 4 + src/gfx/shader.hpp | 4 + src/gfx/shader_defs.hpp | 3 +- src/gfx/shader_sources.cpp | 71 ++++++---- src/gfx/surface.hpp | 2 + src/net/defs.hpp | 7 +- src/utils/version.hpp | 2 +- 22 files changed, 495 insertions(+), 39 deletions(-) create mode 100644 src/gameview/worldenv.cpp create mode 100644 src/gameview/worldenv.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ba95e1..fd76b61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,8 @@ set(CLIENT_ONLY_SOURCES "src/gameview/skinning_ubo.cpp" "src/gameview/vehicleview.hpp" "src/gameview/vehicleview.cpp" + "src/gameview/worldenv.hpp" + "src/gameview/worldenv.cpp" "src/gameview/worldview.hpp" "src/gameview/worldview.cpp" "src/gfx/buffer_object.cpp" diff --git a/src/assets/model.cpp b/src/assets/model.cpp index c7af6af..40c74be 100644 --- a/src/assets/model.cpp +++ b/src/assets/model.cpp @@ -107,6 +107,11 @@ std::shared_ptr assets::Model::LoadFromFile(const std::stri { CLIENT_ONLY(sflags |= gfx::SF_OBJECT_COLOR;) } + else if (flag == "+ocolor_mult") + { + CLIENT_ONLY(sflags |= gfx::SF_OBJECT_COLOR;) + CLIENT_ONLY(sflags |= gfx::SF_OBJECT_COLOR_MULT;) + } else if (flag == "+blend") { std::string blend_str; @@ -118,6 +123,10 @@ std::shared_ptr assets::Model::LoadFromFile(const std::stri sflags |= gfx::SF_BLEND_ADDITIVE; ) } + else if (flag == "+unlit") + { + CLIENT_ONLY(sflags |= gfx::SF_UNLIT;) + } } CLIENT_ONLY( diff --git a/src/game/openworld.cpp b/src/game/openworld.cpp index 603ec21..1665aa3 100644 --- a/src/game/openworld.cpp +++ b/src/game/openworld.cpp @@ -78,6 +78,16 @@ game::OpenWorld::OpenWorld() : EnterableWorld("openworld") }); } + daytime_offset_ = static_cast(rand() % 24); + +} + +void game::OpenWorld::Update(int64_t delta_time) +{ + Super::Update(delta_time); + + const float timespeed = 0.05f; + SetDayTime(static_cast(GetTime()) * 0.001f * timespeed + daytime_offset_); } game::DrivableVehicle& game::OpenWorld::SpawnRandomVehicle() diff --git a/src/game/openworld.hpp b/src/game/openworld.hpp index 7d33316..a4ae1a1 100644 --- a/src/game/openworld.hpp +++ b/src/game/openworld.hpp @@ -9,14 +9,19 @@ namespace game class OpenWorld : public EnterableWorld { public: + using Super = EnterableWorld; + OpenWorld(); + virtual void Update(int64_t delta_time) override; + private: game::DrivableVehicle& SpawnRandomVehicle(); void SpawnBot(); private: std::vector npcs_; + float daytime_offset_ = 0.0f; }; } \ No newline at end of file diff --git a/src/game/player.cpp b/src/game/player.cpp index f5c0743..1be714b 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -116,6 +116,7 @@ void game::Player::SyncWorld() if (world_) { SendWorldUpdateMsg(); + SendEnv(); SyncEntities(); } } @@ -125,6 +126,8 @@ void game::Player::SendWorldMsg() MSGDEBUG(std::cout << "seding CHWORLD" << std::endl;) auto msg = BeginMsg(net::MSG_CHWORLD); world_->SendInitData(*this, msg); + + last_env_time_ = 0; // reset after world changed } void game::Player::SendWorldUpdateMsg() @@ -136,6 +139,17 @@ void game::Player::SendWorldUpdateMsg() msg.Write(world_->GetMsg()); } +void game::Player::SendEnv() +{ + if (!world_ || last_env_time_ + 1000 > world_->GetTime()) + return; + + last_env_time_ = world_->GetTime(); + + auto msg = BeginMsg(net::MSG_ENV); + msg.Write(world_->GetDayTime()); +} + void game::Player::SyncEntities() { // update cull pos diff --git a/src/game/player.hpp b/src/game/player.hpp index 0bc0689..29925f6 100644 --- a/src/game/player.hpp +++ b/src/game/player.hpp @@ -53,6 +53,7 @@ private: void SyncWorld(); void SendWorldMsg(); void SendWorldUpdateMsg(); + void SendEnv(); // entities sync void SyncEntities(); @@ -78,6 +79,7 @@ private: World* world_ = nullptr; World* known_world_ = nullptr; std::set known_ents_; + int64_t last_env_time_ = 0; PlayerInputFlags in_ = 0; float view_yaw_ = 0.0f, view_pitch_ = 0.0f; diff --git a/src/game/world.hpp b/src/game/world.hpp index 60617c0..7b5de68 100644 --- a/src/game/world.hpp +++ b/src/game/world.hpp @@ -49,6 +49,8 @@ public: const std::string& GetMapName() const { return map_.GetName(); } const std::map>& GetEntities() const { return ents_; } const int64_t& GetTime() const { return time_ms_; } + float GetDayTime() const { return daytime_; } + void SetDayTime(float daytime) { daytime_ = glm::mod(daytime, 24.0f); } virtual ~World() = default; @@ -68,6 +70,7 @@ private: net::EntNum last_entnum_ = 0; int64_t time_ms_ = 0; + float daytime_ = 12.0f; }; } // namespace game \ No newline at end of file diff --git a/src/gameview/client_session.cpp b/src/gameview/client_session.cpp index 1bfc380..dc94ecb 100644 --- a/src/gameview/client_session.cpp +++ b/src/gameview/client_session.cpp @@ -228,7 +228,9 @@ void game::view::ClientSession::DrawWorld(gfx::DrawList& dlist, gfx::DrawListPar // 0.0f, 1.0f)); float aspect = static_cast(params.screen_width) / static_cast(params.screen_height); - glm::mat4 proj = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 3000.0f); + const float farplane = 3000.0f; + + glm::mat4 proj = glm::perspective(glm::radians(45.0f), aspect, 0.1f, farplane); glm::vec3 eye; glm::mat4 view; GetViewInfo(eye, view); @@ -239,7 +241,7 @@ void game::view::ClientSession::DrawWorld(gfx::DrawList& dlist, gfx::DrawListPar // glm::mat4 fake_view_proj = glm::perspective(glm::radians(30.0f), aspect, 0.1f, 3000.0f) * view; game::view::DrawArgs draw_args(dlist, params.env, gui, params.view_proj, eye, - glm::ivec2(params.screen_width, params.screen_height), 500.0f); + glm::ivec2(params.screen_width, params.screen_height), farplane, 500.0f); world_->Draw(draw_args); glm::mat4 camera_world = glm::inverse(view); diff --git a/src/gameview/draw_args.hpp b/src/gameview/draw_args.hpp index 7374242..1efb900 100644 --- a/src/gameview/draw_args.hpp +++ b/src/gameview/draw_args.hpp @@ -18,12 +18,13 @@ struct DrawArgs const glm::vec3 eye; const gfx::Frustum frustum; const glm::ivec2 screen_size; + const float farplane; const float render_distance; DrawArgs(gfx::DrawList& dlist, gfx::DrawListEnvironmentParams& env, gui::Context& gui, const glm::mat4& view_proj, - const glm::vec3& eye, const glm::ivec2& screen_size, float render_distance) + const glm::vec3& eye, const glm::ivec2& screen_size, float farplane, float render_distance) : dlist(dlist), env(env), gui(gui), view_proj(view_proj), eye(eye), frustum(view_proj), - screen_size(screen_size), render_distance(render_distance) + screen_size(screen_size), farplane(farplane), render_distance(render_distance) { } }; diff --git a/src/gameview/worldenv.cpp b/src/gameview/worldenv.cpp new file mode 100644 index 0000000..cc33963 --- /dev/null +++ b/src/gameview/worldenv.cpp @@ -0,0 +1,233 @@ +#include "worldenv.hpp" + +#include "assets/cache.hpp" + +game::view::WorldEnv::WorldEnv() +{ + sunmodel_ = assets::CacheManager::GetModel("data/env_sun.mdl"); + moonmodel_ = assets::CacheManager::GetModel("data/env_moon.mdl"); + halfspheremodel_ = assets::CacheManager::GetModel("data/env_halfsphere.mdl"); +} + +static const glm::vec4 color1(1.0f); + +static const game::view::WorldEnvKeyframe env_kfs[] = { + game::view::WorldEnvKeyframe{ + 0.0f, // time + glm::vec3(0.1f, 0.15f, 0.3f), // clear color + glm::vec3(0.4f, 0.4f, 0.4f), // ambient color + glm::vec3(0.5f, 0.8f, 1.0f) * 0.4f, // sun color + -1.0f, // sun light source + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // sun disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.1f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 5.0f, // time + glm::vec3(0.15f, 0.2, 0.3f), // clear color + glm::vec3(0.5f, 0.5f, 0.5f) * 1.0f, // ambient color + glm::vec3(0.5f, 0.8f, 1.0f) * 0.4f, // sun color + -1.0f, // sun light source + glm::vec4(1.0f, 0.9f, 0.8f, 1.0f), // sun disc color + glm::vec4(1.0f, 0.8f, 0.6f, 0.2f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 6.0f, // time + glm::vec3(0.65f, 0.8f, 1.0f) * 0.9f, // clear color + glm::vec3(0.5f, 0.5f, 0.5f) * 1.1f, // ambient color + glm::vec3(1.0f, 0.95f, 0.7f) * 0.8f, // sun color + 1.0f, // sun light source + glm::vec4(1.0f, 0.9f, 0.8f, 1.0f), // sun disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.4f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 12.0f, // time + glm::vec3(0.6f, 0.8f, 1.0f), // clear color + glm::vec3(0.5f, 0.5f, 0.5f) * 0.9f, // ambient color + glm::vec3(1.0f, 0.95f, 0.7f) * 0.9f, // sun color + 1.0f, // sun light source + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), // sun disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.7f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 17.0f, // time + glm::vec3(0.5f, 0.7f, 1.0f) * 0.9f, // clear color + glm::vec3(0.5f, 0.5f, 0.5f) * 1.1f, // ambient color + glm::vec3(1.0f, 0.95f, 0.7f) * 0.9f, // sun color + 1.0f, // sun light source + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), // sun disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.5f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 17.5f, // time + glm::vec3(0.5f, 0.7f, 1.0f) * 0.8f, // clear color + glm::vec3(0.8f, 0.6f, 0.5f) * 0.8f, // ambient color + glm::vec3(1.0f, 0.8f, 0.6f) * 0.8f, // sun color + 1.0f, // sun light source + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), // sun disc color + glm::vec4(1.0f, 0.7f, 0.5f, 1.0f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 0.2f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.1f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 18.0f, // time + glm::vec3(0.5f, 0.7f, 1.0f) * 0.7f, // clear color + glm::vec3(0.8f, 0.6f, 0.5f) * 0.8f, // ambient color + glm::vec3(1.0f, 0.8f, 0.6f) * 0.8f, // sun color + 0.0f, // sun light source + glm::vec4(1.0f, 0.8f, 0.7f, 1.0f), // sun disc color + glm::vec4(1.0f, 0.7f, 0.5f, 1.0f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 0.2f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.1f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 19.0f, // time + glm::vec3(0.1f, 0.15f, 0.3f), // clear color + glm::vec3(0.4f, 0.4f, 0.4f), // ambient color + glm::vec3(0.5f, 0.8f, 1.0f) * 0.4f, // sun color + -1.0f, // sun light source + glm::vec4(1.0f, 0.5f, 0.3f, 1.0f), // sun disc color + glm::vec4(1.0f, 0.5f, 0.2f, 0.8f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.1f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + game::view::WorldEnvKeyframe{ + 20.0f, // time + glm::vec3(0.1f, 0.15f, 0.3f), // clear color + glm::vec3(0.4f, 0.4f, 0.4f), // ambient color + glm::vec3(0.5f, 0.8f, 1.0f) * 0.4f, // sun color + -1.0f, // sun light source + glm::vec4(1.0f, 1.0f, 1.0f, 0.0f), // sun disc color + glm::vec4(1.0f, 0.5f, 0.2f, 0.0f), // sun halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), // moon disc color + glm::vec4(1.0f, 1.0f, 1.0f, 0.1f), // moon halfsphere color + glm::vec4(1.0f, 1.0f, 1.0f, 10000.0f), // fog + }, + + +}; + +void game::view::WorldEnv::Draw(const DrawArgs& args) +{ + const WorldEnvKeyframe *kf1, *kf2; + + if (daytime_ < 0.0f) + daytime_ = 0.0f; + + const size_t num_kfs = sizeof(env_kfs) / sizeof(WorldEnvKeyframe); + for (size_t i = 0; i < num_kfs; ++i) + { + if (daytime_ >= env_kfs[i].daytime) + { + kf1 = &env_kfs[i]; + kf2 = &env_kfs[(i + 1) % num_kfs]; + } + } + + float t2 = kf2->daytime; + if (t2 < daytime_) + t2 += 24.0f; + + float t = (daytime_ - kf1->daytime) / (t2 - kf1->daytime); + + + // args.env.clear_color = glm::vec3(0.1f, 0.15f, 0.3f); + // args.env.ambient_light = glm::vec3(0.4f, 0.4f, 0.4f); + // args.env.sun_color = glm::vec3(0.5f, 0.8f, 1.0f) * 0.4f; + // args.env.sun_direction = glm::normalize(glm::vec3(1.0f, 1.0f, -1.0f)); + + args.env.clear_color = glm::mix(kf1->clear_color, kf2->clear_color, t); + args.env.ambient_light = glm::mix(kf1->ambient_color, kf2->ambient_color, t); + args.env.sun_color = glm::mix(kf1->sun_color, kf2->sun_color, t); + args.env.fog = glm::mix(kf1->fog, kf2->fog, t); + + float dist = args.farplane * 0.5f; + + // std::cout<() / 24.0f; + + sun_color_ = glm::mix(kf1->sun_disc_color, kf2->sun_disc_color, t); + sun_matrix_ = glm::mat4(1.0f); + sun_matrix_ = glm::translate(sun_matrix_, args.eye); + sun_matrix_ = glm::scale(sun_matrix_, glm::vec3(dist)); + sun_matrix_ = glm::rotate(sun_matrix_, 0.3f, glm::vec3(1.0f, 0.0f, 0.0f)); + sun_matrix_ = glm::rotate(sun_matrix_, sun_angle, glm::vec3(0.0f, 1.0f, 0.0f)); + sun_matrix_ = glm::translate(sun_matrix_, glm::vec3(0.0f, 0.0f, 1.0f)); + sun_matrix_ = glm::scale(sun_matrix_, glm::vec3(0.7f)); + + sun_halfsphere_color_ = glm::mix(kf1->sun_halfsphere_color, kf2->sun_halfsphere_color, t); + sun_halfsphere_matrix_ = glm::scale(sun_matrix_, glm::vec3(1.0f, 1.0f, 1.5f)); + + moon_color_ = glm::mix(kf1->moon_disc_color, kf2->moon_disc_color, t); + moon_matrix_ = glm::mat4(1.0f); + moon_matrix_ = glm::translate(moon_matrix_, args.eye); + moon_matrix_ = glm::scale(moon_matrix_, glm::vec3(dist)); + moon_matrix_ = glm::rotate(moon_matrix_, sun_angle + glm::pi(), glm::vec3(0.0f, 1.0f, 0.0f)); + moon_matrix_ = glm::translate(moon_matrix_, glm::vec3(0.0f, 0.0f, 1.0f)); + moon_matrix_ = glm::scale(moon_matrix_, glm::vec3(0.6f)); + + moon_halfsphere_color_ = glm::mix(kf1->moon_halfsphere_color, kf2->moon_halfsphere_color, t); + moon_halfsphere_matrix_ = glm::scale(moon_matrix_, glm::vec3(1.1f, 1.1f, 1.5f)); + + float sun_dir = glm::mix(kf1->sun_dir, kf2->sun_dir, t); + + if (sun_dir >= 0.0f) + { + args.env.sun_direction = -glm::normalize(glm::vec3(sun_matrix_[2])); + args.env.sun_color *= sun_dir; + } + else + { + args.env.sun_direction = -glm::normalize(glm::vec3(moon_matrix_[2])); + args.env.sun_color *= -sun_dir; + } + + DrawEnvModel(args, *halfspheremodel_, moon_halfsphere_matrix_, moon_halfsphere_color_, dist); + DrawEnvModel(args, *halfspheremodel_, sun_halfsphere_matrix_, sun_halfsphere_color_, dist - 1.0f); + DrawEnvModel(args, *sunmodel_, moon_matrix_, moon_color_, dist - 2.0f); + DrawEnvModel(args, *sunmodel_, sun_matrix_, sun_color_, dist - 3.0f); +} + +void game::view::WorldEnv::DrawEnvModel(const DrawArgs& args, const assets::Model& model, const glm::mat4& matrix, + const glm::vec4& color, float dist) +{ + const auto& mesh = model.GetMesh(); + + for (const auto& surface : mesh->surfaces) + { + gfx::DrawSurfaceCmd cmd{}; + cmd.surface = &surface; + cmd.matrices = &matrix; + cmd.color = &color; + cmd.dist = dist; + + args.dlist.AddSurface(cmd); + } +} diff --git a/src/gameview/worldenv.hpp b/src/gameview/worldenv.hpp new file mode 100644 index 0000000..1dc0f48 --- /dev/null +++ b/src/gameview/worldenv.hpp @@ -0,0 +1,56 @@ +#include "assets/model.hpp" +#include "draw_args.hpp" + +namespace game::view +{ + +struct WorldEnvKeyframe +{ + float daytime; + glm::vec3 clear_color; + glm::vec3 ambient_color; + glm::vec3 sun_color; + float sun_dir; // 1=sun 0=none -1=moon + glm::vec4 sun_disc_color; + glm::vec4 sun_halfsphere_color; + glm::vec4 moon_disc_color; + glm::vec4 moon_halfsphere_color; + glm::vec4 fog; +}; + +class WorldEnv +{ +public: + WorldEnv(); + + void Draw(const DrawArgs& args); + + void SetDayTime(float daytime) { daytime_ = glm::mod(daytime, 24.0f); } + float GetDayTime() const { return daytime_; } + +private: + void DrawEnvModel(const DrawArgs& args, const assets::Model& model, const glm::mat4& matrix, const glm::vec4& color, float dist); + +private: + float daytime_ = 0.0f; // 0 - 24 + + std::shared_ptr sunmodel_; + std::shared_ptr moonmodel_; + std::shared_ptr halfspheremodel_; + + glm::mat4 sun_matrix_; + glm::vec4 sun_color_; + + glm::mat4 moon_matrix_; + glm::vec4 moon_color_; + + glm::mat4 sun_halfsphere_matrix_; + glm::vec4 sun_halfsphere_color_; + + glm::mat4 moon_halfsphere_matrix_; + glm::vec4 moon_halfsphere_color_; +}; + + + +} \ No newline at end of file diff --git a/src/gameview/worldview.cpp b/src/gameview/worldview.cpp index 64988b3..5b523de 100644 --- a/src/gameview/worldview.cpp +++ b/src/gameview/worldview.cpp @@ -38,12 +38,18 @@ game::view::WorldView::WorldView(ClientSession& session, net::InMessage& msg) : Cache(assets::CacheManager::GetSound("data/breakwood.snd")); Cache(assets::CacheManager::GetSound("data/cardoor.snd")); Cache(assets::CacheManager::GetSound("data/crash.snd")); + + env_ = std::make_unique(); + env_->SetDayTime(12.0f); } bool game::view::WorldView::ProcessMsg(net::MessageType type, net::InMessage& msg) { switch (type) { + case net::MSG_ENV: + return ProcessEnvMsg(msg); + case net::MSG_ENTSPAWN: return ProcessEntSpawnMsg(msg); @@ -78,6 +84,8 @@ void game::view::WorldView::Update(const UpdateInfo& info) { ent->TryUpdate(info); } + + UpdateEnv(); } void game::view::WorldView::Draw(const DrawArgs& args) const @@ -88,7 +96,7 @@ void game::view::WorldView::Draw(const DrawArgs& args) const return; } - args.env.clear_color = glm::vec3(0.5f, 0.7f, 1.0f); + DrawEnv(args); map_->Draw(args); @@ -149,6 +157,53 @@ void game::view::WorldView::DrawLoadingScreen(const DrawArgs& args) const args.gui.DrawTextAligned(load_text, pos + glm::vec2(size.x + 50.0f, size.y * 0.5f), glm::vec2(-0.5f, -0.5f)); } +void game::view::WorldView::UpdateEnv() +{ + if (!env_) + return; + + env_->SetDayTime(glm::mix(daytime0_, daytime1_, glm::clamp(GetTime() - env_msg_time_, 0.0f, 1.0f))); +} + +void game::view::WorldView::DrawEnv(const DrawArgs& args) const +{ + if (env_) + { + env_->Draw(args); + return; + } + + // args.env.clear_color = glm::vec3(0.5f, 0.7f, 1.0f); + + args.env.clear_color = glm::vec3(0.1f, 0.15f, 0.3f); + args.env.ambient_light = glm::vec3(0.4f, 0.4f, 0.4f); + args.env.sun_color = glm::vec3(0.5f, 0.8f, 1.0f) * 0.4f; + args.env.sun_direction = glm::normalize(glm::vec3(1.0f, 1.0f, -1.0f)); + + +} + +bool game::view::WorldView::ProcessEnvMsg(net::InMessage& msg) +{ + float new_daytime; + + if (!msg.Read(new_daytime)) + return false; + + if (!env_) + return true; + + env_msg_time_ = GetTime(); + daytime0_ = env_->GetDayTime(); + daytime1_ = new_daytime; + + if (daytime1_ < daytime0_) + daytime0_ -= 24.0f; + + + return true; +} + bool game::view::WorldView::ProcessEntSpawnMsg(net::InMessage& msg) { net::EntNum entnum; diff --git a/src/gameview/worldview.hpp b/src/gameview/worldview.hpp index e1f0a7b..10ddde1 100644 --- a/src/gameview/worldview.hpp +++ b/src/gameview/worldview.hpp @@ -9,6 +9,7 @@ #include "collision/dynamicsworld.hpp" #include "entityview.hpp" #include "mapinstanceview.hpp" +#include "worldenv.hpp" namespace game::view { @@ -35,7 +36,11 @@ public: private: void DrawLoadingScreen(const DrawArgs& args) const; + void UpdateEnv(); + void DrawEnv(const DrawArgs& args) const; + // msg handlers + bool ProcessEnvMsg(net::InMessage& msg); bool ProcessEntSpawnMsg(net::InMessage& msg); bool ProcessEntMsgMsg(net::InMessage& msg); bool ProcessUpdateEntsMsg(net::InMessage& msg); @@ -50,9 +55,14 @@ private: std::unique_ptr map_; std::map> ents_; - + std::unique_ptr env_; + float time_ = 0.0f; + float daytime0_ = 0.0f; + float daytime1_ = 0.0f; + float env_msg_time_ = 0.0f; + audio::Master& audiomaster_; std::vector cache_; diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 832d414..4f91811 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -117,6 +117,12 @@ void gfx::Renderer::SetupMeshShader(MeshShader& mshader, const DrawListParams& p glUniformMatrix4fv(shader.U(gfx::SU_VIEW_PROJ), 1, GL_FALSE, ¶ms.view_proj[0][0]); + // setup lighting + glUniform3fv(shader.U(gfx::SU_AMBIENT_LIGHT), 1, ¶ms.env.ambient_light[0]); + glUniform3fv(shader.U(gfx::SU_SUN_COLOR), 1, ¶ms.env.sun_color[0]); + glUniform3fv(shader.U(gfx::SU_SUN_DIRECTION), 1, ¶ms.env.sun_direction[0]); + glUniform4fv(shader.U(gfx::SU_FOG), 1, ¶ms.env.fog[0]); + mshader.global_setup = true; } @@ -188,7 +194,9 @@ void gfx::Renderer::DrawSurfaceList(std::span list, const DrawLi const bool twosided_flag = surface->sflags & SF_2SIDED; const bool blend_flag = surface->sflags & SF_BLEND; const bool object_color_flag = surface->sflags & SF_OBJECT_COLOR; + const bool object_color_mult_flag = surface->sflags & SF_OBJECT_COLOR_MULT; const bool deform_flag = surface->sflags & SF_DEFORM_GRID; + const bool unlit_flag = surface->sflags & SF_UNLIT; // sync 2sided if (last_twosided != twosided_flag) @@ -223,11 +231,20 @@ void gfx::Renderer::DrawSurfaceList(std::span list, const DrawLi if (object_color_flag && cmd.color) { // use object color and disable alpha cull - shflags &= ~SHF_CULL_ALPHA; - shflags |= SHF_BACKGROUND; + + if (!object_color_mult_flag) + { + shflags &= ~SHF_CULL_ALPHA; + shflags |= SHF_BACKGROUND; + } + color = glm::vec4(*cmd.color); } + // check unlit + if (unlit_flag) + shflags |= SHF_UNLIT; + // sync blending if (blend_flag != last_blend) { diff --git a/src/gfx/renderer.hpp b/src/gfx/renderer.hpp index 01612d0..b41ba70 100644 --- a/src/gfx/renderer.hpp +++ b/src/gfx/renderer.hpp @@ -11,7 +11,11 @@ namespace gfx struct DrawListEnvironmentParams { - glm::vec3 clear_color; + glm::vec3 clear_color; + glm::vec3 ambient_light; + glm::vec3 sun_color; + glm::vec3 sun_direction; + glm::vec4 fog; // alpha = distance }; struct DrawListParams diff --git a/src/gfx/shader.cpp b/src/gfx/shader.cpp index 49414ad..dd1bbdd 100644 --- a/src/gfx/shader.cpp +++ b/src/gfx/shader.cpp @@ -13,6 +13,10 @@ static const char* const s_uni_names[] = { "u_camera", // SU_CAMERA "u_deform_tex", // SU_DEFORM_TEX "u_deform_info", // SU_DEFORM_INFO + "u_ambient_light", // SU_AMBIENT_LIGHT + "u_sun_color", // SU_SUN_COLOR + "u_sun_direction", // SU_SUN_DIRECTION + "u_fog", // SU_FOG }; // Vytvori shader z daneho zdroje diff --git a/src/gfx/shader.hpp b/src/gfx/shader.hpp index f74e9c4..41b841f 100644 --- a/src/gfx/shader.hpp +++ b/src/gfx/shader.hpp @@ -18,6 +18,10 @@ namespace gfx SU_CAMERA, SU_DEFORM_TEX, SU_DEFORM_INFO, + SU_AMBIENT_LIGHT, + SU_SUN_COLOR, + SU_SUN_DIRECTION, + SU_FOG, SU_COUNT }; diff --git a/src/gfx/shader_defs.hpp b/src/gfx/shader_defs.hpp index b09d14b..4e48c1c 100644 --- a/src/gfx/shader_defs.hpp +++ b/src/gfx/shader_defs.hpp @@ -4,4 +4,5 @@ #define SD_MAX_BONES 128 #define SHF_CULL_ALPHA 1 -#define SHF_BACKGROUND 2 \ No newline at end of file +#define SHF_BACKGROUND 2 +#define SHF_UNLIT 4 \ No newline at end of file diff --git a/src/gfx/shader_sources.cpp b/src/gfx/shader_sources.cpp index 82f05d9..1159437 100644 --- a/src/gfx/shader_sources.cpp +++ b/src/gfx/shader_sources.cpp @@ -19,6 +19,9 @@ #define SHADER_DEFS \ "#define MAX_LIGHTS " STRINGIFY(SD_MAX_LIGHTS) "\n" \ "#define MAX_BONES " STRINGIFY(SD_MAX_BONES) "\n" \ + "#define SHF_CULL_ALPHA " STRINGIFY(SHF_CULL_ALPHA) "\n" \ + "#define SHF_BACKGROUND " STRINGIFY(SHF_BACKGROUND) "\n" \ + "#define SHF_UNLIT " STRINGIFY(SHF_UNLIT) "\n" \ "\n" #define SHADER_HEADER \ @@ -32,6 +35,12 @@ #define LIGHT_MATRICES_GLSL R"GLSL( uniform vec3 u_ambient_light; + uniform vec3 u_sun_direction; + uniform vec3 u_sun_color; + uniform vec4 u_fog; + + uniform int u_flags; + uniform int u_num_lights; uniform vec3 u_light_positions[MAX_LIGHTS]; uniform vec4 u_light_colors_rs[MAX_LIGHTS]; // rgb = color, a = radius @@ -39,13 +48,18 @@ #define COMPUTE_LIGHTS_GLSL R"GLSL( // Example sun values (can later be uniforms) -vec3 u_sun_direction = normalize(vec3(0.3, 0.5, -0.8)); // direction from which sunlight comes -vec3 u_sun_color = vec3(1.0, 0.95, 0.7) * 0.9; // warm sunlight color +//vec3 u_sun_direction = normalize(vec3(0.3, 0.5, -0.8)); // direction from which sunlight comes +//vec3 u_sun_color = vec3(1.0, 0.95, 0.7) * 0.9; // warm sunlight color + +//uniform vec3 u_ambient_light; vec3 ComputeLights(in vec3 sector_pos, in vec3 sector_normal) { + if ((u_flags & SHF_UNLIT) > 0) + return vec3(1.0); + // Base ambient - vec3 color = vec3(0.5, 0.5, 0.5) * 0.9; // u_ambient_light + vec3 color = u_ambient_light; //vec3(0.5, 0.5, 0.5) * 0.9; // u_ambient_light // Sunlight contribution float sun_dot = max(dot(sector_normal, -u_sun_direction), 0.0); @@ -107,9 +121,6 @@ R"GLSL( in vec2 v_uv; in vec3 v_color; -#define SHF_CULL_ALPHA 1 -#define SHF_BACKGROUND 2 - uniform sampler2D u_tex; uniform vec4 u_color; uniform int u_flags; @@ -119,16 +130,20 @@ layout (location = 0) out vec4 o_color; void main() { o_color = vec4(texture(u_tex, v_uv)); + if ((u_flags & SHF_BACKGROUND) > 0) + { + o_color = mix(u_color, o_color, o_color.a); + } + else + { + o_color *= u_color; + } + if ((u_flags & SHF_CULL_ALPHA) > 0) { if (o_color.a < 0.5) discard; } - else if ((u_flags & SHF_BACKGROUND) > 0) - { - // blend with bg - o_color = mix(u_color, o_color, o_color.a); - } o_color.rgb *= v_color; // Apply vertex color //o_color = vec4(1.0, 0.0, 0.0, 1.0); @@ -183,9 +198,6 @@ R"GLSL( in vec2 v_uv; in vec3 v_color; -#define SHF_CULL_ALPHA 1 -#define SHF_BACKGROUND 2 - uniform sampler2D u_tex; uniform vec4 u_color; uniform int u_flags; @@ -195,16 +207,20 @@ layout (location = 0) out vec4 o_color; void main() { o_color = vec4(texture(u_tex, v_uv)); + if ((u_flags & SHF_BACKGROUND) > 0) + { + o_color = mix(u_color, o_color, o_color.a); + } + else + { + o_color *= u_color; + } + if ((u_flags & SHF_CULL_ALPHA) > 0) { if (o_color.a < 0.5) discard; } - else if ((u_flags & SHF_BACKGROUND) > 0) - { - // blend with bg - o_color = mix(u_color, o_color, o_color.a); - } o_color.rgb *= v_color; // Apply vertex color //o_color = vec4(1.0, 0.0, 0.0, 1.0); @@ -253,9 +269,6 @@ R"GLSL( in vec2 v_uv; in vec3 v_color; -#define SHF_CULL_ALPHA 1 -#define SHF_BACKGROUND 2 - uniform sampler2D u_tex; uniform vec4 u_color; uniform int u_flags; @@ -265,16 +278,20 @@ layout (location = 0) out vec4 o_color; void main() { o_color = vec4(texture(u_tex, v_uv)); + if ((u_flags & SHF_BACKGROUND) > 0) + { + o_color = mix(u_color, o_color, o_color.a); + } + else + { + o_color *= u_color; + } + if ((u_flags & SHF_CULL_ALPHA) > 0) { if (o_color.a < 0.5) discard; } - else if ((u_flags & SHF_BACKGROUND) > 0) - { - // blend with bg - o_color = mix(u_color, o_color, o_color.a); - } o_color.rgb *= v_color; // Apply vertex color //o_color = vec4(1.0, 0.0, 0.0, 1.0); diff --git a/src/gfx/surface.hpp b/src/gfx/surface.hpp index 4a3d190..81e5edd 100644 --- a/src/gfx/surface.hpp +++ b/src/gfx/surface.hpp @@ -26,6 +26,8 @@ enum SurfaceFlag : SurfaceFlags SF_BLEND_ADDITIVE = 0x04, // use additive blending instead of opacity SF_OBJECT_COLOR = 0x08, // use object color for background instead of alpha culling SF_DEFORM_GRID = 0x10, // use deform grid + SF_UNLIT = 0x20, // dont apply lighting + SF_OBJECT_COLOR_MULT = 0x40, // object color multiplies instead of acting as background }; struct Surface diff --git a/src/net/defs.hpp b/src/net/defs.hpp index a1a36f8..7ced616 100644 --- a/src/net/defs.hpp +++ b/src/net/defs.hpp @@ -34,6 +34,9 @@ enum MessageType : uint8_t // CHWORLD MSG_CHWORLD, + // ENV + MSG_ENV, + // CAM MSG_CAM, @@ -76,6 +79,9 @@ constexpr long long PI_D = 78256779; using ViewYawQ = Quantized; using ViewPitchQ = Quantized; +// env +using DayTimeQ = Quantized; + // entities using EntNum = uint16_t; using EntCount = EntNum; @@ -182,5 +188,4 @@ enum MenuActionType using MenuSelectDir = uint8_t; // 0=left, 1=right - } // namespace net \ No newline at end of file diff --git a/src/utils/version.hpp b/src/utils/version.hpp index 4427aa8..54f17a0 100644 --- a/src/utils/version.hpp +++ b/src/utils/version.hpp @@ -1,3 +1,3 @@ #pragma once -#define FEKAL_VERSION 2026050901 +#define FEKAL_VERSION 2026051901