Commit graph

4 commits

Author SHA1 Message Date
Erik
31d3a4678f fix(lighting): port ACME lighting constants replacing guessed values
Replace guessed sun direction (0.5, 0.4, 0.6) with ACME's verified
value (0.5, 0.3, -0.3) from GameScene.cs:238. Replace hardcoded
ambient/diffuse (0.25/0.75) with ACME's ambient intensity 0.45 from
LandscapeEditorSettings.cs:108.

Terrain shaders now match ACME Landscape.vert/frag pattern:
- Vertex shader computes Lambert term with xLightDirection uniform
- Fragment shader applies: color * (clamp(lambert, 0, 1) + xAmbient)

Static object shader matches ACME StaticObject.vert:
- LightingFactor = max(dot(N, -L), 0) + ambient
- Removed separate uDiffuseIntensity (ACME doesn't have one)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:01:28 +02:00
Erik
787e0f0aff fix(render): skip empty groups in instanced draw to prevent crash on Tab
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 18:55:29 +02:00
Erik
6a55838a10 perf(rendering): true DrawElementsInstanced — one draw call per (GfxObj × sub-mesh)
Replaces the per-entity glUniform uModel path with a shared instance VBO and
DrawElementsInstanced. All instance model matrices are uploaded to GPU once per
frame; the VAO's per-instance attribute pointers (locations 3–6, divisor=1) are
updated with a byte-offset re-point per group so a single VBO serves all groups
without requiring DrawElementsInstancedBaseInstance (not in Silk.NET 2.23).

Changes:
- InstancedMeshRenderer: add _instanceVbo, _instanceBuffer scratch; EnsureUploaded
  sets up mat4 instance attrs (locs 3–6) from the shared VBO; Draw builds the flat
  float[] of all instance matrices once then calls DrawElementsInstanced per sub-mesh.
  Drops the unused uint TerrainLayer attribute (loc 3 from vertex VBO) — mesh shaders
  never used it. Adds InstanceGroup helper to track per-group buffer offsets.
- mesh_instanced.frag: replace sampler2DArray+uTextureLayer with sampler2D uDiffuse,
  matching the existing TextureCache / individual-texture pipeline.
- mesh_instanced.vert+frag: track as committed files (were untracked).
- Shader.cs: add SetVec3 helper needed for uLightDirection uniform.
- GameWindow.cs: switch mesh shader load from mesh.vert/.frag to
  mesh_instanced.vert/.frag.

Visual output is identical: same entities, same textures, same lighting constants
(SUN_DIR=(0.5,0.4,0.6), AMBIENT=0.25, DIFFUSE=0.75 — moved from frag to vert).
Build: clean. Tests: 431/431 green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 18:51:49 +02:00
Erik
b5099e2b21 refactor(rendering): introduce InstancedMeshRenderer with GfxObj grouping
Groups all (entity, meshRef) pairs by GfxObjId before drawing so each
GfxObj's sub-meshes are processed as a contiguous batch.  Still uses
per-entity uniform uModel — visual output is identical to the old
StaticMeshRenderer — but the _groups dict is the structural prerequisite
for swapping to DrawElementsInstanced in the follow-up commit.

Key changes:
- New InstancedMeshRenderer.cs with CollectGroups() that fills
  _groups[gfxObjId] = List<InstanceEntry> each frame, reusing the
  inner List<> objects to avoid per-frame allocation.
- Same two-pass (opaque+clipmap first, translucent second) draw logic
  from StaticMeshRenderer, now iterating over groups rather than raw
  entity/meshRef pairs.
- GameWindow.cs: field and constructor swapped from StaticMeshRenderer
  to InstancedMeshRenderer — public API is identical.
- 431 tests green, 0 warnings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 18:46:20 +02:00