feat(app): Phase A.1 — TerrainRenderer.RemoveLandblock for streaming unloads
TerrainRenderer's internal landblock collection is now a Dictionary keyed by landblock id so the streaming system can release GPU resources per-landblock as the visible window moves. AddLandblock takes the id as its first parameter; if the same id is added twice, the old buffers are freed before the new ones land (defensive but cheap). RemoveLandblock is a no-op for unknown ids and deletes VBO/EBO/VAO for known ones. Single existing caller in GameWindow.cs updated to pass the id. Build green. No unit tests — direct-to-GL methods need a live context. Tasks 5-7 will validate end-to-end. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c5e207a51f
commit
495f87a4ad
2 changed files with 32 additions and 6 deletions
|
|
@ -245,7 +245,7 @@ public sealed class GameWindow : IDisposable
|
|||
((int)lbY - centerY) * 192f,
|
||||
0f);
|
||||
|
||||
_terrain.AddLandblock(meshData, origin);
|
||||
_terrain.AddLandblock(lb.LandblockId, meshData, origin);
|
||||
}
|
||||
Console.WriteLine($"terrain: {surfaceCache.Count} unique palette codes across {worldView.Landblocks.Count} landblocks");
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public sealed unsafe class TerrainRenderer : IDisposable
|
|||
private readonly GL _gl;
|
||||
private readonly Shader _shader;
|
||||
private readonly TerrainAtlas _atlas;
|
||||
private readonly List<LandblockGpu> _landblocks = new();
|
||||
private readonly Dictionary<uint, LandblockGpu> _landblocks = new();
|
||||
|
||||
public TerrainRenderer(GL gl, Shader shader, TerrainAtlas atlas)
|
||||
{
|
||||
|
|
@ -31,10 +31,19 @@ public sealed unsafe class TerrainRenderer : IDisposable
|
|||
_atlas = atlas;
|
||||
}
|
||||
|
||||
public void AddLandblock(LandblockMeshData meshData, Vector3 worldOrigin)
|
||||
public void AddLandblock(uint landblockId, LandblockMeshData meshData, Vector3 worldOrigin)
|
||||
{
|
||||
if (_landblocks.TryGetValue(landblockId, out var existing))
|
||||
{
|
||||
_gl.DeleteBuffer(existing.Vbo);
|
||||
_gl.DeleteBuffer(existing.Ebo);
|
||||
_gl.DeleteVertexArray(existing.Vao);
|
||||
_landblocks.Remove(landblockId);
|
||||
}
|
||||
|
||||
var gpu = new LandblockGpu
|
||||
{
|
||||
LandblockId = landblockId,
|
||||
Vao = _gl.GenVertexArray(),
|
||||
WorldOrigin = worldOrigin,
|
||||
IndexCount = meshData.Indices.Length,
|
||||
|
|
@ -76,7 +85,23 @@ public sealed unsafe class TerrainRenderer : IDisposable
|
|||
_gl.VertexAttribIPointer(5, 4, VertexAttribIType.UnsignedByte, stride, (void*)(dataOffset + 12));
|
||||
|
||||
_gl.BindVertexArray(0);
|
||||
_landblocks.Add(gpu);
|
||||
_landblocks[landblockId] = gpu;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release GPU buffers for a previously-added landblock. No-op if the
|
||||
/// landblock wasn't added. Called by the streaming system when a
|
||||
/// landblock falls outside the visible window.
|
||||
/// </summary>
|
||||
public void RemoveLandblock(uint landblockId)
|
||||
{
|
||||
if (!_landblocks.TryGetValue(landblockId, out var gpu))
|
||||
return;
|
||||
|
||||
_gl.DeleteBuffer(gpu.Vbo);
|
||||
_gl.DeleteBuffer(gpu.Ebo);
|
||||
_gl.DeleteVertexArray(gpu.Vao);
|
||||
_landblocks.Remove(landblockId);
|
||||
}
|
||||
|
||||
public void Draw(ICamera camera)
|
||||
|
|
@ -96,7 +121,7 @@ public sealed unsafe class TerrainRenderer : IDisposable
|
|||
int alphaLoc = _gl.GetUniformLocation(_shader.Program, "uAlpha");
|
||||
if (alphaLoc >= 0) _gl.Uniform1(alphaLoc, 1);
|
||||
|
||||
foreach (var lb in _landblocks)
|
||||
foreach (var lb in _landblocks.Values)
|
||||
{
|
||||
var model = Matrix4x4.CreateTranslation(lb.WorldOrigin);
|
||||
_shader.SetMatrix4("uModel", model);
|
||||
|
|
@ -108,7 +133,7 @@ public sealed unsafe class TerrainRenderer : IDisposable
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var lb in _landblocks)
|
||||
foreach (var lb in _landblocks.Values)
|
||||
{
|
||||
_gl.DeleteBuffer(lb.Vbo);
|
||||
_gl.DeleteBuffer(lb.Ebo);
|
||||
|
|
@ -119,6 +144,7 @@ public sealed unsafe class TerrainRenderer : IDisposable
|
|||
|
||||
private sealed class LandblockGpu
|
||||
{
|
||||
public uint LandblockId;
|
||||
public uint Vao;
|
||||
public uint Vbo;
|
||||
public uint Ebo;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue