Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using UnityEngine;
- using UnityEngine.Rendering;
- using Object = UnityEngine.Object;
- namespace MarchingCubesAlgorithm
- {
- public static class GPUMarchingCubes
- {
- private static ComputeShader marchingCubesCompute;
- private static ComputeBuffer caseToNumTrisBuf;
- private static ComputeBuffer caseToTriEdgesBuf;
- private static ComputeBuffer edgeToCornersBuf;
- private static GraphicsBuffer verticesBuf;
- private static GraphicsBuffer indicesBuf;
- private static ComputeBuffer vertexCounterBuf;
- private static ComputeBuffer debugBuf;
- private static Mesh mesh;
- private static readonly int VOXEL_GRID = Shader.PropertyToID("voxelGrid");
- private static readonly int DEBUG_BUFFER = Shader.PropertyToID("debugBuffer");
- private static readonly int GRID_SIZE = Shader.PropertyToID("gridSize");
- private static readonly int STEP_SIZE = Shader.PropertyToID("stepSize");
- private static readonly int CASE_TO_NUM_TRIS = Shader.PropertyToID("caseToNumTris");
- private static readonly int CASE_TO_TRI_EDGES = Shader.PropertyToID("caseToTriEdges");
- private static readonly int EDGE_TO_CORNERS = Shader.PropertyToID("edgeToCorners");
- private static readonly int VERTICES = Shader.PropertyToID("vertexBuffer");
- private static readonly int INDICES = Shader.PropertyToID("indexBuffer");
- private static readonly int VERTEX_COUNTER = Shader.PropertyToID("triangleCounter");
- public static void Initialize(ComputeShader marchingCubesCompute, Vector3Int voxelGridSize)
- {
- GPUMarchingCubes.marchingCubesCompute = marchingCubesCompute;
- Dispose();
- caseToNumTrisBuf = new ComputeBuffer(256, sizeof(int));
- caseToTriEdgesBuf = new ComputeBuffer(3840, sizeof(int));
- edgeToCornersBuf = new ComputeBuffer(24, sizeof(int) * 3);
- caseToNumTrisBuf.SetData(LookupTables.caseToNumTris);
- caseToTriEdgesBuf.SetData(LookupTables.caseToTriEdges1D);
- edgeToCornersBuf.SetData(LookupTables.nativeEdgeToCorners);
- marchingCubesCompute.SetBuffer(0, CASE_TO_NUM_TRIS, caseToNumTrisBuf);
- marchingCubesCompute.SetBuffer(0, CASE_TO_TRI_EDGES, caseToTriEdgesBuf);
- marchingCubesCompute.SetBuffer(0, EDGE_TO_CORNERS, edgeToCornersBuf);
- int numVoxels = voxelGridSize.x * voxelGridSize.y * voxelGridSize.z;
- int maxVertexCount = numVoxels * 5 * 3;
- AllocateMesh(maxVertexCount);
- vertexCounterBuf = new ComputeBuffer(1, sizeof(uint), ComputeBufferType.Counter);
- vertexCounterBuf.SetCounterValue(0);
- marchingCubesCompute.SetBuffer(0, VERTEX_COUNTER, vertexCounterBuf);
- debugBuf = new ComputeBuffer(numVoxels, sizeof(float) * 3);
- marchingCubesCompute.SetBuffer(0, DEBUG_BUFFER, debugBuf);
- }
- public static Mesh GenerateMesh(ComputeBuffer voxelGridBuf, Vector3Int voxelGridSize, int stepSize)
- {
- if (!marchingCubesCompute)
- throw new ArgumentException(
- "ComputeShader has not been initialized. You should call Initialize() before GenerateMesh()");
- vertexCounterBuf.SetCounterValue(0);
- marchingCubesCompute.SetBuffer(0, VERTICES, verticesBuf);
- marchingCubesCompute.SetBuffer(0, INDICES, indicesBuf);
- marchingCubesCompute.SetBuffer(0, VOXEL_GRID, voxelGridBuf);
- marchingCubesCompute.SetInts(GRID_SIZE, voxelGridSize.x, voxelGridSize.y, voxelGridSize.z);
- marchingCubesCompute.SetInt(STEP_SIZE, stepSize);
- int threadGroupsX = Mathf.FloorToInt(voxelGridSize.x / 8);
- int threadGroupsY = Mathf.FloorToInt(voxelGridSize.y / 8);
- int threadGroupsZ = Mathf.FloorToInt(voxelGridSize.z / 8);
- marchingCubesCompute.Dispatch(0, threadGroupsX, threadGroupsY, threadGroupsZ);
- voxelGridBuf.Dispose();
- Debug.Log("Num vertices: " + GetAppendBufferCount(vertexCounterBuf));
- int numVoxels = voxelGridSize.x * voxelGridSize.y * voxelGridSize.z;
- int maxVertexCount = numVoxels * 5 * 3;
- int[] cpuIndices = new int[maxVertexCount];
- indicesBuf.GetData(cpuIndices);
- bool allZero = true;
- for (int i = 0; i < cpuIndices.Length; i++)
- {
- if (cpuIndices[i] != 0)
- {
- allZero = false;
- break;
- }
- }
- Debug.Log(allZero);
- mesh.bounds = new Bounds(Vector3.zero, voxelGridSize);
- return Object.Instantiate(mesh);
- }
- public static void Dispose()
- {
- caseToNumTrisBuf?.Dispose();
- caseToTriEdgesBuf?.Dispose();
- edgeToCornersBuf?.Dispose();
- verticesBuf?.Dispose();
- indicesBuf?.Dispose();
- vertexCounterBuf?.Dispose();
- Object.Destroy(mesh);
- }
- private static void AllocateMesh(int vertexCount)
- {
- mesh = new Mesh();
- // We want GraphicsBuffer access as Raw (ByteAddress) buffers.
- mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw;
- mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
- // Vertex position
- VertexAttributeDescriptor vp = new(VertexAttribute.Position);
- // Vertex/index buffer formats
- mesh.SetVertexBufferParams(vertexCount, vp);
- mesh.SetIndexBufferParams(vertexCount, IndexFormat.UInt32);
- // Submesh initialization
- mesh.SetSubMesh(0, new SubMeshDescriptor(0, vertexCount),
- MeshUpdateFlags.DontRecalculateBounds);
- // GraphicsBuffer references
- verticesBuf = mesh.GetVertexBuffer(0);
- indicesBuf = mesh.GetIndexBuffer();
- }
- private static int GetAppendBufferCount(ComputeBuffer appendBuffer)
- {
- ComputeBuffer countBuffer = new(1, sizeof(int), ComputeBufferType.IndirectArguments);
- ComputeBuffer.CopyCount(appendBuffer, countBuffer, 0);
- int[] countArray = { 0 };
- countBuffer.GetData(countArray);
- countBuffer.Release();
- return countArray[0];
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement