From e6cc9e6c4eb4033db2f16b37c984a8f664515e9c Mon Sep 17 00:00:00 2001 From: emil28092005 Date: Thu, 18 Jun 2026 19:25:02 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20dynamic=20point=20light=20on=20a=20phys?= =?UTF-8?q?ics=20ball=20=E2=80=94=20falls=20and=20illuminates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LightBall entity: sphere mesh + DynamicSphere physics + Light.Point - Renderer reads light position from Transform (not static Light.Position) so the light moves with the physics body - Light intensity 20, range 30, warm color (1.0, 0.9, 0.7) - Ball falls from y=15, bounces on floor, light follows it - Renderer: prefers Light+Transform pair for dynamic position, falls back to Light only --- src/CortexEngine.App/Program.cs | 7 +++++++ src/Engine.Graphics.Vulkan/VulkanRenderer.cs | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/CortexEngine.App/Program.cs b/src/CortexEngine.App/Program.cs index 0dc7c94..575da58 100644 --- a/src/CortexEngine.App/Program.cs +++ b/src/CortexEngine.App/Program.cs @@ -268,6 +268,13 @@ class Program .Set(new Transform(new Vector3(0, 8, 0), Quaternion.Identity, Vector3.One)) .Set(Light.Point(new Vector3(0, 8, 0), new Vector3(1.0f, 0.9f, 0.7f), intensity: 15.0f, range: 25.0f)); + var lightSphere = ProceduralMesh.CreateSphere(0.5f, 24, 12, new Vector3(1.0f, 0.9f, 0.7f)); + world.Entity("LightBall") + .Set(new Transform(new Vector3(0, 15, 0), Quaternion.Identity, Vector3.One)) + .Set(lightSphere) + .Set(RigidBody.DynamicSphere(0.5f, mass: 0.5f)) + .Set(Light.Point(new Vector3(0, 15, 0), new Vector3(1.0f, 0.9f, 0.7f), intensity: 20.0f, range: 30.0f)); + var entityCount = 0; world.Each((Entity e, ref Transform _) => entityCount++); Console.WriteLine($"[Scene] {entityCount} entities: torus knot + 4 dynamic cubes + 3 dynamic spheres + static floor + grid"); diff --git a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs index 285c7d8..08ba118 100644 --- a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs @@ -77,17 +77,28 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen vp = Matrix4x4.CreateLookAt(new Vector3(0, 0, -6), Vector3.Zero, Vector3.UnitY) * proj; } - // Collect point light from ECS (first point light found) + // Collect point light from ECS — prefer light attached to a moving entity var lightPos = new Vector4(0, 5, 0, 0); var lightColor = new Vector4(1, 1, 1, 0); - world.Each((Entity e, ref Light l) => + world.Each((Entity e, ref Light l, ref Transform lt) => { if (l.IsPoint && lightPos.W == 0) { - lightPos = new Vector4(l.Position, l.Intensity); + lightPos = new Vector4(lt.Position, l.Intensity); lightColor = new Vector4(l.Color, l.Range); } }); + if (lightPos.W == 0) + { + world.Each((Entity e, ref Light l) => + { + if (l.IsPoint && lightPos.W == 0) + { + lightPos = new Vector4(l.Position, l.Intensity); + lightColor = new Vector4(l.Color, l.Range); + } + }); + } // Pack UBO: mat4 vp (64 bytes) + vec4 lightPos (16) + vec4 lightColor (16) = 96 bytes var uboData = stackalloc byte[128];