feat: improve fps controller / add fog and ambient light to the scene

This commit is contained in:
2026-10-16 09:29:59 +02:00
parent 21621001c2
commit 4c9b77c948
105 changed files with 609 additions and 110 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

+3 -2
View File
@@ -91,16 +91,17 @@ void main()
diffuseColor, roughness, metallic, f0, shadow);
}
// emissive
vec3 emissiveColor = material.emissiveColor.rgb * sampleTexture2D(material.emissiveTex, samplerID, inUV).rgb;
fragColor += emissiveColor;
// ambient, the specular part keeps metals from turning black without lights
float NoV = clamp(dot(n, v), 0.0001, 1.0);
vec3 ambientLight = pcs.sceneData.ambientColor * pcs.sceneData.ambientIntensity;
vec3 ambientSpecular = envBRDFApprox(f0, roughness, NoV);
fragColor += (diffuseColor + ambientSpecular) * ambientLight * ambientOcclusion;
float fogAmount = pcs.sceneData.fogDensity * length(cameraPos - fragPos);
fragColor = mix(pcs.sceneData.fogColor, fragColor, exp(-fogAmount * fogAmount));
if (pcs.sceneData.debugLightHeatmap != 0) {
fragColor = mix(fragColor, lightHeatmapColor(tileLightCount), 0.5);
}
@@ -58,6 +58,9 @@ public:
[[nodiscard]] bool AllowsSleep() const { return m_AllowSleep; }
void SetAllowSleep(bool allowSleep) { m_AllowSleep = allowSleep; NotifyPhysicsChanged(); }
[[nodiscard]] bool FreezesRotation() const { return m_FreezeRotation; }
void SetFreezeRotation(bool freezeRotation) { m_FreezeRotation = freezeRotation; NotifyPhysicsChanged(); }
[[nodiscard]] PhysicsWorld* GetPhysicsWorld() const { return m_World; }
private:
@@ -72,4 +75,5 @@ private:
bool m_UseGravity{true};
bool m_AllowSleep{true};
bool m_FreezeRotation{false};
};
@@ -20,7 +20,7 @@ public:
void init(GfxDevice& gfxDevice, RenderResources& resources, VkFormat drawImageFormat, VkFormat depthImageFormat);
void cleanup(VkDevice device);
void draw(VkCommandBuffer cmd, RenderResources& resources, const Camera& camera);
void draw(VkCommandBuffer cmd, RenderResources& resources, const Camera& camera, float rotation);
void setSkyboxImage(const ImageID skyboxId);
@@ -30,8 +30,6 @@ private:
std::unique_ptr<Pipeline> pipeline;
ImageID skyboxTextureId{NULL_IMAGE_ID};
glm::mat4 skyboxRotation{1.f};
struct SkyboxPushConstants {
glm::mat4 invViewProj;
glm::vec4 skyboxRot[3];
@@ -34,6 +34,7 @@ public:
float ambientIntensity;
glm::vec3 fogColor;
float fogDensity;
float skyboxRotation{0.0f}; // radians around the world up axis
};
explicit GameRenderer();
@@ -53,7 +53,8 @@ public:
bool Raycast(const glm::vec3& origin,
const glm::vec3& direction,
float maxDistance,
PhysicsRaycastHit& hit) const override;
PhysicsRaycastHit& hit,
PhysicsBodyHandle ignoreBody = {}) const override;
std::vector<TriggerEvent> ConsumeTriggerEvents() override;
@@ -115,6 +115,7 @@ struct PhysicsBodyDesc {
float mass{1.0f};
bool useGravity{true};
bool allowSleep{true};
bool freezeRotation{false};
};
struct TriggerEvent {
@@ -46,10 +46,12 @@ public:
virtual void AddForce(PhysicsBodyHandle body, const glm::vec3& force) = 0;
virtual void AddImpulse(PhysicsBodyHandle body, const glm::vec3& impulse) = 0;
// Triggers are never hit. ignoreBody is skipped too, e.g. so a character can cast from inside its own collider
virtual bool Raycast(const glm::vec3& origin,
const glm::vec3& direction,
float maxDistance,
PhysicsRaycastHit& hit) const = 0;
PhysicsRaycastHit& hit,
PhysicsBodyHandle ignoreBody = {}) const = 0;
// Trigger events accumulated during the last Step().
virtual std::vector<TriggerEvent> ConsumeTriggerEvents() { return {}; }
@@ -46,7 +46,8 @@ public:
bool Raycast(const glm::vec3& origin,
const glm::vec3& direction,
float maxDistance,
PhysicsRaycastHit& hit) const override;
PhysicsRaycastHit& hit,
PhysicsBodyHandle ignoreBody = {}) const override;
void SyncKinematicBodiesToPhysics();
void SyncDynamicBodiesToTransforms();
+19
View File
@@ -14,6 +14,18 @@
class CameraComponent;
class GameObject;
struct SceneEnvironment {
glm::vec3 ambientColor{0.1f};
float ambientIntensity{0.5f};
glm::vec3 fogColor{0.5f};
float fogDensity{0.0f};
float skyboxRotationSpeed{0.01f};
float skyboxRotation{0.0f};
};
class SceneSerializer;
class PhysicsWorld;
@@ -107,6 +119,9 @@ public:
PhysicsSceneBridge& GetPhysics() { return m_Physics; }
[[nodiscard]] SceneEnvironment& GetEnvironment() { return m_Environment; }
[[nodiscard]] const SceneEnvironment& GetEnvironment() const { return m_Environment; }
[[nodiscard]] CameraComponent* GetCurrentCamera() const;
[[nodiscard]] std::vector<CameraComponent*> GetCameras() const;
void SetCurrentCamera(const CameraComponent* camera);
@@ -134,6 +149,10 @@ private:
ObjectId m_CurrentCameraId{InvalidObjectId};
SceneEnvironment m_Environment{};
void DrawSettingsImGui();
std::function<void()> m_registerBindings;
std::function<void()> m_unregisterBindings;
bool m_bindingsUnloaded{false};
+5
View File
@@ -14,6 +14,10 @@ public:
[[nodiscard]] double FixedDeltaTime() const;
[[nodiscard]] double DeltaTime() const;
// How far the current frame is between the last two fixed steps (0..1), used to interpolate physics objects
[[nodiscard]] float FixedAlpha() const { return m_FixedAlpha; }
void SetFixedAlpha(float alpha) { m_FixedAlpha = alpha; }
[[nodiscard]] std::chrono::nanoseconds SleepDuration() const;
void Update();
@@ -25,6 +29,7 @@ private:
static constexpr double m_FixedDeltaTime{1.0 / 60.0};
static constexpr double FPS{60};
double m_DeltaTime{};
float m_FixedAlpha{1.0f};
std::chrono::high_resolution_clock::time_point m_PrevTime;
};
@@ -24,6 +24,7 @@ namespace ImGuiUtils {
const std::vector<std::shared_ptr<GameObject>>& pendingAdditions,
ObjectId& selectedObjectId,
const std::function<GameObject*()>& createGameObject,
const std::function<void()>& drawSceneSettings,
bool* open = nullptr);
}
+2 -2
View File
@@ -1,3 +1,4 @@
#include <algorithm>
#include <chrono>
#include <exception>
#include <SDL_vulkan.h>
@@ -274,8 +275,7 @@ if (!isRunning) break;
TracyPlot("Fixed Steps", static_cast<int64_t>(steps));
}
const float alpha = accumulator / fixedDt;
(void)alpha;
Time::GetInstance().SetFixedAlpha(std::clamp(accumulator / fixedDt, 0.0f, 1.0f));
{
ZoneScopedN("Swapchain Resize Check");
+10 -1
View File
@@ -106,7 +106,8 @@ nlohmann::json Rigidbody::Serialize() const {
{"friction", m_Friction},
{"restitution", m_Restitution},
{"useGravity", m_UseGravity},
{"allowSleep", m_AllowSleep}
{"allowSleep", m_AllowSleep},
{"freezeRotation", m_FreezeRotation}
};
}
@@ -129,6 +130,9 @@ void Rigidbody::Deserialize(const nlohmann::json& data) {
if (data.contains("allowSleep")) {
m_AllowSleep = data.at("allowSleep").get<bool>();
}
if (data.contains("freezeRotation")) {
m_FreezeRotation = data.at("freezeRotation").get<bool>();
}
}
void Rigidbody::ImGuiInspector() {
@@ -163,6 +167,11 @@ void Rigidbody::ImGuiInspector() {
SetAllowSleep(allowSleep);
}
bool freezeRotation = m_FreezeRotation;
if (ImGui::Checkbox("Freeze rotation", &freezeRotation)) {
SetFreezeRotation(freezeRotation);
}
if (HasPhysicsBody()) {
const glm::vec3 velocity = GetLinearVelocity();
ImGui::Text(
@@ -2,7 +2,6 @@
#include <destrum/FS/AssetFS.h>
#include <glm/glm.hpp>
#include <destrum/Util/DeltaTime.h>
#include "volk.h"
#include "glm/ext/matrix_transform.hpp"
@@ -98,26 +97,20 @@ void SkyboxPipeline::cleanup(VkDevice device)
void SkyboxPipeline::draw(
VkCommandBuffer cmd,
RenderResources& resources,
const Camera& camera)
const Camera& camera,
float rotation)
{
if (skyboxTextureId == NULL_IMAGE_ID) {
return;
}
const float rotationSpeed = 0.01f;
skyboxRotation = glm::rotate(
skyboxRotation,
rotationSpeed * static_cast<float>(Time::GetInstance().DeltaTime()),
glm::vec3(0.f, 1.f, 0.f));
pipeline->bind(cmd);
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
resources.bindBindlessDescSet(cmd, pipelineLayout);
const glm::mat3 r = glm::mat3(skyboxRotation);
const glm::mat3 r = glm::mat3(glm::rotate(glm::mat4{1.f}, rotation, glm::vec3(0.f, 1.f, 0.f)));
// rotation only, translation in the inverse makes the sky jitter far from the origin
const glm::mat4 viewRotation = glm::mat4(glm::mat3(camera.GetViewMatrix()));
+1 -1
View File
@@ -306,7 +306,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "SkyboxPipeline::draw");
vkutil::ScopedCmdLabel label(cmd, "SkyboxPipeline::draw", vkutil::labelColors::sky);
skyboxPipeline->draw(cmd, *resources, camera);
skyboxPipeline->draw(cmd, *resources, camera, sceneData.skyboxRotation);
}
{
+38 -4
View File
@@ -7,6 +7,7 @@
#include <Jolt/Core/JobSystemThreadPool.h>
#include <Jolt/Core/TempAllocator.h>
#include <Jolt/Physics/Body/BodyCreationSettings.h>
#include <Jolt/Physics/Body/BodyFilter.h>
#include <Jolt/Physics/Body/BodyInterface.h>
#include <Jolt/Physics/Body/MotionType.h>
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
@@ -95,6 +96,29 @@ namespace
}
}
// Raycasts skip triggers and optionally one body (e.g. the caster's own collider)
class RaycastBodyFilter final : public BodyFilter
{
public:
explicit RaycastBodyFilter(const BodyID& ignoredBody)
: m_IgnoredBody(ignoredBody)
{
}
bool ShouldCollide(const BodyID& inBodyID) const override
{
return inBodyID != m_IgnoredBody;
}
bool ShouldCollideLocked(const Body& inBody) const override
{
return !inBody.IsSensor();
}
private:
BodyID m_IgnoredBody;
};
namespace Layers
{
static constexpr ObjectLayer NON_MOVING = 0;
@@ -447,6 +471,10 @@ public:
settings.mIsSensor = desc.shape.isTrigger;
settings.mAllowSleeping = desc.allowSleep;
settings.mGravityFactor = desc.useGravity ? 1.0f : 0.0f;
if (desc.freezeRotation)
{
settings.mAllowedDOFs = EAllowedDOFs::TranslationX | EAllowedDOFs::TranslationY | EAllowedDOFs::TranslationZ;
}
settings.mUserData = reinterpret_cast<JPH::uint64>(desc.owner);
if (desc.type == RigidbodyType::Dynamic)
@@ -631,7 +659,8 @@ public:
bool Raycast(const glm::vec3& origin,
const glm::vec3& direction,
float maxDistance,
PhysicsRaycastHit& hit) const
PhysicsRaycastHit& hit,
PhysicsBodyHandle ignoreBody) const
{
if (maxDistance <= 0.0f || glm::length2(direction) <= 0.0000001f)
{
@@ -645,8 +674,12 @@ public:
ToJoltVec3(directionNormalized * maxDistance)
};
const BodyRecord* ignored = ignoreBody.IsValid() ? FindBody(ignoreBody) : nullptr;
const RaycastBodyFilter bodyFilter(ignored != nullptr ? ignored->bodyID : BodyID{});
RayCastResult result{};
if (!m_PhysicsSystem.GetNarrowPhaseQuery().CastRay(ray, result))
if (!m_PhysicsSystem.GetNarrowPhaseQuery().CastRay(
ray, result, BroadPhaseLayerFilter{}, ObjectLayerFilter{}, bodyFilter))
{
return false;
}
@@ -838,9 +871,10 @@ void JoltPhysicsWorld::AddImpulse(PhysicsBodyHandle body, const glm::vec3& impul
bool JoltPhysicsWorld::Raycast(const glm::vec3& origin,
const glm::vec3& direction,
float maxDistance,
PhysicsRaycastHit& hit) const
PhysicsRaycastHit& hit,
PhysicsBodyHandle ignoreBody) const
{
return m_Impl->Raycast(origin, direction, maxDistance, hit);
return m_Impl->Raycast(origin, direction, maxDistance, hit, ignoreBody);
}
std::vector<TriggerEvent> JoltPhysicsWorld::ConsumeTriggerEvents()
+1
View File
@@ -70,6 +70,7 @@ void PhysicsWorld::RegisterRigidbody(Rigidbody& rigidbody) {
desc.mass = rigidbody.GetMass();
desc.useGravity = rigidbody.UsesGravity();
desc.allowSleep = rigidbody.AllowsSleep();
desc.freezeRotation = rigidbody.FreezesRotation();
desc.material.friction = rigidbody.GetFriction();
desc.material.restitution = rigidbody.GetRestitution();
+5 -2
View File
@@ -165,7 +165,8 @@ void SimplePhysicsWorld::SyncDynamicBodiesToTransforms() {
bool SimplePhysicsWorld::Raycast(const glm::vec3& origin,
const glm::vec3& direction,
float maxDistance,
PhysicsRaycastHit& hit) const {
PhysicsRaycastHit& hit,
PhysicsBodyHandle ignoreBody) const {
if (maxDistance <= 0.0f) {
return false;
}
@@ -183,7 +184,9 @@ bool SimplePhysicsWorld::Raycast(const glm::vec3& origin,
for (const BodyRecord& body : m_Bodies) {
if (!body.alive || body.desc.shape.type == PhysicsShapeType::None ||
!body.desc.owner || body.desc.owner->IsBeingDestroyed() ||
!body.desc.owner->IsActiveInHierarchy()) {
!body.desc.owner->IsActiveInHierarchy() ||
body.desc.shape.isTrigger ||
(ignoreBody.IsValid() && body.handle.id == ignoreBody.id)) {
continue;
}
+31
View File
@@ -4,6 +4,10 @@
#include <destrum/Util/ImGuiUtils.h>
#include <algorithm>
#include <cmath>
#include <glm/gtc/constants.hpp>
#include <imgui.h>
unsigned int Scene::m_idCounter = 0;
@@ -131,6 +135,32 @@ void Scene::Update(float dt) {
}
}
m_Environment.skyboxRotation = std::fmod(
m_Environment.skyboxRotation + m_Environment.skyboxRotationSpeed * dt,
glm::two_pi<float>());
}
void Scene::DrawSettingsImGui() {
SceneEnvironment& environment = m_Environment;
ImGui::SeparatorText("Ambient");
ImGui::ColorEdit3("Ambient color", &environment.ambientColor.x);
ImGui::DragFloat("Ambient intensity", &environment.ambientIntensity, 0.01f, 0.0f, 100.0f);
ImGui::SeparatorText("Fog");
ImGui::ColorEdit3("Fog color", &environment.fogColor.x, ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float);
ImGui::DragFloat("Fog density", &environment.fogDensity, 0.001f, 0.0f, 1.0f, "%.4f");
ImGui::SeparatorText("Skybox");
float speedDegrees = glm::degrees(environment.skyboxRotationSpeed);
if (ImGui::DragFloat("Spin (deg/s)", &speedDegrees, 0.05f)) {
environment.skyboxRotationSpeed = glm::radians(speedDegrees);
}
float rotationDegrees = glm::degrees(environment.skyboxRotation);
if (ImGui::SliderFloat("Rotation (deg)", &rotationDegrees, -360.0f, 360.0f)) {
environment.skyboxRotation = glm::radians(rotationDegrees);
}
}
void Scene::FixedUpdate(float dt) {
@@ -200,6 +230,7 @@ void Scene::RenderImgui(bool* open) {
m_pendingAdditions,
m_SelectedObjectId,
[this] { return CreateGameObject("GameObject"); },
[this] { DrawSettingsImGui(); },
open);
}
@@ -300,6 +300,15 @@ bool SceneSerializer::Save(Scene& scene, const std::filesystem::path& path) {
if (scene.m_CurrentCameraId != InvalidObjectId) {
root["currentCamera"] = scene.m_CurrentCameraId;
}
const SceneEnvironment& environment = scene.GetEnvironment();
root["environment"] = {
{"ambientColor", {environment.ambientColor.x, environment.ambientColor.y, environment.ambientColor.z}},
{"ambientIntensity", environment.ambientIntensity},
{"fogColor", {environment.fogColor.x, environment.fogColor.y, environment.fogColor.z}},
{"fogDensity", environment.fogDensity},
{"skyboxRotationSpeed", environment.skyboxRotationSpeed},
{"skyboxRotation", environment.skyboxRotation},
};
for (const auto& objectPtr : scene.GetObjects()) {
if (!objectPtr || objectPtr->IsBeingDestroyed()) {
@@ -573,6 +582,23 @@ bool SceneSerializer::ConstructScene(Scene& scene, LoadResult& result,
scene.m_name = root.at("name").get<std::string>();
}
scene.m_CurrentCameraId = root.value("currentCamera", InvalidObjectId);
scene.m_Environment = SceneEnvironment{};
if (root.contains("environment") && root.at("environment").is_object()) {
const auto& data = root.at("environment");
SceneEnvironment& environment = scene.m_Environment;
const auto readColor = [&data](const char* key, glm::vec3& color) {
if (data.contains(key) && data.at(key).is_array() && data.at(key).size() == 3) {
const auto& value = data.at(key);
color = {value.at(0).get<float>(), value.at(1).get<float>(), value.at(2).get<float>()};
}
};
readColor("ambientColor", environment.ambientColor);
environment.ambientIntensity = data.value("ambientIntensity", environment.ambientIntensity);
readColor("fogColor", environment.fogColor);
environment.fogDensity = data.value("fogDensity", environment.fogDensity);
environment.skyboxRotationSpeed = data.value("skyboxRotationSpeed", environment.skyboxRotationSpeed);
environment.skyboxRotation = data.value("skyboxRotation", environment.skyboxRotation);
}
if (progressCallback) progressCallback(0.9f);
+4
View File
@@ -125,6 +125,7 @@ namespace ImGuiUtils {
const std::vector<std::shared_ptr<GameObject>>& pendingAdditions,
ObjectId& selectedObjectId,
const std::function<GameObject*()>& createGameObject,
const std::function<void()>& drawSceneSettings,
bool* open) {
RegisterEngineComponents();
@@ -176,6 +177,9 @@ namespace ImGuiUtils {
}
}
}
if (drawSceneSettings && ImGui::CollapsingHeader("Scene Settings")) {
drawSceneSettings();
}
ImGui::Separator();
const float availableWidth = ImGui::GetContentRegionAvail().x;