From 41429682da3ecd2c44a98276fcc403f385569cec Mon Sep 17 00:00:00 2001 From: Octal Date: Sat, 25 Nov 2023 21:01:18 -0600 Subject: [PATCH] Load chunks around the camera --- Client/Rendering/World/ChunkRenderSlot.cs | 4 +-- Client/Rendering/World/ChunkRenderer.cs | 38 ++++++++++++++--------- Client/VoxelClient.cs | 2 ++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Client/Rendering/World/ChunkRenderSlot.cs b/Client/Rendering/World/ChunkRenderSlot.cs index 40b2ff3..6ce6ce1 100644 --- a/Client/Rendering/World/ChunkRenderSlot.cs +++ b/Client/Rendering/World/ChunkRenderSlot.cs @@ -47,11 +47,11 @@ public override void Render(double delta) { } } - public void Move(ivec3 newCenterPos) { + public void Move(ivec3 newCenterPos, LoadedChunkSection chunks) { realPosition = newCenterPos + RelativePosition; //Should never be null bc this only has 1 callsite that already null checks it - targetChunk = Client.world!.GetOrCreateChunk(realPosition); + targetChunk = chunks.GetChunkRelative(RelativePosition); lastVersion = null; } diff --git a/Client/Rendering/World/ChunkRenderer.cs b/Client/Rendering/World/ChunkRenderer.cs index 25f4099..0421030 100644 --- a/Client/Rendering/World/ChunkRenderer.cs +++ b/Client/Rendering/World/ChunkRenderer.cs @@ -5,22 +5,25 @@ using Voxel.Client.Rendering.Texture; using Voxel.Client.Rendering.VertexTypes; using Voxel.Common.Util; +using Voxel.Common.World; namespace Voxel.Client.Rendering.World; public class ChunkRenderer : Renderer { + public readonly Pipeline ChunkPipeline; + public readonly ResourceLayout ChunkResourceLayout; + + public readonly Atlas TerrainAtlas; + + public LoadedChunkSection chunks; + private ChunkRenderSlot[]? renderSlots; private int renderDistance = 0; private int realRenderDistance = 0; private ivec3 renderPosition = ivec3.Zero; - public readonly Pipeline ChunkPipeline; - public readonly ResourceLayout ChunkResourceLayout; - - public readonly Atlas TerrainAtlas; - private ChunkRenderSlot? this[int x, int y, int z] { get { if (renderSlots == null) return null; @@ -44,8 +47,9 @@ private ChunkRenderSlot? this[ivec3 pos] { } public ChunkRenderer(VoxelClient client) : base(client) { + chunks = new(client.world!, renderPosition, ClientConfig.General.renderDistance, ClientConfig.General.renderDistance); SetRenderDistance(ClientConfig.General.renderDistance); - + TerrainAtlas = new("main", client.RenderSystem); AtlasLoader.LoadAtlas(RenderSystem.Game.AssetReader, TerrainAtlas, RenderSystem); BlockModelManager.Init(RenderSystem.Game.AssetReader, TerrainAtlas); @@ -58,16 +62,16 @@ public ChunkRenderer(VoxelClient client) : base(client) { if (!client.RenderSystem.ShaderManager.GetShaders("shaders/simple", out var shaders)) throw new("Shaders not present."); - ChunkPipeline = ResourceFactory.CreateGraphicsPipeline(new GraphicsPipelineDescription { + ChunkPipeline = ResourceFactory.CreateGraphicsPipeline(new() { BlendState = BlendStateDescription.SingleOverrideBlend, - DepthStencilState = new DepthStencilStateDescription { + DepthStencilState = new() { DepthComparison = ComparisonKind.LessEqual, DepthTestEnabled = true, DepthWriteEnabled = true, }, Outputs = RenderSystem.GraphicsDevice.SwapchainFramebuffer.OutputDescription, PrimitiveTopology = PrimitiveTopology.TriangleList, - RasterizerState = new RasterizerStateDescription { + RasterizerState = new() { CullMode = FaceCullMode.Back, DepthClipEnabled = true, FillMode = PolygonFillMode.Solid, @@ -87,8 +91,7 @@ public ChunkRenderer(VoxelClient client) : base(client) { } }); } - - + public void Reload() { if (renderSlots == null) return; @@ -114,12 +117,13 @@ public override void Render(double delta) { } public void SetRenderDistance(int distance) { + chunks.Resize(distance, distance); if (renderSlots != null) foreach (var slot in renderSlots) slot.Dispose(); //Todo - Cache and re-use instead of dispose renderDistance = distance; - realRenderDistance = ((renderDistance * 2) + 1); + realRenderDistance = renderDistance * 2 + 1; var totalChunks = realRenderDistance * realRenderDistance * realRenderDistance; renderSlots = new ChunkRenderSlot[totalChunks]; @@ -127,7 +131,7 @@ public void SetRenderDistance(int distance) { for (int y = 0; y < realRenderDistance; y++) for (int z = 0; z < realRenderDistance; z++) { var slot = new ChunkRenderSlot(Client, new ivec3(x, y, z) - distance); - slot.Move(renderPosition); + slot.Move(renderPosition, chunks); this[x, y, z] = slot; } @@ -141,10 +145,16 @@ public void SetRenderPosition(dvec3 worldPosition) { if (newPos == renderPosition || renderSlots == null) return; + renderPosition = newPos; + + chunks.Move(newPos); foreach (var slot in renderSlots) - slot.Move(renderPosition); + slot.Move(renderPosition, chunks); + + //Sort by distance so that closer chunks are rebuilt first. + Array.Sort(renderSlots, (a, b) => a.RelativePosition.LengthSqr.CompareTo(b.RelativePosition.LengthSqr)); } public override void Dispose() { diff --git a/Client/VoxelClient.cs b/Client/VoxelClient.cs index afe2195..25aac7c 100644 --- a/Client/VoxelClient.cs +++ b/Client/VoxelClient.cs @@ -96,6 +96,8 @@ public override void OnTick() { inputDir /= 4; camera.MoveAndSlide(world!, inputDir); + + GameRenderer.WorldRenderer.ChunkRenderer.SetRenderPosition(camera.position); } public override void OnWindowResize() {