diff --git a/Assets/compiled/Debug.vert.dxil b/Assets/compiled/Debug.vert.dxil index 6175834..add627d 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 6334fb4..d602062 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 ab4d30b..d980a68 100644 Binary files a/Assets/compiled/ImGui.vert.dxil and b/Assets/compiled/ImGui.vert.dxil differ diff --git a/Assets/compiled/Triangle.vert.dxil b/Assets/compiled/Triangle.vert.dxil index 9416589..7e88767 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 07c0f32..e0fcf7e 100644 --- a/Assets/source/RootConstants.hlsl +++ b/Assets/source/RootConstants.hlsl @@ -4,6 +4,7 @@ cbuffer RootConstants : register(b0, space0) { row_major float4x4 ViewProjection; + row_major float4x4 Model; uint BufferIndex; uint TextureIndex; uint VertexOffset; // Base vertex for indexed drawing with bindless buffers diff --git a/Assets/source/Triangle.vert.hlsl b/Assets/source/Triangle.vert.hlsl index 79c1663..705adce 100644 --- a/Assets/source/Triangle.vert.hlsl +++ b/Assets/source/Triangle.vert.hlsl @@ -19,7 +19,7 @@ Output main(uint vertexIndex : SV_VertexID) float4 col = asfloat(buffer.Load4(offset + 12)); //output.Position = float4(pos, 1.0f); - output.Position = mul(ViewProjection, float4(pos, 1.0f)); + output.Position = mul(ViewProjection, mul(Model, float4(pos, 1.0f))); output.Color = col; return output; } diff --git a/Juliet/include/Core/Math/Matrix.h b/Juliet/include/Core/Math/Matrix.h index 36e7d97..569be81 100644 --- a/Juliet/include/Core/Math/Matrix.h +++ b/Juliet/include/Core/Math/Matrix.h @@ -8,33 +8,42 @@ namespace Juliet struct Matrix { float m[4][4]; + }; - static Matrix Identity() - { - Matrix result = {}; - result.m[0][0] = 1.0f; - result.m[1][1] = 1.0f; - result.m[2][2] = 1.0f; - result.m[3][3] = 1.0f; - return result; - } + [[nodiscard]] inline Matrix MatrixIdentity() + { + Matrix result = {}; + result.m[0][0] = 1.0f; + result.m[1][1] = 1.0f; + result.m[2][2] = 1.0f; + result.m[3][3] = 1.0f; + return result; + } - Matrix operator*(const Matrix& rhs) const + [[nodiscard]] inline Matrix MatrixTranslation(float x, float y, float z) + { + Matrix result = MatrixIdentity(); + result.m[0][3] = x; + result.m[1][3] = y; + result.m[2][3] = z; + return result; + } + + [[nodiscard]] inline Matrix operator*(const Matrix& lhs, const Matrix& rhs) + { + Matrix result = {}; + for (int i = 0; i < 4; ++i) { - Matrix result = {}; - for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) { - for (int j = 0; j < 4; ++j) + for (int k = 0; k < 4; ++k) { - for (int k = 0; k < 4; ++k) - { - result.m[i][j] += m[i][k] * rhs.m[k][j]; - } + result.m[i][j] += lhs.m[i][k] * rhs.m[k][j]; } } - return result; } - }; + return result; + } inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { diff --git a/Juliet/include/Graphics/Mesh.h b/Juliet/include/Graphics/Mesh.h index 58ffa56..6528817 100644 --- a/Juliet/include/Graphics/Mesh.h +++ b/Juliet/include/Graphics/Mesh.h @@ -2,6 +2,7 @@ #include #include +#include #include namespace Juliet @@ -16,5 +17,7 @@ namespace Juliet index_t VertexOffset; index_t IndexOffset; + + Matrix Transform = MatrixIdentity(); }; } // namespace Juliet diff --git a/Juliet/include/Graphics/MeshRenderer.h b/Juliet/include/Graphics/MeshRenderer.h index 769001f..9ead3d3 100644 --- a/Juliet/include/Graphics/MeshRenderer.h +++ b/Juliet/include/Graphics/MeshRenderer.h @@ -43,6 +43,7 @@ namespace Juliet struct PushData { Matrix ViewProjection; + Matrix Model; uint32 BufferIndex; }; @@ -55,6 +56,7 @@ namespace Juliet // Utils [[nodiscard]] JULIET_API MeshID AddCube(); [[nodiscard]] JULIET_API MeshID AddQuad(); + JULIET_API void SetMeshTransform(MeshID id, const Matrix& transform); #if ALLOW_SHADER_HOT_RELOAD JULIET_API void ReloadMeshRendererShaders(); diff --git a/Juliet/src/Core/HAL/Display/Display.cpp b/Juliet/src/Core/HAL/Display/Display.cpp index 2142fc2..c81287d 100644 --- a/Juliet/src/Core/HAL/Display/Display.cpp +++ b/Juliet/src/Core/HAL/Display/Display.cpp @@ -123,7 +123,7 @@ namespace Juliet { // Find and destroy VectorArena& windows = g_CurrentDisplayDevice->Windows; - for (index_t idx = windows.Size() - 1; idx != 0; --idx) + for (index_t idx = windows.Size(); idx-- > 0;) { Window& windowRef = windows[idx]; if (windowRef.ID == window->ID) diff --git a/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp b/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp index 29a3ffa..a493d4b 100644 --- a/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp +++ b/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp @@ -36,7 +36,7 @@ namespace Juliet::Win32 device->PumpEvents = PumpEvents; - device->Windows.Create(JULIET_DEBUG_ONLY("Display Windows")); + device->Windows.Create(arena JULIET_DEBUG_PARAM("Display Windows")); return device; } diff --git a/Juliet/src/Core/Memory/MemoryArena.cpp b/Juliet/src/Core/Memory/MemoryArena.cpp index 9941f47..ebc59e8 100644 --- a/Juliet/src/Core/Memory/MemoryArena.cpp +++ b/Juliet/src/Core/Memory/MemoryArena.cpp @@ -75,12 +75,12 @@ namespace Juliet void ArenaRelease(NonNullPtr arena) { - JULIET_DEBUG_ONLY(DebugUnregisterArena(arena);) - + // Release active blocks (Current chain) for (Arena *node = arena->Current, *previous = nullptr; node != nullptr; node = previous) { previous = node->Previous; + JULIET_DEBUG_ONLY(DebugUnregisterArena(node);) JULIET_DEBUG_ONLY(DebugArenaFreeBlock(node);) Memory::OS_Release(node, node->Reserved); diff --git a/Juliet/src/Core/Memory/MemoryArenaDebug.cpp b/Juliet/src/Core/Memory/MemoryArenaDebug.cpp index b4b8060..4822079 100644 --- a/Juliet/src/Core/Memory/MemoryArenaDebug.cpp +++ b/Juliet/src/Core/Memory/MemoryArenaDebug.cpp @@ -68,6 +68,8 @@ namespace Juliet { arena->GlobalNext->GlobalPrev = arena->GlobalPrev; } + arena->GlobalPrev = nullptr; + arena->GlobalNext = nullptr; } void DebugArenaSetDebugName(NonNullPtr arena, const char* name) diff --git a/Juliet/src/Graphics/DebugDisplayRenderer.cpp b/Juliet/src/Graphics/DebugDisplayRenderer.cpp index af2c337..464c4d4 100644 --- a/Juliet/src/Graphics/DebugDisplayRenderer.cpp +++ b/Juliet/src/Graphics/DebugDisplayRenderer.cpp @@ -300,15 +300,17 @@ namespace Juliet { BindGraphicsPipeline(renderPass, g_DebugState.DepthTestedPipeline); - // Pack VP matrix + buffer index into push constants + // Pack VP matrix + Model (identity for debug) + buffer index into push constants struct { Matrix vp; + Matrix model; uint32 bufferIndex; uint32 vertexOffset; // Offset in vertices (not bytes) uint32 padding[2]; } pushData; pushData.vp = Camera_GetViewProjectionMatrix(camera); + pushData.model = MatrixIdentity(); pushData.bufferIndex = bufferIndex; pushData.vertexOffset = 0; // Depth-tested vertices start at 0 SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / sizeof(uint32), &pushData); @@ -321,15 +323,17 @@ namespace Juliet { BindGraphicsPipeline(renderPass, g_DebugState.OverlayPipeline); - // Pack VP matrix + buffer index into push constants + // Pack VP matrix + Model (identity for debug) + buffer index into push constants struct { Matrix vp; + Matrix model; uint32 bufferIndex; uint32 vertexOffset; // Offset in vertices (not bytes) uint32 padding[2]; } pushData; pushData.vp = Camera_GetViewProjectionMatrix(camera); + pushData.model = MatrixIdentity(); pushData.bufferIndex = bufferIndex; pushData.vertexOffset = kMaxDebugVertices / 2; // Overlay vertices start at half SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / sizeof(uint32), &pushData); diff --git a/Juliet/src/Graphics/MeshRenderer.cpp b/Juliet/src/Graphics/MeshRenderer.cpp index 9d168c2..1785b28 100644 --- a/Juliet/src/Graphics/MeshRenderer.cpp +++ b/Juliet/src/Graphics/MeshRenderer.cpp @@ -187,12 +187,13 @@ namespace Juliet uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer); pushData.BufferIndex = vertexDescriptorIndex; - SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0); for (Mesh& mesh : g_MeshRenderer.Meshes) { + pushData.Model = mesh.Transform; + 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); } @@ -292,6 +293,11 @@ namespace Juliet return g_MeshRenderer.Meshes.Count - 1; } + void SetMeshTransform(MeshID id, const Matrix& transform) + { + Assert(id < static_cast(g_MeshRenderer.Meshes.Count), "Invalid MeshID"); + g_MeshRenderer.Meshes.Data[id].Transform = transform; + } #if ALLOW_SHADER_HOT_RELOAD void ReloadMeshRendererShaders() { diff --git a/JulietApp/main.cpp b/JulietApp/main.cpp index 0fcac63..f221c93 100644 --- a/JulietApp/main.cpp +++ b/JulietApp/main.cpp @@ -109,7 +109,20 @@ void JulietApplication::Init() Running = false; } - std::ignore = AddCube(); + 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 = AddCube(); + float x = static_cast(col) * kSpacing - kOffset; + float y = static_cast(row) * kSpacing - kOffset; + SetMeshTransform(cube, MatrixTranslation(x, y, 0.0f)); + } + } CommandList* loadCmd = AcquireCommandList(GraphicsDevice); LoadMeshesOnGPU(loadCmd); @@ -275,8 +288,6 @@ void JulietApplication::OnRender(RenderPass* pass, CommandList* cmd) pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera()); RenderMeshes(pass, cmd, pushData); - - // SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); } ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture) @@ -308,14 +319,14 @@ Camera JulietApplication::GetDebugCamera() float currentOrbitTime = time * orbitSpeed; // --- Adjusted for 1-Meter Scale --- - float baseRadius = 2.5f; // Hover 2.5 meters away (down from 15.0f) + float baseRadius = 25.0f; // Increased to see 10x10 cube grid float radius = baseRadius; - /* Uncomment for active zoom - float zoomAmplitude = 1.0f; // Oscillate between 1.5m and 3.5m away + //* Uncomment for active zoom + float zoomAmplitude = 10.0f; // Oscillate between 1.5m and 3.5m away float zoomSpeed = 0.8f; - radius = baseRadius + (sinf(time * zoomSpeed) * zoomAmplitude); - */ + radius = baseRadius + (sinf(time * zoomSpeed) * zoomAmplitude); + //*/ float zHeight = radius * 0.5f; // Keep a nice downward viewing angle Camera cam = {};