Major refactor and organization, optimizations to chunk, world and renderer
This commit is contained in:
149
Graphics/Renderer.cs
Normal file
149
Graphics/Renderer.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using OpenTK.Mathematics;
|
||||
using Voxel.Core;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace Voxel.Graphics
|
||||
{
|
||||
static class Renderer
|
||||
{
|
||||
private static int _ssbo;
|
||||
private static int _vao;
|
||||
private static bool _buffersDirty;
|
||||
|
||||
private static Dictionary<(int, int), int> _chunkBufferSizes = new Dictionary<(int, int), int>();
|
||||
private static Shader _shader;
|
||||
private static readonly Texture _texture;
|
||||
private static World? _world;
|
||||
|
||||
static Renderer()
|
||||
{
|
||||
string vertexPath = "Shaders/shader.vert";
|
||||
string fragmentPath = "Shaders/shader.frag";
|
||||
string texturePath = "Assets/atlas.png";
|
||||
|
||||
_shader = new Shader(vertexPath, fragmentPath);
|
||||
_texture = new Texture(texturePath);
|
||||
|
||||
_shader.SetInt("uTexture", 0);
|
||||
|
||||
_ssbo = GL.GenBuffer();
|
||||
_vao = GL.GenVertexArray();
|
||||
|
||||
GL.BindVertexArray(_vao);
|
||||
GL.BindBuffer(BufferTarget.ShaderStorageBuffer, _ssbo);
|
||||
|
||||
GL.BufferData(BufferTarget.ShaderStorageBuffer, 1024 * 1024 * 128, IntPtr.Zero, BufferUsageHint.DynamicDraw);
|
||||
GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 0, _ssbo);
|
||||
}
|
||||
|
||||
public static void Render()
|
||||
{
|
||||
GL.BindVertexArray(_vao);
|
||||
GL.BindBuffer(BufferTarget.ShaderStorageBuffer, _ssbo);
|
||||
|
||||
_shader.Use();
|
||||
_shader.SetMatrix4("view", Camera.view);
|
||||
_shader.SetVector3("cameraPosition", Camera.Position);
|
||||
_shader.SetMatrix4("projection", Camera.projection);
|
||||
|
||||
if (_buffersDirty)
|
||||
{
|
||||
UpdateAllChunksBuffer();
|
||||
_buffersDirty = false;
|
||||
}
|
||||
|
||||
RenderWorld();
|
||||
RenderUi();
|
||||
}
|
||||
|
||||
public static void UpdateChunkBuffer(Chunk chunk)
|
||||
{
|
||||
if (_world == null || !_chunkBufferSizes.TryGetValue((chunk.X, chunk.Y), out int faceOffset))
|
||||
return;
|
||||
|
||||
ChunkMesh chunkMesh = chunk.GetChunkMesh();
|
||||
byte[] data = chunkMesh.GetPackedData();
|
||||
|
||||
int newByteSize = chunkMesh.Size * 4;
|
||||
int currentAllocatedBytes = GetAllocatedSizeForChunk(chunk.X, chunk.Y);
|
||||
|
||||
if (newByteSize <= currentAllocatedBytes)
|
||||
{
|
||||
GL.BindBuffer(BufferTarget.ShaderStorageBuffer, _ssbo);
|
||||
GL.BufferSubData(BufferTarget.ShaderStorageBuffer, (IntPtr)(faceOffset * 4), newByteSize, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
MarkBuffersDirty();
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetAllocatedSizeForChunk(int x, int y)
|
||||
{
|
||||
// todo, memory manager
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void UpdateAllChunksBuffer()
|
||||
{
|
||||
if (_world == null) return;
|
||||
|
||||
_chunkBufferSizes.Clear();
|
||||
int faceOffset = 0;
|
||||
|
||||
foreach (Chunk chunk in _world.GetAllChunks())
|
||||
{
|
||||
ChunkMesh chunkMesh = chunk.GetChunkMesh();
|
||||
|
||||
_chunkBufferSizes[(chunk.X, chunk.Y)] = faceOffset;
|
||||
|
||||
byte[] data = chunkMesh.GetPackedData();
|
||||
|
||||
GL.BufferSubData(BufferTarget.ShaderStorageBuffer,
|
||||
(IntPtr)(faceOffset * 4), // faceOffset * 4 = byte offset
|
||||
chunkMesh.Size * 4,
|
||||
data
|
||||
);
|
||||
|
||||
faceOffset += chunkMesh.Size;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderUi()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static void RenderWorld()
|
||||
{
|
||||
if (_world == null) return;
|
||||
|
||||
foreach (Chunk chunk in _world.GetAllChunks())
|
||||
{
|
||||
ChunkMesh chunkMesh = chunk.GetChunkMesh();
|
||||
|
||||
if (chunkMesh.Size == 0) continue;
|
||||
|
||||
if (!_chunkBufferSizes.TryGetValue((chunk.X, chunk.Y), out int offset)) continue;
|
||||
|
||||
_shader.SetInt("chunkX", chunk.X);
|
||||
_shader.SetInt("chunkY", chunk.Y);
|
||||
|
||||
//GL.MemoryBarrier(MemoryBarrierFlags.ShaderStorageBarrierBit);
|
||||
GL.DrawArrays(PrimitiveType.Triangles, offset * 6, chunkMesh.Size * 6);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetWorld(World world)
|
||||
{
|
||||
_world = world;
|
||||
_buffersDirty = true;
|
||||
}
|
||||
|
||||
public static void MarkBuffersDirty()
|
||||
{
|
||||
_buffersDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user