feat: improve fps controller / add fog and ambient light to the scene
|
After Width: | Height: | Size: 5.3 MiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -91,16 +91,17 @@ void main()
|
|||||||
diffuseColor, roughness, metallic, f0, shadow);
|
diffuseColor, roughness, metallic, f0, shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emissive
|
|
||||||
vec3 emissiveColor = material.emissiveColor.rgb * sampleTexture2D(material.emissiveTex, samplerID, inUV).rgb;
|
vec3 emissiveColor = material.emissiveColor.rgb * sampleTexture2D(material.emissiveTex, samplerID, inUV).rgb;
|
||||||
fragColor += emissiveColor;
|
fragColor += emissiveColor;
|
||||||
|
|
||||||
// ambient, the specular part keeps metals from turning black without lights
|
|
||||||
float NoV = clamp(dot(n, v), 0.0001, 1.0);
|
float NoV = clamp(dot(n, v), 0.0001, 1.0);
|
||||||
vec3 ambientLight = pcs.sceneData.ambientColor * pcs.sceneData.ambientIntensity;
|
vec3 ambientLight = pcs.sceneData.ambientColor * pcs.sceneData.ambientIntensity;
|
||||||
vec3 ambientSpecular = envBRDFApprox(f0, roughness, NoV);
|
vec3 ambientSpecular = envBRDFApprox(f0, roughness, NoV);
|
||||||
fragColor += (diffuseColor + ambientSpecular) * ambientLight * ambientOcclusion;
|
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) {
|
if (pcs.sceneData.debugLightHeatmap != 0) {
|
||||||
fragColor = mix(fragColor, lightHeatmapColor(tileLightCount), 0.5);
|
fragColor = mix(fragColor, lightHeatmapColor(tileLightCount), 0.5);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ public:
|
|||||||
[[nodiscard]] bool AllowsSleep() const { return m_AllowSleep; }
|
[[nodiscard]] bool AllowsSleep() const { return m_AllowSleep; }
|
||||||
void SetAllowSleep(bool allowSleep) { m_AllowSleep = allowSleep; NotifyPhysicsChanged(); }
|
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; }
|
[[nodiscard]] PhysicsWorld* GetPhysicsWorld() const { return m_World; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -72,4 +75,5 @@ private:
|
|||||||
|
|
||||||
bool m_UseGravity{true};
|
bool m_UseGravity{true};
|
||||||
bool m_AllowSleep{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 init(GfxDevice& gfxDevice, RenderResources& resources, VkFormat drawImageFormat, VkFormat depthImageFormat);
|
||||||
void cleanup(VkDevice device);
|
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);
|
void setSkyboxImage(const ImageID skyboxId);
|
||||||
|
|
||||||
@@ -30,8 +30,6 @@ private:
|
|||||||
std::unique_ptr<Pipeline> pipeline;
|
std::unique_ptr<Pipeline> pipeline;
|
||||||
ImageID skyboxTextureId{NULL_IMAGE_ID};
|
ImageID skyboxTextureId{NULL_IMAGE_ID};
|
||||||
|
|
||||||
glm::mat4 skyboxRotation{1.f};
|
|
||||||
|
|
||||||
struct SkyboxPushConstants {
|
struct SkyboxPushConstants {
|
||||||
glm::mat4 invViewProj;
|
glm::mat4 invViewProj;
|
||||||
glm::vec4 skyboxRot[3];
|
glm::vec4 skyboxRot[3];
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public:
|
|||||||
float ambientIntensity;
|
float ambientIntensity;
|
||||||
glm::vec3 fogColor;
|
glm::vec3 fogColor;
|
||||||
float fogDensity;
|
float fogDensity;
|
||||||
|
float skyboxRotation{0.0f}; // radians around the world up axis
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit GameRenderer();
|
explicit GameRenderer();
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ public:
|
|||||||
bool Raycast(const glm::vec3& origin,
|
bool Raycast(const glm::vec3& origin,
|
||||||
const glm::vec3& direction,
|
const glm::vec3& direction,
|
||||||
float maxDistance,
|
float maxDistance,
|
||||||
PhysicsRaycastHit& hit) const override;
|
PhysicsRaycastHit& hit,
|
||||||
|
PhysicsBodyHandle ignoreBody = {}) const override;
|
||||||
|
|
||||||
std::vector<TriggerEvent> ConsumeTriggerEvents() override;
|
std::vector<TriggerEvent> ConsumeTriggerEvents() override;
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ struct PhysicsBodyDesc {
|
|||||||
float mass{1.0f};
|
float mass{1.0f};
|
||||||
bool useGravity{true};
|
bool useGravity{true};
|
||||||
bool allowSleep{true};
|
bool allowSleep{true};
|
||||||
|
bool freezeRotation{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TriggerEvent {
|
struct TriggerEvent {
|
||||||
|
|||||||
@@ -46,10 +46,12 @@ public:
|
|||||||
virtual void AddForce(PhysicsBodyHandle body, const glm::vec3& force) = 0;
|
virtual void AddForce(PhysicsBodyHandle body, const glm::vec3& force) = 0;
|
||||||
virtual void AddImpulse(PhysicsBodyHandle body, const glm::vec3& impulse) = 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,
|
virtual bool Raycast(const glm::vec3& origin,
|
||||||
const glm::vec3& direction,
|
const glm::vec3& direction,
|
||||||
float maxDistance,
|
float maxDistance,
|
||||||
PhysicsRaycastHit& hit) const = 0;
|
PhysicsRaycastHit& hit,
|
||||||
|
PhysicsBodyHandle ignoreBody = {}) const = 0;
|
||||||
|
|
||||||
// Trigger events accumulated during the last Step().
|
// Trigger events accumulated during the last Step().
|
||||||
virtual std::vector<TriggerEvent> ConsumeTriggerEvents() { return {}; }
|
virtual std::vector<TriggerEvent> ConsumeTriggerEvents() { return {}; }
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ public:
|
|||||||
bool Raycast(const glm::vec3& origin,
|
bool Raycast(const glm::vec3& origin,
|
||||||
const glm::vec3& direction,
|
const glm::vec3& direction,
|
||||||
float maxDistance,
|
float maxDistance,
|
||||||
PhysicsRaycastHit& hit) const override;
|
PhysicsRaycastHit& hit,
|
||||||
|
PhysicsBodyHandle ignoreBody = {}) const override;
|
||||||
|
|
||||||
void SyncKinematicBodiesToPhysics();
|
void SyncKinematicBodiesToPhysics();
|
||||||
void SyncDynamicBodiesToTransforms();
|
void SyncDynamicBodiesToTransforms();
|
||||||
|
|||||||
@@ -14,6 +14,18 @@
|
|||||||
|
|
||||||
class CameraComponent;
|
class CameraComponent;
|
||||||
class GameObject;
|
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 SceneSerializer;
|
||||||
class PhysicsWorld;
|
class PhysicsWorld;
|
||||||
|
|
||||||
@@ -107,6 +119,9 @@ public:
|
|||||||
|
|
||||||
PhysicsSceneBridge& GetPhysics() { return m_Physics; }
|
PhysicsSceneBridge& GetPhysics() { return m_Physics; }
|
||||||
|
|
||||||
|
[[nodiscard]] SceneEnvironment& GetEnvironment() { return m_Environment; }
|
||||||
|
[[nodiscard]] const SceneEnvironment& GetEnvironment() const { return m_Environment; }
|
||||||
|
|
||||||
[[nodiscard]] CameraComponent* GetCurrentCamera() const;
|
[[nodiscard]] CameraComponent* GetCurrentCamera() const;
|
||||||
[[nodiscard]] std::vector<CameraComponent*> GetCameras() const;
|
[[nodiscard]] std::vector<CameraComponent*> GetCameras() const;
|
||||||
void SetCurrentCamera(const CameraComponent* camera);
|
void SetCurrentCamera(const CameraComponent* camera);
|
||||||
@@ -134,6 +149,10 @@ private:
|
|||||||
|
|
||||||
ObjectId m_CurrentCameraId{InvalidObjectId};
|
ObjectId m_CurrentCameraId{InvalidObjectId};
|
||||||
|
|
||||||
|
SceneEnvironment m_Environment{};
|
||||||
|
|
||||||
|
void DrawSettingsImGui();
|
||||||
|
|
||||||
std::function<void()> m_registerBindings;
|
std::function<void()> m_registerBindings;
|
||||||
std::function<void()> m_unregisterBindings;
|
std::function<void()> m_unregisterBindings;
|
||||||
bool m_bindingsUnloaded{false};
|
bool m_bindingsUnloaded{false};
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ public:
|
|||||||
[[nodiscard]] double FixedDeltaTime() const;
|
[[nodiscard]] double FixedDeltaTime() const;
|
||||||
[[nodiscard]] double DeltaTime() 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;
|
[[nodiscard]] std::chrono::nanoseconds SleepDuration() const;
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
@@ -25,6 +29,7 @@ private:
|
|||||||
static constexpr double m_FixedDeltaTime{1.0 / 60.0};
|
static constexpr double m_FixedDeltaTime{1.0 / 60.0};
|
||||||
static constexpr double FPS{60};
|
static constexpr double FPS{60};
|
||||||
double m_DeltaTime{};
|
double m_DeltaTime{};
|
||||||
|
float m_FixedAlpha{1.0f};
|
||||||
std::chrono::high_resolution_clock::time_point m_PrevTime;
|
std::chrono::high_resolution_clock::time_point m_PrevTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace ImGuiUtils {
|
|||||||
const std::vector<std::shared_ptr<GameObject>>& pendingAdditions,
|
const std::vector<std::shared_ptr<GameObject>>& pendingAdditions,
|
||||||
ObjectId& selectedObjectId,
|
ObjectId& selectedObjectId,
|
||||||
const std::function<GameObject*()>& createGameObject,
|
const std::function<GameObject*()>& createGameObject,
|
||||||
|
const std::function<void()>& drawSceneSettings,
|
||||||
bool* open = nullptr);
|
bool* open = nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <SDL_vulkan.h>
|
#include <SDL_vulkan.h>
|
||||||
@@ -274,8 +275,7 @@ if (!isRunning) break;
|
|||||||
TracyPlot("Fixed Steps", static_cast<int64_t>(steps));
|
TracyPlot("Fixed Steps", static_cast<int64_t>(steps));
|
||||||
}
|
}
|
||||||
|
|
||||||
const float alpha = accumulator / fixedDt;
|
Time::GetInstance().SetFixedAlpha(std::clamp(accumulator / fixedDt, 0.0f, 1.0f));
|
||||||
(void)alpha;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ZoneScopedN("Swapchain Resize Check");
|
ZoneScopedN("Swapchain Resize Check");
|
||||||
|
|||||||
@@ -106,7 +106,8 @@ nlohmann::json Rigidbody::Serialize() const {
|
|||||||
{"friction", m_Friction},
|
{"friction", m_Friction},
|
||||||
{"restitution", m_Restitution},
|
{"restitution", m_Restitution},
|
||||||
{"useGravity", m_UseGravity},
|
{"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")) {
|
if (data.contains("allowSleep")) {
|
||||||
m_AllowSleep = data.at("allowSleep").get<bool>();
|
m_AllowSleep = data.at("allowSleep").get<bool>();
|
||||||
}
|
}
|
||||||
|
if (data.contains("freezeRotation")) {
|
||||||
|
m_FreezeRotation = data.at("freezeRotation").get<bool>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rigidbody::ImGuiInspector() {
|
void Rigidbody::ImGuiInspector() {
|
||||||
@@ -163,6 +167,11 @@ void Rigidbody::ImGuiInspector() {
|
|||||||
SetAllowSleep(allowSleep);
|
SetAllowSleep(allowSleep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool freezeRotation = m_FreezeRotation;
|
||||||
|
if (ImGui::Checkbox("Freeze rotation", &freezeRotation)) {
|
||||||
|
SetFreezeRotation(freezeRotation);
|
||||||
|
}
|
||||||
|
|
||||||
if (HasPhysicsBody()) {
|
if (HasPhysicsBody()) {
|
||||||
const glm::vec3 velocity = GetLinearVelocity();
|
const glm::vec3 velocity = GetLinearVelocity();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <destrum/FS/AssetFS.h>
|
#include <destrum/FS/AssetFS.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <destrum/Util/DeltaTime.h>
|
|
||||||
|
|
||||||
#include "volk.h"
|
#include "volk.h"
|
||||||
#include "glm/ext/matrix_transform.hpp"
|
#include "glm/ext/matrix_transform.hpp"
|
||||||
@@ -98,26 +97,20 @@ void SkyboxPipeline::cleanup(VkDevice device)
|
|||||||
void SkyboxPipeline::draw(
|
void SkyboxPipeline::draw(
|
||||||
VkCommandBuffer cmd,
|
VkCommandBuffer cmd,
|
||||||
RenderResources& resources,
|
RenderResources& resources,
|
||||||
const Camera& camera)
|
const Camera& camera,
|
||||||
|
float rotation)
|
||||||
{
|
{
|
||||||
if (skyboxTextureId == NULL_IMAGE_ID) {
|
if (skyboxTextureId == NULL_IMAGE_ID) {
|
||||||
return;
|
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);
|
pipeline->bind(cmd);
|
||||||
|
|
||||||
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
|
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
|
||||||
|
|
||||||
resources.bindBindlessDescSet(cmd, pipelineLayout);
|
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
|
// rotation only, translation in the inverse makes the sky jitter far from the origin
|
||||||
const glm::mat4 viewRotation = glm::mat4(glm::mat3(camera.GetViewMatrix()));
|
const glm::mat4 viewRotation = glm::mat4(glm::mat3(camera.GetViewMatrix()));
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "SkyboxPipeline::draw");
|
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "SkyboxPipeline::draw");
|
||||||
vkutil::ScopedCmdLabel label(cmd, "SkyboxPipeline::draw", vkutil::labelColors::sky);
|
vkutil::ScopedCmdLabel label(cmd, "SkyboxPipeline::draw", vkutil::labelColors::sky);
|
||||||
|
|
||||||
skyboxPipeline->draw(cmd, *resources, camera);
|
skyboxPipeline->draw(cmd, *resources, camera, sceneData.skyboxRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <Jolt/Core/JobSystemThreadPool.h>
|
#include <Jolt/Core/JobSystemThreadPool.h>
|
||||||
#include <Jolt/Core/TempAllocator.h>
|
#include <Jolt/Core/TempAllocator.h>
|
||||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||||
|
#include <Jolt/Physics/Body/BodyFilter.h>
|
||||||
#include <Jolt/Physics/Body/BodyInterface.h>
|
#include <Jolt/Physics/Body/BodyInterface.h>
|
||||||
#include <Jolt/Physics/Body/MotionType.h>
|
#include <Jolt/Physics/Body/MotionType.h>
|
||||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.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
|
namespace Layers
|
||||||
{
|
{
|
||||||
static constexpr ObjectLayer NON_MOVING = 0;
|
static constexpr ObjectLayer NON_MOVING = 0;
|
||||||
@@ -447,6 +471,10 @@ public:
|
|||||||
settings.mIsSensor = desc.shape.isTrigger;
|
settings.mIsSensor = desc.shape.isTrigger;
|
||||||
settings.mAllowSleeping = desc.allowSleep;
|
settings.mAllowSleeping = desc.allowSleep;
|
||||||
settings.mGravityFactor = desc.useGravity ? 1.0f : 0.0f;
|
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);
|
settings.mUserData = reinterpret_cast<JPH::uint64>(desc.owner);
|
||||||
|
|
||||||
if (desc.type == RigidbodyType::Dynamic)
|
if (desc.type == RigidbodyType::Dynamic)
|
||||||
@@ -631,7 +659,8 @@ public:
|
|||||||
bool Raycast(const glm::vec3& origin,
|
bool Raycast(const glm::vec3& origin,
|
||||||
const glm::vec3& direction,
|
const glm::vec3& direction,
|
||||||
float maxDistance,
|
float maxDistance,
|
||||||
PhysicsRaycastHit& hit) const
|
PhysicsRaycastHit& hit,
|
||||||
|
PhysicsBodyHandle ignoreBody) const
|
||||||
{
|
{
|
||||||
if (maxDistance <= 0.0f || glm::length2(direction) <= 0.0000001f)
|
if (maxDistance <= 0.0f || glm::length2(direction) <= 0.0000001f)
|
||||||
{
|
{
|
||||||
@@ -645,8 +674,12 @@ public:
|
|||||||
ToJoltVec3(directionNormalized * maxDistance)
|
ToJoltVec3(directionNormalized * maxDistance)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const BodyRecord* ignored = ignoreBody.IsValid() ? FindBody(ignoreBody) : nullptr;
|
||||||
|
const RaycastBodyFilter bodyFilter(ignored != nullptr ? ignored->bodyID : BodyID{});
|
||||||
|
|
||||||
RayCastResult result{};
|
RayCastResult result{};
|
||||||
if (!m_PhysicsSystem.GetNarrowPhaseQuery().CastRay(ray, result))
|
if (!m_PhysicsSystem.GetNarrowPhaseQuery().CastRay(
|
||||||
|
ray, result, BroadPhaseLayerFilter{}, ObjectLayerFilter{}, bodyFilter))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -838,9 +871,10 @@ void JoltPhysicsWorld::AddImpulse(PhysicsBodyHandle body, const glm::vec3& impul
|
|||||||
bool JoltPhysicsWorld::Raycast(const glm::vec3& origin,
|
bool JoltPhysicsWorld::Raycast(const glm::vec3& origin,
|
||||||
const glm::vec3& direction,
|
const glm::vec3& direction,
|
||||||
float maxDistance,
|
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()
|
std::vector<TriggerEvent> JoltPhysicsWorld::ConsumeTriggerEvents()
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ void PhysicsWorld::RegisterRigidbody(Rigidbody& rigidbody) {
|
|||||||
desc.mass = rigidbody.GetMass();
|
desc.mass = rigidbody.GetMass();
|
||||||
desc.useGravity = rigidbody.UsesGravity();
|
desc.useGravity = rigidbody.UsesGravity();
|
||||||
desc.allowSleep = rigidbody.AllowsSleep();
|
desc.allowSleep = rigidbody.AllowsSleep();
|
||||||
|
desc.freezeRotation = rigidbody.FreezesRotation();
|
||||||
desc.material.friction = rigidbody.GetFriction();
|
desc.material.friction = rigidbody.GetFriction();
|
||||||
desc.material.restitution = rigidbody.GetRestitution();
|
desc.material.restitution = rigidbody.GetRestitution();
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,8 @@ void SimplePhysicsWorld::SyncDynamicBodiesToTransforms() {
|
|||||||
bool SimplePhysicsWorld::Raycast(const glm::vec3& origin,
|
bool SimplePhysicsWorld::Raycast(const glm::vec3& origin,
|
||||||
const glm::vec3& direction,
|
const glm::vec3& direction,
|
||||||
float maxDistance,
|
float maxDistance,
|
||||||
PhysicsRaycastHit& hit) const {
|
PhysicsRaycastHit& hit,
|
||||||
|
PhysicsBodyHandle ignoreBody) const {
|
||||||
if (maxDistance <= 0.0f) {
|
if (maxDistance <= 0.0f) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -183,7 +184,9 @@ bool SimplePhysicsWorld::Raycast(const glm::vec3& origin,
|
|||||||
for (const BodyRecord& body : m_Bodies) {
|
for (const BodyRecord& body : m_Bodies) {
|
||||||
if (!body.alive || body.desc.shape.type == PhysicsShapeType::None ||
|
if (!body.alive || body.desc.shape.type == PhysicsShapeType::None ||
|
||||||
!body.desc.owner || body.desc.owner->IsBeingDestroyed() ||
|
!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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
#include <destrum/Util/ImGuiUtils.h>
|
#include <destrum/Util/ImGuiUtils.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <glm/gtc/constants.hpp>
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
unsigned int Scene::m_idCounter = 0;
|
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) {
|
void Scene::FixedUpdate(float dt) {
|
||||||
@@ -200,6 +230,7 @@ void Scene::RenderImgui(bool* open) {
|
|||||||
m_pendingAdditions,
|
m_pendingAdditions,
|
||||||
m_SelectedObjectId,
|
m_SelectedObjectId,
|
||||||
[this] { return CreateGameObject("GameObject"); },
|
[this] { return CreateGameObject("GameObject"); },
|
||||||
|
[this] { DrawSettingsImGui(); },
|
||||||
open);
|
open);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -300,6 +300,15 @@ bool SceneSerializer::Save(Scene& scene, const std::filesystem::path& path) {
|
|||||||
if (scene.m_CurrentCameraId != InvalidObjectId) {
|
if (scene.m_CurrentCameraId != InvalidObjectId) {
|
||||||
root["currentCamera"] = scene.m_CurrentCameraId;
|
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()) {
|
for (const auto& objectPtr : scene.GetObjects()) {
|
||||||
if (!objectPtr || objectPtr->IsBeingDestroyed()) {
|
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_name = root.at("name").get<std::string>();
|
||||||
}
|
}
|
||||||
scene.m_CurrentCameraId = root.value("currentCamera", InvalidObjectId);
|
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);
|
if (progressCallback) progressCallback(0.9f);
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ namespace ImGuiUtils {
|
|||||||
const std::vector<std::shared_ptr<GameObject>>& pendingAdditions,
|
const std::vector<std::shared_ptr<GameObject>>& pendingAdditions,
|
||||||
ObjectId& selectedObjectId,
|
ObjectId& selectedObjectId,
|
||||||
const std::function<GameObject*()>& createGameObject,
|
const std::function<GameObject*()>& createGameObject,
|
||||||
|
const std::function<void()>& drawSceneSettings,
|
||||||
bool* open) {
|
bool* open) {
|
||||||
RegisterEngineComponents();
|
RegisterEngineComponents();
|
||||||
|
|
||||||
@@ -176,6 +177,9 @@ namespace ImGuiUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (drawSceneSettings && ImGui::CollapsingHeader("Scene Settings")) {
|
||||||
|
drawSceneSettings();
|
||||||
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
const float availableWidth = ImGui::GetContentRegionAvail().x;
|
const float availableWidth = ImGui::GetContentRegionAvail().x;
|
||||||
|
|||||||