diff --git a/Assets/compiled/Debug.vert.dxil b/Assets/compiled/Debug.vert.dxil index 5fdd7a0..865e6a3 100644 Binary files a/Assets/compiled/Debug.vert.dxil and b/Assets/compiled/Debug.vert.dxil differ diff --git a/Assets/compiled/ImGui.frag.dxil b/Assets/compiled/ImGui.frag.dxil index 368b0b5..0529b79 100644 Binary files a/Assets/compiled/ImGui.frag.dxil and b/Assets/compiled/ImGui.frag.dxil differ diff --git a/Assets/compiled/ImGui.vert.dxil b/Assets/compiled/ImGui.vert.dxil index e26ed40..10a905d 100644 Binary files a/Assets/compiled/ImGui.vert.dxil and b/Assets/compiled/ImGui.vert.dxil differ diff --git a/Assets/compiled/Skybox.vert.dxil b/Assets/compiled/Skybox.vert.dxil index 12ae4fb..6cc5b90 100644 Binary files a/Assets/compiled/Skybox.vert.dxil and b/Assets/compiled/Skybox.vert.dxil differ diff --git a/Assets/compiled/SolidColor.frag.dxil b/Assets/compiled/SolidColor.frag.dxil index 8a78cc9..910457d 100644 Binary files a/Assets/compiled/SolidColor.frag.dxil and b/Assets/compiled/SolidColor.frag.dxil differ diff --git a/Assets/compiled/Triangle.vert.dxil b/Assets/compiled/Triangle.vert.dxil index 1e2d232..b674c48 100644 Binary files a/Assets/compiled/Triangle.vert.dxil and b/Assets/compiled/Triangle.vert.dxil differ diff --git a/Assets/source/RootConstants.hlsl b/Assets/source/RootConstants.hlsl index 301fcf9..b2270a3 100644 --- a/Assets/source/RootConstants.hlsl +++ b/Assets/source/RootConstants.hlsl @@ -9,16 +9,23 @@ struct PointLight float Intensity; }; +struct TransformData +{ + row_major float4x4 Model; +}; + cbuffer RootConstants : register(b0, space0) { row_major float4x4 ViewProjection; - row_major float4x4 Model; + uint MeshIndex; + uint TransformsBufferIndex; uint BufferIndex; - uint TextureIndex; + uint TextureIndex; uint VertexOffset; // Base vertex for indexed drawing with bindless buffers uint _Padding; // Padding for alignment float2 Scale; // 2D scale factor float2 Translate; // 2D translation + float2 _Padding2; // Explicit padding to align LightDirection to 16 bytes float3 LightDirection; // Normalized, world-space float LightPad; diff --git a/Assets/source/Triangle.vert.hlsl b/Assets/source/Triangle.vert.hlsl index eb1c49b..3984130 100644 --- a/Assets/source/Triangle.vert.hlsl +++ b/Assets/source/Triangle.vert.hlsl @@ -21,6 +21,10 @@ Output main(uint vertexIndex : SV_VertexID) float3 normal = asfloat(buffer.Load3(offset + 12)); float4 col = asfloat(buffer.Load4(offset + 24)); + // Fetch Model Matrix + StructuredBuffer transformsBuffer = ResourceDescriptorHeap[TransformsBufferIndex]; + float4x4 Model = transformsBuffer[MeshIndex].Model; + float4 worldPos = mul(Model, float4(pos, 1.0f)); output.Position = mul(ViewProjection, worldPos); output.Color = col; diff --git a/Juliet/include/Core/Math/Matrix.h b/Juliet/include/Core/Math/Matrix.h index 4c7d876..79f3d85 100644 --- a/Juliet/include/Core/Math/Matrix.h +++ b/Juliet/include/Core/Math/Matrix.h @@ -45,6 +45,15 @@ namespace Juliet return result; } + [[nodiscard]] inline Matrix MatrixScale(float x, float y, float z) + { + Matrix result = MatrixIdentity(); + result.m[0][0] = x; + result.m[1][1] = y; + result.m[2][2] = z; + return result; + } + [[nodiscard]] inline Matrix MatrixRotationX(float radians) { float c = cosf(radians); diff --git a/Juliet/include/Graphics/PushConstants.h b/Juliet/include/Graphics/PushConstants.h index 5a3fa04..740ad74 100644 --- a/Juliet/include/Graphics/PushConstants.h +++ b/Juliet/include/Graphics/PushConstants.h @@ -9,13 +9,15 @@ namespace Juliet struct PushData { Matrix ViewProjection; - Matrix Model; + uint32 MeshIndex; + uint32 TransformsBufferIndex; uint32 BufferIndex; uint32 TextureIndex; uint32 VertexOffset; uint32 Padding; float Scale[2]; float Translate[2]; + float Padding2[2]; Vector3 LightDirection; float LightPad; diff --git a/Juliet/src/Graphics/DebugDisplayRenderer.cpp b/Juliet/src/Graphics/DebugDisplayRenderer.cpp index 6484971..bd56e5d 100644 --- a/Juliet/src/Graphics/DebugDisplayRenderer.cpp +++ b/Juliet/src/Graphics/DebugDisplayRenderer.cpp @@ -300,12 +300,11 @@ namespace Juliet // Render depth-tested primitives (vertices at offset 0 in buffer) if (g_DebugState.DepthTestedVertexCount > 0 && g_DebugState.DepthTestedPipeline && g_DebugState.VertexBuffer) { - BindGraphicsPipeline(renderPass, g_DebugState.DepthTestedPipeline); - - // Pack VP matrix + Model (identity for debug) + buffer index into push constants + // Pack VP matrix + buffer index into push constants PushData pushData = {}; pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera); - pushData.Model = MatrixIdentity(); + pushData.MeshIndex = 0; + pushData.TransformsBufferIndex = 0; // Not used by debug shader but layout must match pushData.BufferIndex = bufferIndex; pushData.TextureIndex = 0; pushData.VertexOffset = 0; // Depth-tested vertices start at 0 @@ -329,10 +328,11 @@ namespace Juliet { BindGraphicsPipeline(renderPass, g_DebugState.OverlayPipeline); - // Pack VP matrix + Model (identity for debug) + buffer index into push constants + // Pack VP matrix + buffer index into push constants PushData pushData = {}; pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera); - pushData.Model = MatrixIdentity(); + pushData.MeshIndex = 0; + pushData.TransformsBufferIndex = 0; pushData.BufferIndex = bufferIndex; pushData.TextureIndex = 0; pushData.VertexOffset = kMaxDebugVertices / 2; // Overlay vertices start at half diff --git a/Juliet/src/Graphics/MeshRenderer.cpp b/Juliet/src/Graphics/MeshRenderer.cpp index 2aa73ee..b56435a 100644 --- a/Juliet/src/Graphics/MeshRenderer.cpp +++ b/Juliet/src/Graphics/MeshRenderer.cpp @@ -12,7 +12,26 @@ namespace Juliet { namespace { - MeshRenderer g_MeshRenderer; + struct MeshRendererState + { + GraphicsDevice* Device = nullptr; + GraphicsPipeline* Pipeline = nullptr; + GraphicsBuffer* VertexBuffer = nullptr; + GraphicsBuffer* IndexBuffer = nullptr; + GraphicsBuffer* LightsBuffer = nullptr; + GraphicsBuffer* TransformsBuffer = nullptr; + GraphicsTransferBuffer* LoadCopyBuffer = nullptr; + + VectorArena Meshes; + VectorArena Vertices; + VectorArena Indices; + VectorArena PointLights; + + PointLight* MappedLights = nullptr; + Matrix* MappedTransforms = nullptr; + }; + + MeshRendererState g_MeshRenderer; } // namespace void InitializeMeshRenderer(NonNullPtr arena) @@ -92,6 +111,18 @@ namespace Juliet g_MeshRenderer.MappedLights = static_cast(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.LightsBuffer)); Assert(g_MeshRenderer.MappedLights != nullptr); + // Transforms Buffer + BufferCreateInfo transformsBufferCI = {}; + transformsBufferCI.Size = 10000 * sizeof(Matrix); // Max 10000 meshes for now + transformsBufferCI.Stride = sizeof(Matrix); + transformsBufferCI.Usage = BufferUsage::StructuredBuffer; + transformsBufferCI.IsDynamic = true; + g_MeshRenderer.TransformsBuffer = CreateGraphicsBuffer(graphicsDevice, transformsBufferCI); + Assert(g_MeshRenderer.TransformsBuffer != nullptr); + g_MeshRenderer.MappedTransforms = + static_cast(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.TransformsBuffer)); + Assert(g_MeshRenderer.MappedTransforms != nullptr); + // Sync existing lights that might have been added before graphics initialization for (index_t i = 0; i < g_MeshRenderer.PointLights.Count; ++i) { @@ -130,6 +161,14 @@ namespace Juliet { UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); + g_MeshRenderer.LightsBuffer = nullptr; + } + + if (g_MeshRenderer.TransformsBuffer) + { + UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer); + DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer); + g_MeshRenderer.TransformsBuffer = nullptr; } } @@ -214,15 +253,24 @@ namespace Juliet uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer); uint32 lightDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); - pushData.BufferIndex = vertexDescriptorIndex; - pushData.LightBufferIndex = lightDescriptorIndex; - pushData.ActiveLightCount = static_cast(g_MeshRenderer.PointLights.Count); + uint32 transformsDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer); + + pushData.BufferIndex = vertexDescriptorIndex; + pushData.LightBufferIndex = lightDescriptorIndex; + pushData.TransformsBufferIndex = transformsDescriptorIndex; + pushData.ActiveLightCount = static_cast(g_MeshRenderer.PointLights.Count); SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0); + uint32 meshIndex = 0; for (Mesh& mesh : g_MeshRenderer.Meshes) { - pushData.Model = mesh.Transform; + if (g_MeshRenderer.MappedTransforms) + { + g_MeshRenderer.MappedTransforms[meshIndex] = mesh.Transform; + } + + pushData.MeshIndex = meshIndex; pushData.TextureIndex = 0; pushData.VertexOffset = static_cast(mesh.VertexOffset); pushData.Padding = 0; @@ -233,6 +281,7 @@ namespace Juliet SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); DrawIndexedPrimitives(pass, static_cast(mesh.IndexCount), 1, static_cast(mesh.IndexOffset), static_cast(mesh.VertexOffset), 0); + meshIndex++; } } @@ -278,40 +327,40 @@ namespace Juliet Mesh result = {}; constexpr Vertex vertexData[] = { // Front Face (Z = -0.5f) — Red - { { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, - { { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, - { { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, + { { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Back Face (Z = 0.5f) — Green - { { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, - { { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, - { { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, + { { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Top Face (Y = 0.5f) — Blue - { { -0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, - { { 0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, - { { 0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, + { { -0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Bottom Face (Y = -0.5f) — Yellow - { { -0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, - { { -0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, + { { -0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Right Face (X = 0.5f) — Cyan - { { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, - { { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, - { { 0.5f, -0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, - { { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, + { { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Left Face (X = -0.5f) — Magenta - { { -0.5f, 0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, 0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, -0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, -0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } } + { { -0.5f, 0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, 0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } } }; constexpr size_t cubeVertexCount = ArraySize(vertexData); result.VertexCount = cubeVertexCount; diff --git a/Juliet/src/Graphics/SkyboxRenderer.cpp b/Juliet/src/Graphics/SkyboxRenderer.cpp index 70b1f5c..052ddb7 100644 --- a/Juliet/src/Graphics/SkyboxRenderer.cpp +++ b/Juliet/src/Graphics/SkyboxRenderer.cpp @@ -82,9 +82,11 @@ namespace Juliet return; } - PushData pushData = {}; - pushData.ViewProjection = viewProjection; - pushData.Model = MatrixIdentity(); + PushData pushData = {}; + pushData.ViewProjection = viewProjection; + pushData.MeshIndex = 0; + pushData.TransformsBufferIndex = 0; + pushData.BufferIndex = 0; BindGraphicsPipeline(pass, g_SkyboxRenderer.Pipeline); SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); diff --git a/JulietApp/main.cpp b/JulietApp/main.cpp index 8eec4a9..3fe9816 100644 --- a/JulietApp/main.cpp +++ b/JulietApp/main.cpp @@ -38,6 +38,18 @@ #endif static bool ShowMemoryDebugger = false; +static bool animateCubes = true; +static bool animateLights = true; +static bool animateCamera = true; + +static bool freeCameraMode = false; +static float camYaw = 0.0f; +static float camPitch = 0.0f; +static Juliet::Vector3 camPos = { 25.0f, 0.0f, 12.5f }; + +static float animateCubesTime = 0.0f; +static float animateLightsTime = 0.0f; +static float animateCameraTime = 0.0f; // TODO : Replace with message box from framework + call main and not winmain + subsystem // TODO : Think how to do the draw pipeline. @@ -226,6 +238,7 @@ void JulietApplication::Update() bool reloadShaders = false; static bool reloadShadersDebounce = false; + static bool f1Debounce = false; SystemEvent evt; while (GetEvent(evt)) @@ -249,18 +262,112 @@ void JulietApplication::Update() { reloadShadersDebounce = false; } + + if (evt.Type == EventType::Mouse_Move && freeCameraMode) + { + float sensitivity = 0.005f; + camYaw += evt.Data.MouseMovement.X_Displacement * sensitivity; + camPitch -= evt.Data.MouseMovement.Y_Displacement * sensitivity; + + // Limit pitch to avoid flipping + if (camPitch > 1.5f) camPitch = 1.5f; + if (camPitch < -1.5f) camPitch = -1.5f; + } } + if (IsKeyDown(ScanCode::F1)) + { + if (!f1Debounce) + { + freeCameraMode = !freeCameraMode; + f1Debounce = true; + } + } + else + { + f1Debounce = false; + } + + if (freeCameraMode) + { + float speed = 10.0f * deltaTime; + if ((GetKeyModState() & KeyMod::Shift) != KeyMod::None) + { + speed *= 3.0f; + } + + Vector3 forward = { cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) }; + Vector3 right = { cosf(camYaw + 1.5708f), sinf(camYaw + 1.5708f), 0.0f }; + Vector3 up = { 0.0f, 0.0f, 1.0f }; + + if (IsKeyDown(ScanCode::W)) camPos = camPos + forward * speed; + if (IsKeyDown(ScanCode::S)) camPos = camPos - forward * speed; + if (IsKeyDown(ScanCode::D)) camPos = camPos + right * speed; + if (IsKeyDown(ScanCode::A)) camPos = camPos - right * speed; + if (IsKeyDown(ScanCode::E)) camPos = camPos + up * speed; + if (IsKeyDown(ScanCode::Q)) camPos = camPos - up * speed; + } + + if (animateCubes) animateCubesTime += deltaTime; + if (animateLights) animateLightsTime += deltaTime; + if (animateCamera) animateCameraTime += deltaTime; + +#ifdef JULIET_ENABLE_IMGUI + ImGui::Begin("Debug Controls"); + ImGui::Checkbox("Animate Cubes", &animateCubes); + ImGui::Checkbox("Animate Lights", &animateLights); + ImGui::Checkbox("Animate Camera", &animateCamera); + ImGui::End(); +#endif + ArenaClear(GameScratchArena); - Vector3 redLightPos{ cosf(CameraTime * 2.0f) * 5.0f, sinf(CameraTime * 2.0f) * 5.0f, 2.0f }; + Vector3 redLightPos = { 5.0f, 5.0f, 2.0f }; + Vector3 blueLightPos = { -5.0f, 0.0f, 2.0f }; + + if (animateLights || animateLightsTime > 0.0f) + { + redLightPos = { cosf(animateLightsTime * 2.0f) * 5.0f, sinf(animateLightsTime * 2.0f) * 5.0f, 2.0f }; + blueLightPos = { -5.0f, cosf(animateLightsTime) * 3.0f, 2.0f }; + } + SetPointLightPosition(RedLightID, redLightPos); - Vector3 blueLightPos{ -5.0f, cosf(CameraTime) * 3.0f, 2.0f }; SetPointLightPosition(BlueLightID, blueLightPos); -#ifdef JULIET_ENABLE_IMGUI - ImGui::ShowDemoWindow(); -#endif + // Animate the 100 cubes (10x10 grid) + constexpr int kGridSize = 10; + constexpr float kSpacing = 2.5f; + constexpr float kOffset = (kGridSize - 1) * kSpacing * 0.5f; + + for (int row = 0; row < kGridSize; ++row) + { + for (int col = 0; col < kGridSize; ++col) + { + MeshID cube = static_cast(row * kGridSize + col); // Assuming they were added first + float x = static_cast(col) * kSpacing - kOffset; + float y = static_cast(row) * kSpacing - kOffset; + + float seed = static_cast(cube); + float timeZ = animateCubesTime * 2.0f + seed * 0.5f; + float z = 0.0f; + + float scaleF = 1.0f; + Matrix rotation = MatrixIdentity(); + + if (animateCubes || animateCubesTime > 0.0f) + { + z = sinf(timeZ) * 1.5f; // Oscillate up and down + scaleF = 1.0f + sinf(animateCubesTime * 1.5f + seed) * 0.3f; // Pulse scale + rotation = MatrixRotation(animateCubesTime * 1.2f + seed * 0.73f, animateCubesTime * 0.8f + seed * 1.17f, + animateCubesTime * 0.5f + seed * 0.53f); + } + Matrix scale = MatrixScale(scaleF, scaleF, scaleF); + + SetMeshTransform(cube, MatrixTranslation(x, y, z) * rotation * scale); + } + } + + DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false); DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true); @@ -358,24 +465,51 @@ DepthStencilTargetInfo* JulietApplication::GetDepthTargetInfo() Camera JulietApplication::GetDebugCamera() { - float time = CameraTime; - - float orbitSpeed = 0.5f; - float currentOrbitTime = time * orbitSpeed; + if (freeCameraMode) + { + Camera cam = {}; + cam.Position = camPos; + cam.Target = camPos + Vector3{ cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) }; + cam.Up = { 0.0f, 0.0f, 1.0f }; + cam.FOV = 1.047f; + cam.AspectRatio = 1200.0f / 800.0f; + cam.NearPlane = 0.1f; + cam.FarPlane = 1000.0f; + return cam; + } // --- Adjusted for 1-Meter Scale --- float baseRadius = 25.0f; // Increased to see 10x10 cube grid float radius = baseRadius; - //* Uncomment for active zoom - float zoomAmplitude = 15.0f; - float zoomSpeed = 0.5f; - radius = baseRadius + (sinf(time * zoomSpeed) * zoomAmplitude); - //*/ + + if (animateCamera || animateCameraTime > 0.0f) + { + float orbitSpeed = 0.5f; + float currentOrbitTime = animateCameraTime * orbitSpeed; + + float zoomAmplitude = 15.0f; + float zoomSpeed = 0.5f; + radius = baseRadius + (sinf(animateCameraTime * zoomSpeed) * zoomAmplitude); + + float zHeight = radius * 0.5f; // Keep a nice downward viewing angle + + Camera cam = {}; + cam.Position = { cosf(currentOrbitTime) * radius, sinf(currentOrbitTime) * radius, zHeight }; + cam.Target = { 0.0f, 0.0f, 0.0f }; + cam.Up = { 0.0f, 0.0f, 1.0f }; + cam.FOV = 1.047f; + cam.AspectRatio = 1200.0f / 800.0f; + cam.NearPlane = 0.1f; + cam.FarPlane = 1000.0f; + + return cam; + } + float zHeight = radius * 0.5f; // Keep a nice downward viewing angle Camera cam = {}; - cam.Position = { cosf(currentOrbitTime) * radius, sinf(currentOrbitTime) * radius, zHeight }; + cam.Position = { radius, 0.0f, zHeight }; cam.Target = { 0.0f, 0.0f, 0.0f }; cam.Up = { 0.0f, 0.0f, 1.0f }; cam.FOV = 1.047f;