diff --git a/Videos/cortex_20260619_093010.mp4 b/Videos/cortex_20260619_093010.mp4 new file mode 100644 index 0000000..c5a0bb7 Binary files /dev/null and b/Videos/cortex_20260619_093010.mp4 differ diff --git a/Videos/cortex_20260619_093035.mp4 b/Videos/cortex_20260619_093035.mp4 new file mode 100644 index 0000000..da8c346 Binary files /dev/null and b/Videos/cortex_20260619_093035.mp4 differ diff --git a/src/CortexEngine.App/Program.cs b/src/CortexEngine.App/Program.cs index f080728..d4cde5e 100644 --- a/src/CortexEngine.App/Program.cs +++ b/src/CortexEngine.App/Program.cs @@ -281,14 +281,21 @@ class Program var bias = vkRenderer.ShadowBias; var sampleRadius = vkRenderer.ShadowSampleRadius; var farPlane = vkRenderer.ShadowFarPlane; + var ambient = vkRenderer.AmbientColor; ImGui.SliderFloat("Shadow Bias", ref bias, 0.0001f, 0.1f, "%.4f"); ImGui.SliderFloat("Sample Radius", ref sampleRadius, 0.001f, 0.1f, "%.4f"); ImGui.SliderFloat("Far Plane", ref farPlane, 10.0f, 120.0f, "%.1f"); + ImGui.Separator(); + ImGui.Text("Ambient Light"); + ImGui.SliderFloat("Ambient R", ref ambient.X, 0.0f, 0.5f, "%.3f"); + ImGui.SliderFloat("Ambient G", ref ambient.Y, 0.0f, 0.5f, "%.3f"); + ImGui.SliderFloat("Ambient B", ref ambient.Z, 0.0f, 0.5f, "%.3f"); vkRenderer.ShadowBias = bias; vkRenderer.ShadowSampleRadius = sampleRadius; vkRenderer.ShadowFarPlane = farPlane; + vkRenderer.AmbientColor = ambient; ImGui.Text($"Current: bias={bias:F4} radius={sampleRadius:F4} far={farPlane:F1}"); diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag index 81d3ba3..b199e14 100644 --- a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag +++ b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag @@ -18,6 +18,7 @@ layout(set = 0, binding = 0) uniform SceneUBO { vec2 padding; LightData lights[8]; vec4 shadowParams[4]; + vec4 ambientColor; // xyz = ambient color, w = unused } scene; layout(set = 0, binding = 1) uniform samplerCubeArray shadowArray; @@ -151,7 +152,7 @@ void main() float roughness = 0.5; float metallic = 0.1; - vec3 color = AMBIENT * albedo; + vec3 color = scene.ambientColor.xyz * albedo; for (int i = 0; i < scene.numLights; i++) { diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv index c2b0c65..0f61933 100644 Binary files a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv and b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv differ diff --git a/src/Engine.Graphics.Vulkan/VulkanFrameResources.cs b/src/Engine.Graphics.Vulkan/VulkanFrameResources.cs index 6afe650..ba32837 100644 --- a/src/Engine.Graphics.Vulkan/VulkanFrameResources.cs +++ b/src/Engine.Graphics.Vulkan/VulkanFrameResources.cs @@ -5,7 +5,7 @@ namespace Engine.Graphics.Vulkan; internal sealed unsafe class VulkanFrameResources : IDisposable { public const int MaxFramesInFlight = 2; - public const ulong UboSize = 448; + public const ulong UboSize = 464; public VkCommandPool CommandPool; public VkCommandBuffer[] CommandBuffers = new VkCommandBuffer[MaxFramesInFlight]; diff --git a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs index 6e8ce23..c1fff7b 100644 --- a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs @@ -32,6 +32,7 @@ public sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreensh public float ShadowBias { get; set; } = 0.0001f; public float ShadowSampleRadius { get; set; } = 0.015f; public float ShadowFarPlane { get; set; } = 60.0f; + public Vector3 AmbientColor { get; set; } = new(0.01f, 0.01f, 0.02f); public bool IsRecording { get; set; } public byte[]? CapturedFrame { get; private set; } @@ -227,6 +228,10 @@ public sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreensh System.Buffer.MemoryCopy(&sp, uboData + 336 + i * 16, 16, 16); } + // Ambient color at offset 400 (after 4 shadowParams = 64 bytes) + var ambient = new Vector4(AmbientColor, 0); + System.Buffer.MemoryCopy(&ambient, uboData + 400, 16, 16); + // Compute light view-proj for each shadow light var lightViewProjs = new Matrix4x4[numShadowLights]; for (int i = 0; i < numShadowLights; i++)