Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using GamePlay;
- using R3;
- using Reflex.Attributes;
- using UnityEditor;
- using UnityEngine;
- using UnityEngine.UI;
- using VoxelMap;
- namespace UI
- {
- public class WorldMap : MonoBehaviour
- {
- private const int ColumnPerFrame = 1;
- private const string ClearHeight = "ClearHeight";
- private const string UpdateHeight = "UpdateHeight";
- private const string UpdateChunk = "UpdateChunk";
- private static readonly int HeightBuffer = Shader.PropertyToID("HeightBuffer");
- private static readonly int VertexBuffer = Shader.PropertyToID("VertexBuffer");
- private static readonly int MapTexture = Shader.PropertyToID("MapTexture");
- private static readonly int MeshPositionOffset = Shader.PropertyToID("MeshPositionOffset");
- private static readonly int ChunkSize = Shader.PropertyToID("ChunkSize");
- [SerializeField] private ComputeShader computeShader;
- [SerializeField] private RawImage mapImage;
- private MapProvider _mapProvider;
- private EntityContainerService _entityContainer;
- private ComputeBuffer _heightBuffer;
- private int _updateHeightKernel;
- private int _updateChunkKernel;
- private int _clearHeightKernel;
- [field: SerializeField] public CanvasGroup CanvasGroup { get; private set; }
- public RenderTexture MainTexture { get; private set; }
- private readonly Queue<(int x, int z)> _regeneratingColumns = new Queue<(int x, int z)>();
- [Inject]
- private void Construct(MapProvider mapProvider)
- {
- _mapProvider = mapProvider;
- _heightBuffer = new ComputeBuffer(Chunk.ChunkSizeSquared, sizeof(uint));
- _clearHeightKernel = computeShader.FindKernel(ClearHeight);
- _updateHeightKernel = computeShader.FindKernel(UpdateHeight);
- _updateChunkKernel = computeShader.FindKernel(UpdateChunk);
- computeShader.SetFloat(ChunkSize, Chunk.ChunkSize);
- }
- public void Initialize()
- {
- if (MainTexture != null)
- {
- MainTexture.Release();
- }
- MainTexture = new RenderTexture(_mapProvider.Map.Width, _mapProvider.Map.Depth, 0, RenderTextureFormat.ARGB32)
- {
- enableRandomWrite = true,
- filterMode = FilterMode.Point
- };
- MainTexture.Create();
- mapImage.texture = MainTexture;
- _mapProvider.Map.ChunkUpdated.Subscribe(OnChunkUpdated).AddTo(_mapProvider.Map);
- _regeneratingColumns.Clear();
- for (int x = 0; x < _mapProvider.Map.Width / Chunk.ChunkSize; x++)
- {
- for (var z = 0; z < _mapProvider.Map.Depth / Chunk.ChunkSize; z++)
- {
- _regeneratingColumns.Enqueue((x, z));
- }
- }
- }
- private void Update()
- {
- if (_mapProvider.Map == null)
- {
- return;
- }
- for (var i = 0; i < Math.Min(_regeneratingColumns.Count, ColumnPerFrame); i++)
- {
- (int x, int z) = _regeneratingColumns.Dequeue();
- RefreshChunkColumn(x, z);
- }
- }
- private void RefreshChunkColumn(int x, int z)
- {
- computeShader.SetBuffer(_clearHeightKernel, HeightBuffer, _heightBuffer);
- computeShader.Dispatch(_clearHeightKernel, Chunk.ChunkSize / 8, Chunk.ChunkSize / 8, 1);
- for (var y = 0; y < _mapProvider.Map.Height / Chunk.ChunkSize; y++)
- {
- int chunkIndex = GetChunkIndex(x, y, z);
- Chunk chunk = _mapProvider.Map.Chunks[chunkIndex];
- if (chunk.Mesh.vertexCount == 0)
- {
- continue;
- }
- chunk.Mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
- using GraphicsBuffer vertexBuffer = chunk.Mesh.GetVertexBuffer(0);
- int quadCount = chunk.Mesh.vertexCount / 4;
- computeShader.SetBuffer(_updateHeightKernel, VertexBuffer, vertexBuffer);
- computeShader.SetBuffer(_updateHeightKernel, HeightBuffer, _heightBuffer);
- computeShader.SetFloats(MeshPositionOffset, chunk.Position.x, chunk.Position.y, chunk.Position.z);
- computeShader.Dispatch(_updateHeightKernel, Mathf.Max(1, quadCount / 16), 1, 1);
- computeShader.SetBuffer(_updateChunkKernel, VertexBuffer, vertexBuffer);
- computeShader.SetBuffer(_updateChunkKernel, HeightBuffer, _heightBuffer);
- computeShader.SetTexture(_updateChunkKernel, MapTexture, MainTexture);
- computeShader.SetFloats(MeshPositionOffset, chunk.Position.x, chunk.Position.y, chunk.Position.z);
- computeShader.Dispatch(_updateChunkKernel, Mathf.Max(1, quadCount / 16), 1, 1);
- }
- }
- private void OnChunkUpdated(Chunk chunk)
- {
- _regeneratingColumns.Enqueue((chunk.Position.x / Chunk.ChunkSize, chunk.Position.z / Chunk.ChunkSize));
- }
- private int GetChunkIndex(int x, int y, int z)
- {
- return x * (_mapProvider.Map.Height * _mapProvider.Map.Depth / Chunk.ChunkSizeSquared)
- + y * (_mapProvider.Map.Depth / Chunk.ChunkSize) + z;
- }
- private void OnDestroy()
- {
- _heightBuffer.Release();
- MainTexture.Release();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment