Commit Graph
15 Commits
Author SHA1 Message Date
emil28092005 ef7c808304 feat: pause/resume physics + reset scene buttons in ImGui
- 'Pause Physics' / 'Resume Physics' toggle button in debug panel
- 'Reset Scene' button: deletes all objects (except Camera, lights, Floor),
  recreates scene via CreateObjects()
- CreateScene split: CreateScene (floor + lights) vs CreateObjects (all
  dynamic/decorative objects) — Reset only recreates objects
- physicsEnabled flag controls physicsWorld.Update + SyncTransforms
- Removed duplicate light creation in CreateObjects
2026-06-19 09:39:33 +03:00
emil28092005 346b422cb0 fix: all lights default to intensity=8 range=15.5 + clipboard logging
- All 3 lights: intensity 8.0, range 15.5 (was 12/8/8, 60/40/40)
- Copy Parameters: also logs to console for debugging
- Clipboard text via ImGui.SetClipboardText (standard API)
2026-06-19 08:44:07 +03:00
emil28092005 4955a042e9 fix: restore Copy Parameters button with all 3 lights
- Button outputs: shadow params + all 3 light intensity/range/color
- Format: light1Intensity=12.0, light1Color=(1.00,0.95,0.85), etc.
2026-06-19 08:16:56 +03:00
emil28092005 ad92e758de feat: 3 dynamic point lights with shadows
- MainLight: warm (1.0, 0.95, 0.85), intensity 12, range 60
- SecondLight: cool blue (0.3, 0.6, 1.0), intensity 8, range 40
- ThirdLight: red (0.9, 0.2, 0.3), intensity 8, range 40
- All 3 orbit in chaotic circles at different phases
- All 3 cast shadows (18 shadow passes per frame = 3 × 6)
- ImGui: per-light sliders for all 3 lights
- Reduced intensities slightly to balance 3 overlapping lights
2026-06-19 08:12:18 +03:00
emil28092005 d0af9b5c2d fix: UBO binding 0 visible to fragment shader — lights now work
Root cause: descriptor set layout binding 0 (SceneUBO) had stageFlags=Vertex
only. Fragment shader reads numLights, lights[], shadowParams[] from UBO
but couldn't access it. Changed to Vertex|Fragment.
2026-06-19 08:07:44 +03:00
emil28092005 2f7430e3b1 fix: flip normals when facing away from light/view — fixes cube lighting
Root cause: cube.obj has inconsistent winding order. Many faces have
normals pointing inward (e.g. back face normal = +Z instead of -Z).
With cullMode=None, both sides render, but inward normals cause:
- No diffuse lighting (NdotL < 0 → max() = 0)
- Wrong shadow bias (slope-dependent bias uses wrong NdotL)
- Inconsistent shadow edges on cube faces

Fix: in fragment shader, flip normal if dot(N,L) < 0 or dot(N,V) < 0
This is the standard approach for double-sided rendering with
non-watertight geometry or inconsistent winding order.
2026-06-18 21:53:15 +03:00
emil28092005 29a58d204b feat: ImGui shadow parameters panel with clipboard copy
- Push constant block expanded: 160B → 176B (added vec4 shadowParams)
- shadowParams: x=bias, y=sampleRadius, z=farPlane, w=unused
- Fragment shader: bias and sampleRadius now read from push constants
  (dynamic, adjustable at runtime)
- Shadow.frag: uses pc.shadowParams.z for farPlane (dynamic)
- Slope-dependent bias: bias + bias*2*(1-NdotL) — adaptive
- VulkanRenderer: public ShadowBias, ShadowSampleRadius, ShadowFarPlane properties
- Program.cs: ImGui 'Shadow Parameters' panel with sliders:
  - Light Intensity (0-100), Range (5-100), RGB color
  - Shadow Bias (0.001-0.5), Sample Radius (0.001-0.1), Far Plane (10-120)
  - 'Copy Parameters to Clipboard' button — outputs all values as text
- 227 tests, all pass
2026-06-18 21:48:38 +03:00
emil28092005 749fbc8df4 feat: ImGui integration + real screenshot capture via Vulkan
ImGui:
- ImGui.NET 1.91.6.1 NuGet package
- VulkanImGui: font texture upload, ImGui pipeline (blending, no depth), vertex/index buffer streaming
- GLSL 450 ImGui shaders (vert: scale/translate push constants, frag: font texture sampler)
- Compiled to SPIR-V via @webgpu/glslang
- Debug overlay: FPS, camera position, entity count, light list
- 1600+ FPS with ImGui active

Screenshot:
- vkCmdCopyImageToBuffer embedded in main command buffer
- Layout transition PresentSrcKHR→TransferSrcOptimal→PresentSrcKHR
- Deferred read: staging buffer read on next frame after fence
- BMP format written directly to FileStream (row by row)
- All 16 camera tour screenshots captured (1280x720x32bpp)

All 66 tests pass.
2026-06-17 23:39:38 +03:00
emil28092005 417915e861 feat: switch default backend to Silk.NET OpenGL
- OpenGLRenderContext: Initialize() + CreateOpenGL() for non-blocking
- OpenGLWindow: Initialize() instead of Run(), CreateGL() method
- Program.cs: default backend is now 'opengl', SwapBuffers per frame
- ImGui guarded: only initialized for RaylibRenderer, ObjectManipulator
  checks _imGuiAvailable before calling ImGui.GetIO()
- 66/66 tests, 145 FPS with OpenGL backend
2026-06-17 20:14:15 +03:00
emil28092005 e452a294cc revert: remove shadow mapping attempts, restore clean renderer
Shadow mapping via Raylib doesn't work reliably:
- Rlgl.GetMatrixModelview returns zeros with custom FBO
- MaterialMapIndex binding doesn't map to expected texture units
- DrawModelEx resets texture state internally
Restored to last working state without shadows.
Consider direct OpenGL backend for shadow mapping.
2026-06-17 18:40:30 +03:00
emil28092005 6d16287bcb fix: shadow map re-bind after DrawModelEx + transpose lightViewProj
- Bind shadow map on MaterialMapIndex.Emission (unit 1) per entity
- Re-bind via Rlgl.ActiveTextureSlot(1)+EnableTexture after DrawModelEx
  (DrawModelEx resets texture state internally)
- Transpose lightViewProj matrix (Raylib row-major → OpenGL column-major)
- 66/66 tests, 145 FPS
2026-06-17 18:07:13 +03:00
emil28092005 23cac8052c fix: remove shadow mapping, keep all other improvements
Shadow mapping removed — Raylib's DrawModelEx doesn't support
multi-texture-unit binding needed for shadow map sampling.
Kept: linear gamma, per-channel Fresnel, point/directional lights,
correct CW normals, backface culling, floor entity.
66/66 tests passing.
2026-06-17 16:33:12 +03:00
emil28092005 c82ff48119 fix: rlgl depth FBO shadows, correct normals, linear gamma, per-channel Fresnel
- Shadow mapping via rlgl: custom depth FBO (2048x2048, 24-bit depth texture)
  instead of color-attachment approach. Proper depth-only render pass.
- Shadow map bound via MaterialMapIndex.Emission (texture unit 1), sampled
  in shadow receiver shader with PCF 3x3 soft shadows.
- Fixed inverted normals: Cross(ac, ab) for CW winding in OBJ files.
- Linear workflow: pow(albedo, 2.2) before lighting, pow(result, 1/2.2) after.
- Per-channel Fresnel: vec3 F0 + (1-F0)*pow(1-HdotV,5) instead of F0.x.
- Single CollectLights call after BeginMode3D.
- Shadow pass after BeginDrawing (inside frame).
- Backface culling disabled globally for mixed-winding meshes.
- Point light support: Light.Point/Directional factory methods, attenuation,
  ImGui inspector with type combo, position/range for point lights.
- Floor rendered for both light types (shadow receiver or main shader).
- 66/66 tests passing.
2026-06-17 16:13:46 +03:00
emil28092005 f905fe3040 fix: restore rendering after shadow mapping attempt
Shadow mapping via DrawModelEx doesn't work — Raylib's material system
only supports texture unit 0, shadow map sampling needs unit 1.
Additional uniforms in fragment shader also broke NVIDIA GLSL uniform
layout, causing render artifacts. Reverted shader to pre-shadow state.
Shadow pass infrastructure (RenderShadowPass, shadow shader, RT) kept
but disabled. 66/66 tests passing.
2026-06-17 14:44:49 +03:00
emil28092005 2d30dec01c feat: Dear ImGui editor, GLTF materials, scene serialization
- ImGuiLayer: entity inspector (Transform/Material/Light/Camera editing),
  hierarchy panel, debug overlay with FPS graph (rlImgui-cs + ImGui.NET)
- GltfLoader.LoadWithMaterials: extracts PBR albedo, roughness, metallic,
  base color texture from glTF files
- SceneSerializer: save/load ECS world to/from JSON with custom
  Vector3/Quaternion converters, 6 tests
- ImGui disabled in tour/test mode to keep screenshots clean
- 66/66 tests passing
2026-06-17 14:12:02 +03:00