private void RenderBlocks(GameClient gameClient) { GL.UseProgram(_cubeShader.Value.Id); GL.UniformMatrix4(0, false, ref _projectionMatrix); GL.UniformMatrix4(4, false, ref _modelViewMatrix); var cameraChunkPos = (ChunkPos)gameClient.PositionData.Placement.Pos; var offset = (gameClient.PositionData.Placement.Pos - EntityPos.Origin) + new EntityOffset(0, gameClient.PhysicsValues.PlayerEyeHeight, 0); int chunkUpdates = 0; ChunkPos.IterateOutwards( cameraChunkPos, ChunkViewRadiusXZ, ChunkViewRadiusY, chunkPos => { ChunkBufferEntry entry; _chunkBuffers.TryGetValue(chunkPos, out entry); /* Don't let nearby entries expire. */ if (entry != null) { entry.LastAccess = _currentFrameTime; } if (!IsInViewingFrustum(gameClient, offset, chunkPos)) { return; } var chunk = gameClient.World.PeekChunk(chunkPos); if (chunk != null && chunk.HasData) { if (entry == null) { entry = new ChunkBufferEntry { LastAccess = _currentFrameTime }; _chunkBuffers[chunkPos] = entry; } if (entry.ContentHash != chunk.ContentHash) { if (chunkUpdates < 5 && entry.TriangleTask != null && entry.TriangleTask.IsCompleted) { var triangles = entry.TriangleTask.Result; if (entry.TriangleTaskContentHash == chunk.ContentHash) { ++chunkUpdates; if (entry.VertexArray == null) { entry.VertexArray = new VertexArray(_cubeVertexSpecification); } entry.VertexArray.SetData(triangles, BufferUsageHint.StaticDraw); entry.ContentHash = chunk.ContentHash; } triangles.Dispose(); entry.TriangleTask = null; entry.TriangleTaskContentHash = 0; } if (entry.ContentHash != chunk.ContentHash && entry.TriangleTask == null) { var triangleBuffer = new TriangleBuffer(_cubeVertexSpecification); var localChunk = chunk; entry.TriangleTask = Task.Run(() => { RenderChunk(triangleBuffer, localChunk); return(triangleBuffer); }); entry.TriangleTaskContentHash = chunk.ContentHash; } } entry.VertexArray?.Draw(); } }); GL.UseProgram(0); RemoveExpiredChunks(); }
private void RenderBlocks(GameClient gameClient) { GL.UseProgram(_cubeShader.Value.Id); GL.UniformMatrix4(0, false, ref _projectionMatrix); GL.UniformMatrix4(4, false, ref _modelViewMatrix); var cameraChunkPos = (ChunkPos)gameClient.PositionData.Placement.Pos; var offset = (gameClient.PositionData.Placement.Pos - EntityPos.Origin) + new EntityOffset(0, gameClient.PhysicsValues.PlayerEyeHeight, 0); int chunkUpdates = 0; ChunkPos.IterateOutwards( cameraChunkPos, ChunkViewRadiusXZ, ChunkViewRadiusY, chunkPos => { ChunkBufferEntry entry; _chunkBuffers.TryGetValue(chunkPos, out entry); /* Don't let nearby entries expire. */ if (entry != null) entry.LastAccess = _currentFrameTime; if (!IsInViewingFrustum(gameClient, offset, chunkPos)) return; var chunk = gameClient.World.PeekChunk(chunkPos); if (chunk != null && chunk.HasData) { if (entry == null) { entry = new ChunkBufferEntry { LastAccess = _currentFrameTime }; _chunkBuffers[chunkPos] = entry; } if (entry.ContentHash != chunk.ContentHash) { if (chunkUpdates < 5 && entry.TriangleTask != null && entry.TriangleTask.IsCompleted) { var triangles = entry.TriangleTask.Result; if (entry.TriangleTaskContentHash == chunk.ContentHash) { ++chunkUpdates; if (entry.VertexArray == null) entry.VertexArray = new VertexArray(_cubeVertexSpecification); entry.VertexArray.SetData(triangles, BufferUsageHint.StaticDraw); entry.ContentHash = chunk.ContentHash; } triangles.Dispose(); entry.TriangleTask = null; entry.TriangleTaskContentHash = 0; } if (entry.ContentHash != chunk.ContentHash && entry.TriangleTask == null) { var triangleBuffer = new TriangleBuffer(_cubeVertexSpecification); var localChunk = chunk; entry.TriangleTask = Task.Run(() => { RenderChunk(triangleBuffer, localChunk); return triangleBuffer; }); entry.TriangleTaskContentHash = chunk.ContentHash; } } entry.VertexArray?.Draw(); } }); GL.UseProgram(0); RemoveExpiredChunks(); }