diff --git a/.gitignore b/.gitignore
index 6c6d631..752d1e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@
.idea/
.vs/
[Ii]ntermediate/
+[sS]hip/
# Logs
build_*.txt
@@ -51,3 +52,5 @@ launch_*.txt
*.out
*.app
+misc/agent_error.log
+misc/agent_output_ship.log
diff --git a/AgentData/lighting_and_skybox_plan.md b/AgentData/lighting_and_skybox_plan.md
new file mode 100644
index 0000000..653a631
--- /dev/null
+++ b/AgentData/lighting_and_skybox_plan.md
@@ -0,0 +1,233 @@
+# Lighting & Skybox Plan
+
+## Current State
+
+| Item | Current |
+|------|---------|
+| Vertex format | `float3 Position` + `float4 Color` (28 bytes, no normals) |
+| Vertex shader | [Triangle.vert.hlsl](file:///w:/Classified/Juliet/Assets/source/Triangle.vert.hlsl) — bindless buffer read, `mul(VP, mul(Model, pos))` |
+| Fragment shader | [SolidColor.frag.hlsl](file:///w:/Classified/Juliet/Assets/source/SolidColor.frag.hlsl) — passthrough `return Color` |
+| Push constants | `ViewProjection` + `Model` + `BufferIndex` + extras |
+| Texturing | None — no sampler usage, no texture reads |
+
+---
+
+## Phase 1: Add Normals to Vertex Data
+
+Lighting requires normals. This is the foundation for everything else.
+
+### Vertex Format Change
+
+```diff
+ struct Vertex
+ {
+ float Position[3];
++ float Normal[3];
+ float Color[4];
+ };
+```
+
+- **Stride**: 28 → 40 bytes
+- Update `Triangle.vert.hlsl` stride constant: `uint stride = 40;`
+- Load normal after position: `float3 normal = asfloat(buffer.Load3(offset + 12));`
+- Load color shifts to: `float4 col = asfloat(buffer.Load4(offset + 24));`
+
+### Files to modify
+
+| File | Change |
+|------|--------|
+| [VertexData.h](file:///w:/Classified/Juliet/Juliet/include/Graphics/VertexData.h) | Add `float Normal[3]` to `Vertex` |
+| [MeshRenderer.cpp](file:///w:/Classified/Juliet/Juliet/src/Graphics/MeshRenderer.cpp) | Update `AddCube()` to include per-face normals |
+| [Triangle.vert.hlsl](file:///w:/Classified/Juliet/Assets/source/Triangle.vert.hlsl) | Update stride, load normal, pass to fragment |
+
+---
+
+## Phase 2: Basic Directional Light (Diffuse)
+
+Simple single directional light with diffuse (Lambert) shading.
+
+### Approach: Push light data through RootConstants
+
+Add light direction and color to `RootConstants.hlsl` and the C++ `PushData`:
+
+```hlsl
+// RootConstants.hlsl additions
+float3 LightDirection; // Normalized, world-space
+float _LightPad;
+float3 LightColor;
+float AmbientIntensity;
+```
+
+```cpp
+// PushData additions
+Vector3 LightDirection;
+float _LightPad;
+Vector3 LightColor;
+float AmbientIntensity;
+```
+
+### Shader Changes
+
+**Vertex shader** — transform normal to world space and pass it to fragment:
+
+```hlsl
+// Triangle.vert.hlsl output struct
+struct Output
+{
+ float4 Color : TEXCOORD0;
+ float3 WorldNormal : TEXCOORD1;
+ float4 Position : SV_Position;
+};
+
+// In main():
+float3 worldNormal = mul((float3x3)Model, normal);
+output.WorldNormal = worldNormal;
+```
+
+> [!NOTE]
+> Using `(float3x3)Model` for normal transform is only correct for uniform-scale transforms. For non-uniform scale, you'd need the inverse-transpose. Fine for now with translation-only transforms.
+
+**Fragment shader** — apply Lambert diffuse:
+
+```hlsl
+// SolidColor.frag.hlsl → rename to Lit.frag.hlsl
+#include "RootConstants.hlsl"
+
+float4 main(float4 Color : TEXCOORD0, float3 WorldNormal : TEXCOORD1) : SV_Target0
+{
+ float3 N = normalize(WorldNormal);
+ float NdotL = saturate(dot(N, -LightDirection));
+ float3 diffuse = Color.rgb * LightColor * NdotL;
+ float3 ambient = Color.rgb * AmbientIntensity;
+ return float4(diffuse + ambient, Color.a);
+}
+```
+
+### Files to modify
+
+| File | Change |
+|------|--------|
+| [RootConstants.hlsl](file:///w:/Classified/Juliet/Assets/source/RootConstants.hlsl) | Add light params |
+| [MeshRenderer.h](file:///w:/Classified/Juliet/Juliet/include/Graphics/MeshRenderer.h) | Add light params to `PushData` |
+| [Triangle.vert.hlsl](file:///w:/Classified/Juliet/Assets/source/Triangle.vert.hlsl) | Pass world normal to fragment |
+| [SolidColor.frag.hlsl](file:///w:/Classified/Juliet/Assets/source/SolidColor.frag.hlsl) | Lambert diffuse + ambient |
+| [DebugDisplayRenderer.cpp](file:///w:/Classified/Juliet/Juliet/src/Graphics/DebugDisplayRenderer.cpp) | Update push data struct to match new layout |
+| [main.cpp](file:///w:/Classified/Juliet/JulietApp/main.cpp) | Set `LightDirection`, `LightColor`, `AmbientIntensity` |
+
+---
+
+## Phase 3: Skybox
+
+A skybox renders a cubemap texture behind all geometry, giving the scene a background.
+
+### Approach: Fullscreen-triangle with inverse VP
+
+Render a fullscreen triangle as the very last thing (or first with depth write off), sample a cubemap using the camera view direction reconstructed from screen coordinates.
+
+### New Assets
+
+- **Skybox cubemap texture** — a `.dds` or 6 `.png` face images loaded as a `TextureCube`
+- **New shaders**: `Skybox.vert.hlsl` + `Skybox.frag.hlsl`
+
+### Shader Design
+
+**Vertex shader** — fullscreen triangle using `SV_VertexID`:
+
+```hlsl
+// Skybox.vert.hlsl
+#include "RootConstants.hlsl"
+
+struct Output
+{
+ float3 ViewDir : TEXCOORD0;
+ float4 Position : SV_Position;
+};
+
+Output main(uint vertexID : SV_VertexID)
+{
+ Output output;
+
+ // Fullscreen triangle
+ float2 uv = float2((vertexID << 1) & 2, vertexID & 2);
+ float4 clipPos = float4(uv * 2.0 - 1.0, 1.0, 1.0);
+ clipPos.y = -clipPos.y;
+
+ output.Position = clipPos;
+
+ // Reconstruct view direction from clip space
+ // InverseViewProjection needs to be added to RootConstants
+ float4 worldPos = mul(InverseViewProjection, clipPos);
+ output.ViewDir = worldPos.xyz / worldPos.w;
+
+ return output;
+}
+```
+
+**Fragment shader** — sample cubemap:
+
+```hlsl
+// Skybox.frag.hlsl
+#include "RootConstants.hlsl"
+
+float4 main(float3 ViewDir : TEXCOORD0) : SV_Target0
+{
+ TextureCube skybox = ResourceDescriptorHeap[TextureIndex];
+ SamplerState samp = SamplerDescriptorHeap[0]; // Linear clamp
+ return skybox.Sample(samp, normalize(ViewDir));
+}
+```
+
+### Pipeline Requirements
+
+| Setting | Value |
+|---------|-------|
+| Depth write | **Off** (skybox is infinitely far) |
+| Depth test | **LessEqual** or **Off** (render behind everything) |
+| Cull mode | **None** (fullscreen triangle) |
+| Draw call | `Draw(3, 0)` — no vertex buffer needed |
+
+### New C++ Components
+
+1. **Cubemap loading** — need to create `TextureCube` from 6 face images or a `.dds` cubemap file
+2. **Skybox pipeline** — new `GraphicsPipeline` with the skybox shaders and the pipeline settings above
+3. **Sampler** — need at least one linear sampler in the sampler heap (may already exist for ImGui)
+4. **`InverseViewProjection`** — add to `RootConstants` and compute in C++ via a `MatrixInverse` function
+
+> [!IMPORTANT]
+> `MatrixInverse` needs to be implemented in `Matrix.h`. This is a non-trivial 4×4 matrix inversion (adjugate/determinant method or Gauss-Jordan).
+
+### Files to modify/create
+
+| File | Change |
+|------|--------|
+| [NEW] `Skybox.vert.hlsl` | Fullscreen triangle + view direction |
+| [NEW] `Skybox.frag.hlsl` | Cubemap sample |
+| [RootConstants.hlsl](file:///w:/Classified/Juliet/Assets/source/RootConstants.hlsl) | Add `InverseViewProjection` |
+| [Matrix.h](file:///w:/Classified/Juliet/Juliet/include/Core/Math/Matrix.h) | Add `MatrixInverse()` |
+| [MeshRenderer.h](file:///w:/Classified/Juliet/Juliet/include/Graphics/MeshRenderer.h) | Add `InverseViewProjection` to `PushData` |
+| [main.cpp](file:///w:/Classified/Juliet/JulietApp/main.cpp) | Create skybox pipeline, load cubemap, render skybox |
+
+---
+
+## Recommended Implementation Order
+
+```mermaid
+graph LR
+ A["Phase 1
Add Normals"] --> B["Phase 2
Directional Light"]
+ B --> C["Phase 3
Skybox"]
+```
+
+1. **Phase 1** (normals) is the smallest and unblocks Phase 2
+2. **Phase 2** (lighting) gives the cubes visible 3D depth immediately
+3. **Phase 3** (skybox) is independent of lighting but benefits from having `MatrixInverse` and sampler infrastructure
+
+> [!TIP]
+> Phases 1+2 together are a single session of work (~8 files). Phase 3 is larger due to cubemap loading and new pipeline creation.
+
+---
+
+## Open Questions
+
+1. **Cubemap source** — procedural gradient skybox (no asset needed) vs actual HDR cubemap `.dds` file?
+2. **Sampler heap** — does the engine already have a linear sampler registered, or does one need to be created?
+3. **Specular** — want Blinn-Phong specular in Phase 2, or just diffuse + ambient for now?
diff --git a/Juliet/Juliet.bff b/Juliet/Juliet.bff
index 9edae90..4cb2e6f 100644
--- a/Juliet/Juliet.bff
+++ b/Juliet/Juliet.bff
@@ -47,8 +47,11 @@
// --- DLL BUILD ---
DLL( '$ProjectName$-Lib-$Platform$-$BuildConfigName$' )
{
- .Libraries = { '$ProjectName$-Objs-$Platform$-$BuildConfigName$',
- 'ImGui-Lib-$Platform$-$BuildConfigName$' }
+ .Libraries = { '$ProjectName$-Objs-$Platform$-$BuildConfigName$' }
+ If ( .BuildConfigName != 'Release' )
+ {
+ ^Libraries + { 'ImGui-Lib-$Platform$-$BuildConfigName$' }
+ }
.LinkerOutput = '$BinPath$/$Platform$-$BuildConfigName$/$ProjectName$.dll' // Output .dll to Bin
diff --git a/Juliet/include/Core/HAL/Filesystem/Filesystem.h b/Juliet/include/Core/HAL/Filesystem/Filesystem.h
index 4464117..8fabbe5 100644
--- a/Juliet/include/Core/HAL/Filesystem/Filesystem.h
+++ b/Juliet/include/Core/HAL/Filesystem/Filesystem.h
@@ -5,7 +5,16 @@
namespace Juliet
{
// Returns the path to the application directory
- extern JULIET_API String GetBasePath();
+ [[nodiscard]] extern JULIET_API String GetBasePath();
- extern JULIET_API bool IsAbsolutePath(String path);
+ // Returns the resolved base path to the compiled shaders directory.
+ // In dev, this resolves to ../../Assets/compiled/ relative to the exe.
+ // In shipping, this resolves to Assets/Shaders/ next to the exe.
+ [[nodiscard]] extern JULIET_API String GetAssetBasePath();
+
+ // Builds a full path to an asset file given its filename (e.g. "Triangle.vert.dxil").
+ // The caller owns the returned buffer and must free it.
+ [[nodiscard]] extern JULIET_API String GetAssetPath(String filename);
+
+ [[nodiscard]]extern JULIET_API bool IsAbsolutePath(String path);
} // namespace Juliet
diff --git a/Juliet/include/Core/ImGui/ImGuiService.h b/Juliet/include/Core/ImGui/ImGuiService.h
index a700a65..3a5509c 100644
--- a/Juliet/include/Core/ImGui/ImGuiService.h
+++ b/Juliet/include/Core/ImGui/ImGuiService.h
@@ -3,6 +3,8 @@
#include
#include
+#ifdef JULIET_ENABLE_IMGUI
+
struct ImGuiContext;
namespace Juliet
@@ -25,3 +27,5 @@ namespace Juliet
JULIET_API void RunTests();
} // namespace ImGuiService
} // namespace Juliet
+
+#endif // JULIET_ENABLE_IMGUI
diff --git a/Juliet/src/Core/HAL/Display/Win32/Win32DisplayEvent.cpp b/Juliet/src/Core/HAL/Display/Win32/Win32DisplayEvent.cpp
index 34fe64d..4e58f61 100644
--- a/Juliet/src/Core/HAL/Display/Win32/Win32DisplayEvent.cpp
+++ b/Juliet/src/Core/HAL/Display/Win32/Win32DisplayEvent.cpp
@@ -14,8 +14,10 @@
// For GET_X_LPARAM, GET_Y_LPARAM.
#include
+#ifdef JULIET_ENABLE_IMGUI
#include // Need For IMGUI_IMPL_API
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+#endif
namespace Juliet::Win32
{
@@ -145,10 +147,12 @@ namespace Juliet::Win32
LRESULT CALLBACK Win32MainWindowCallback(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
+#ifdef JULIET_ENABLE_IMGUI
if (ImGui_ImplWin32_WndProcHandler(handle, message, wParam, lParam))
{
return true;
}
+#endif
LRESULT returnCode = -1;
diff --git a/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp b/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp
index 341a870..940bda6 100644
--- a/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp
+++ b/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp
@@ -1,14 +1,29 @@
+#include
+#include
#include
#include
#include
#include
+#include
+#include
+#include
#include
+#include
+
namespace Juliet
{
namespace
{
- String CachedBasePath = {};
+ String CachedBasePath = {};
+ String CachedAssetBasePath = {};
+
+ bool DirectoryExists(const char* path)
+ {
+ Assert(path);
+ DWORD attributes = GetFileAttributesA(path);
+ return (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY);
+ }
}
String GetBasePath()
@@ -20,6 +35,27 @@ namespace Juliet
return CachedBasePath;
}
+ String GetAssetBasePath()
+ {
+ return CachedAssetBasePath;
+ }
+
+ [[nodiscard]] String GetAssetPath(String filename)
+ {
+ Assert(IsValid(CachedAssetBasePath));
+ Assert(IsValid(filename));
+
+ size_t totalSize = CachedAssetBasePath.Size + filename.Size + 1;
+ auto* buffer = static_cast(Calloc(totalSize, sizeof(char)));
+ if (!buffer)
+ {
+ return {};
+ }
+
+ snprintf(buffer, totalSize, "%s%s", CStr(CachedAssetBasePath), CStr(filename));
+ return { buffer, totalSize - 1 };
+ }
+
bool IsAbsolutePath(String path)
{
if (!IsValid(path))
@@ -29,7 +65,40 @@ namespace Juliet
return Platform::IsAbsolutePath(path);
}
- void InitFilesystem() {}
+ void InitFilesystem()
+ {
+ String basePath = GetBasePath();
+ Assert(IsValid(basePath));
+
+ // Probe candidate paths for compiled shader directory
+ // 1. Shipping layout: Assets/Shaders/ next to the exe
+ // 2. Dev layout: ../../Assets/compiled/ (exe is in bin/x64Clang-/)
+ constexpr const char* kCandidates[] = {
+ "Assets/Shaders/",
+ "../../Assets/compiled/"
+ };
+
+ for (const char* candidate : kCandidates)
+ {
+ char probePath[512];
+ snprintf(probePath, sizeof(probePath), "%s%s", CStr(basePath), candidate);
+
+ if (DirectoryExists(probePath))
+ {
+ size_t len = strlen(probePath);
+ auto* buffer = static_cast(Calloc(len + 1, sizeof(char)));
+ if (buffer)
+ {
+ snprintf(buffer, len + 1, "%s", probePath);
+ CachedAssetBasePath = { buffer, len };
+ Log(LogLevel::Message, LogCategory::Core, "Asset base path: %s", buffer);
+ }
+ return;
+ }
+ }
+
+ Log(LogLevel::Error, LogCategory::Core, "Filesystem: Could not find Assets/compiled/ directory!");
+ }
void ShutdownFilesystem()
{
@@ -38,5 +107,10 @@ namespace Juliet
CachedBasePath.Size = 0;
SafeFree(CachedBasePath.Data);
}
+ if (IsValid(CachedAssetBasePath))
+ {
+ CachedAssetBasePath.Size = 0;
+ SafeFree(CachedAssetBasePath.Data);
+ }
}
} // namespace Juliet
diff --git a/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp b/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp
index 20bcae7..d361e83 100644
--- a/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp
+++ b/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp
@@ -58,7 +58,7 @@ namespace Juliet::Platform
bool IsAbsolutePath(String path)
{
- if (path.Data || path.Size == 0)
+ if (!path.Data || path.Size == 0)
{
return false;
}
diff --git a/Juliet/src/Core/ImGui/ImGuiService.cpp b/Juliet/src/Core/ImGui/ImGuiService.cpp
index 0629010..91ff177 100644
--- a/Juliet/src/Core/ImGui/ImGuiService.cpp
+++ b/Juliet/src/Core/ImGui/ImGuiService.cpp
@@ -3,9 +3,10 @@
#include
#include
#include
-
#include
+#ifdef JULIET_ENABLE_IMGUI
+
#include
#include
@@ -102,3 +103,5 @@ namespace Juliet::ImGuiService
Juliet::UnitTest::TestImGui();
}
} // namespace Juliet::ImGuiService
+
+#endif // JULIET_ENABLE_IMGUI
diff --git a/Juliet/src/Core/ImGui/ImGuiTests.cpp b/Juliet/src/Core/ImGui/ImGuiTests.cpp
index faff455..4543686 100644
--- a/Juliet/src/Core/ImGui/ImGuiTests.cpp
+++ b/Juliet/src/Core/ImGui/ImGuiTests.cpp
@@ -10,6 +10,7 @@ namespace Juliet::UnitTest
{
void TestImGui()
{
+#ifdef JULIET_ENABLE_IMGUI
ImGuiContext* ctx = ImGuiService::GetContext();
if (ImGui::GetCurrentContext() != ctx)
@@ -68,5 +69,6 @@ namespace Juliet::UnitTest
(void)drawList;
printf("ImGui tests passed (Exhaustive).\n");
+#endif
}
} // namespace Juliet::UnitTest
diff --git a/Juliet/src/Graphics/DebugDisplayRenderer.cpp b/Juliet/src/Graphics/DebugDisplayRenderer.cpp
index 464c4d4..ee4a5db 100644
--- a/Juliet/src/Graphics/DebugDisplayRenderer.cpp
+++ b/Juliet/src/Graphics/DebugDisplayRenderer.cpp
@@ -2,6 +2,7 @@
#include
#include
+#include
#include
#include
@@ -84,11 +85,11 @@ namespace Juliet
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
- String vertPath = WrapString("../../Assets/compiled/Debug.vert.dxil");
+ String vertPath = GetAssetPath(WrapString("Debug.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
Shader* vertexShader = CreateShader(device, vertPath, shaderCI);
- String fragPath = WrapString("../../Assets/compiled/Debug.frag.dxil");
+ String fragPath = GetAssetPath(WrapString("Debug.frag.dxil"));
shaderCI.Stage = ShaderStage::Fragment;
Shader* fragmentShader = CreateShader(device, fragPath, shaderCI);
diff --git a/Juliet/src/Graphics/ImGuiRenderer.cpp b/Juliet/src/Graphics/ImGuiRenderer.cpp
index eebe4ea..0d19b7d 100644
--- a/Juliet/src/Graphics/ImGuiRenderer.cpp
+++ b/Juliet/src/Graphics/ImGuiRenderer.cpp
@@ -5,6 +5,7 @@
#include
#include
+#include
#include
#include
@@ -127,11 +128,11 @@ namespace Juliet
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
- String vertPath = WrapString("../../Assets/compiled/ImGui.vert.dxil");
+ String vertPath = GetAssetPath(WrapString("ImGui.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
g_ImGuiState.VertexShader = CreateShader(device, vertPath, shaderCI);
- String fragPath = WrapString("../../Assets/compiled/ImGui.frag.dxil");
+ String fragPath = GetAssetPath(WrapString("ImGui.frag.dxil"));
shaderCI.Stage = ShaderStage::Fragment;
g_ImGuiState.FragmentShader = CreateShader(device, fragPath, shaderCI);
diff --git a/Juliet/src/Graphics/MeshRenderer.cpp b/Juliet/src/Graphics/MeshRenderer.cpp
index 8c5b2a1..250b701 100644
--- a/Juliet/src/Graphics/MeshRenderer.cpp
+++ b/Juliet/src/Graphics/MeshRenderer.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -29,12 +30,11 @@ namespace Juliet
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
- // TODO: Assets management that handles path to assets or something.
- String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
+ String shaderPath = GetAssetPath(WrapString("Triangle.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
Shader* vertexShader = CreateShader(graphicsDevice, shaderPath, shaderCI);
- shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
+ shaderPath = GetAssetPath(WrapString("SolidColor.frag.dxil"));
shaderCI.Stage = ShaderStage::Fragment;
Shader* fragmentShader = CreateShader(graphicsDevice, shaderPath, shaderCI);
@@ -307,11 +307,11 @@ namespace Juliet
String entryPoint = WrapString("main");
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
- String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
+ String shaderPath = GetAssetPath(WrapString("Triangle.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
Shader* vertexShader = CreateShader(device, shaderPath, shaderCI);
- shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
+ shaderPath = GetAssetPath(WrapString("SolidColor.frag.dxil"));
shaderCI.Stage = ShaderStage::Fragment;
Shader* fragmentShader = CreateShader(device, shaderPath, shaderCI);
diff --git a/JulietApp/JulietApp.bff b/JulietApp/JulietApp.bff
index e3675ba..e57757a 100644
--- a/JulietApp/JulietApp.bff
+++ b/JulietApp/JulietApp.bff
@@ -59,9 +59,12 @@
.Libraries = {
'JulietApp-Lib-$Platform$-$BuildConfigName$',
'Juliet-Lib-$Platform$-$BuildConfigName$',
- 'Game-Lib-$Platform$-$BuildConfigName$',
- 'ImGui-Lib-$Platform$-$BuildConfigName$'
+ 'Game-Lib-$Platform$-$BuildConfigName$'
}
+ If ( .BuildConfigName != 'Release' )
+ {
+ ^Libraries + { 'ImGui-Lib-$Platform$-$BuildConfigName$' }
+ }
.LinkerOutput = '$BinPath$/$Platform$-$BuildConfigName$/$ProjectName$$ExeExtension$'
diff --git a/misc/agent_error.log b/misc/agent_error.log
deleted file mode 100644
index e69de29..0000000
diff --git a/misc/ship.bat b/misc/ship.bat
new file mode 100644
index 0000000..5f27cf5
--- /dev/null
+++ b/misc/ship.bat
@@ -0,0 +1,62 @@
+@echo off
+setlocal
+
+REM ============================================================
+REM ship.bat - Build clang-Release and prepare Ship/ folder
+REM ============================================================
+
+set ROOT=%~dp0..
+set BUILD_DIR=%ROOT%\bin\x64Clang-Release
+set SHIP_DIR=%ROOT%\Ship
+
+REM Step 0: Build Shader Compiler
+echo [Ship] Building Shader Compiler...
+call "%~dp0fbuild" JulietShaderCompiler-x64Clang-Release -cache
+if errorlevel 1 (
+ echo [Ship] SHADER COMPILER BUILD FAILED
+ exit /b 1
+)
+
+REM Step 1: Compile shaders
+echo [Ship] Compiling shaders...
+call "%~dp0recompile_shaders.bat"
+if errorlevel 1 (
+ echo [Ship] SHADER COMPILATION FAILED
+ exit /b 1
+)
+
+REM Step 2: Build clang-Release
+echo [Ship] Building clang-Release...
+call "%~dp0fbuild" clang-Release -cache
+if errorlevel 1 (
+ echo [Ship] BUILD FAILED
+ exit /b 1
+)
+
+REM Step 3: Prepare Ship folder
+echo [Ship] Preparing Ship folder: %SHIP_DIR%
+
+if exist "%SHIP_DIR%" rd /s /q "%SHIP_DIR%"
+mkdir "%SHIP_DIR%"
+
+REM Copy only the required binaries
+echo [Ship] Copying binaries...
+copy "%BUILD_DIR%\JulietApp.exe" "%SHIP_DIR%\" >nul
+copy "%BUILD_DIR%\Juliet.dll" "%SHIP_DIR%\" >nul
+copy "%BUILD_DIR%\Game.dll" "%SHIP_DIR%\" >nul
+
+REM Copy compiled shaders into Assets\Shaders\
+echo [Ship] Copying shaders...
+mkdir "%SHIP_DIR%\Assets\Shaders"
+copy "%ROOT%\Assets\compiled\*.dxil" "%SHIP_DIR%\Assets\Shaders\" >nul
+del "%SHIP_DIR%\Assets\Shaders\ImGui*.dxil" >nul 2>&1
+
+echo.
+echo [Ship] Done!
+echo [Ship] Ship folder: %SHIP_DIR%
+echo.
+echo [Ship] Contents:
+dir /b "%SHIP_DIR%"
+echo.
+echo [Ship] Shaders:
+dir /b "%SHIP_DIR%\Assets\Shaders"