Advertisement
Fiskmans

MarchingCubes.cs

Apr 19th, 2025 (edited)
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.76 KB | Source Code | 0 0
  1. internal class MarchingCubes
  2. {
  3.     RenderingDevice myRenderDevice;
  4.     Vector3I mySize;
  5.     uint myMaxTris;
  6.     byte[] myCPUNodeData;
  7.     int myDataSize;
  8.     byte[] myCPUTriData;
  9.     int myTriDataSize;
  10.     static readonly int StaticDataSize = sizeof(uint) * 4;
  11.     static readonly int UniformDataSize = sizeof(uint);
  12.  
  13.     Rid myComputeShaderId;
  14.  
  15.     Rid myGPUStaticBufferId;
  16.     Rid myGPUUniformBufferId;
  17.     Rid myGPUDataBufferId;
  18.  
  19.     Rid myGPUTriBufferOutputId;
  20.     Rid myUniformSetId;
  21.     Rid myPipelineId;
  22.  
  23.     public MarchingCubes(Vector3I aSize)
  24.     {
  25.         myRenderDevice = RenderingServer.CreateLocalRenderingDevice();
  26.         mySize = aSize;
  27.         myDataSize = Utils.CountPoints(aSize) * sizeof(int);
  28.         myMaxTris = (uint)Math.Max(Utils.CountPoints(aSize - Vector3I.One), 64);
  29.         myTriDataSize = (int)myMaxTris * sizeof(float) * 3 * 3;
  30.  
  31.         myCPUNodeData = new byte[myDataSize];
  32.         myCPUTriData = new byte[myTriDataSize];
  33.  
  34.  
  35.         // Load GLSL shader
  36.         RDShaderFile shaderFile = GD.Load<RDShaderFile>("res://Shaders/Compute/MarchingCubes.glsl");
  37.         RDShaderSpirV shaderBytecode = shaderFile.GetSpirV();
  38.         myComputeShaderId = myRenderDevice.ShaderCreateFromSpirV(shaderBytecode);
  39.  
  40.         uint[] staticData = [(uint)aSize.X, (uint)aSize.Y, (uint)aSize.Z, (uint)myMaxTris];
  41.         byte[] staticDataRaw = new byte[StaticDataSize];
  42.  
  43.         Buffer.BlockCopy(staticData, 0, staticDataRaw, 0, StaticDataSize);
  44.  
  45.         myGPUStaticBufferId = myRenderDevice.StorageBufferCreate((uint)StaticDataSize, staticDataRaw);
  46.         myGPUUniformBufferId = myRenderDevice.StorageBufferCreate((uint)UniformDataSize);
  47.         myGPUDataBufferId = myRenderDevice.StorageBufferCreate((uint)myCPUNodeData.Length);
  48.         myGPUTriBufferOutputId = myRenderDevice.StorageBufferCreate((uint)myCPUTriData.Length);
  49.  
  50.         RDUniform staticDataBinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 0 };
  51.         staticDataBinding.AddId(myGPUStaticBufferId);
  52.  
  53.         RDUniform uniformDatabinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 1 };
  54.         uniformDatabinding.AddId(myGPUUniformBufferId);
  55.  
  56.         RDUniform dataBinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 2 };
  57.         dataBinding.AddId(myGPUDataBufferId);
  58.  
  59.         RDUniform triOutputbinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 3 };
  60.         triOutputbinding.AddId(myGPUTriBufferOutputId);
  61.  
  62.         myUniformSetId = myRenderDevice.UniformSetCreate([staticDataBinding, uniformDatabinding, dataBinding, triOutputbinding], myComputeShaderId, 0);
  63.  
  64.         myPipelineId = myRenderDevice.ComputePipelineCreate(myComputeShaderId);
  65.         // TODO: do this
  66.     }
  67.  
  68.  
  69.     public Godot.Vector3[] Calculate(int[,,] aValues, uint aSurface = 128, float aScale = 1.0f)
  70.     {
  71.         if (aValues.GetLength(0) != mySize.X) { throw new ArgumentException("X-Axis size missmatch"); }
  72.         if (aValues.GetLength(1) != mySize.Y) { throw new ArgumentException("Y-Axis size missmatch"); }
  73.         if (aValues.GetLength(2) != mySize.Z) { throw new ArgumentException("Z-Axis size missmatch"); }
  74.  
  75.         uint[] uniformData = [aSurface];
  76.         byte[] uniformRaw = new byte[uniformData.Length * sizeof(uint)];
  77.         Buffer.BlockCopy(uniformData, 0, uniformRaw, 0, uniformRaw.Length);
  78.  
  79.         myRenderDevice.BufferUpdate(myGPUUniformBufferId, 0, (uint)UniformDataSize, uniformRaw);
  80.  
  81.         Buffer.BlockCopy(aValues, 0, myCPUNodeData, 0, myDataSize);
  82.         myRenderDevice.BufferUpdate(myGPUDataBufferId, 0, (uint)myCPUNodeData.Length, myCPUNodeData);
  83.  
  84.         long computeListIndex = myRenderDevice.ComputeListBegin();
  85.         myRenderDevice.ComputeListBindComputePipeline(computeListIndex, myPipelineId);
  86.         myRenderDevice.ComputeListBindUniformSet(computeListIndex, myUniformSetId, 0);
  87.         myRenderDevice.ComputeListDispatch(computeListIndex, xGroups: (uint)mySize.X - 1, yGroups: (uint)mySize.Y - 1, zGroups: (uint)mySize.Z - 1);
  88.         myRenderDevice.ComputeListEnd();
  89.  
  90.         myRenderDevice.Submit();
  91.         myRenderDevice.Sync();
  92.  
  93.         byte[] outputBytes = myRenderDevice.BufferGetData(myGPUTriBufferOutputId);
  94.  
  95.         float[] resultFloats = new float[12 /*TODO figure this one out assumes one tri for now*/];
  96.  
  97.         Buffer.BlockCopy(outputBytes, 0, resultFloats, 0, resultFloats.Length * sizeof(float));
  98.  
  99.         Godot.Vector3[] result = new Godot.Vector3[resultFloats.Length / 4];
  100.  
  101.         for (int i = 0; i < result.Length; i++)
  102.         {
  103.             result[i] = new Godot.Vector3(resultFloats[i * 4 + 0], resultFloats[i * 4 + 1], resultFloats[i * 4 + 2]);
  104.         }
  105.  
  106.         return result;
  107.     }
  108.  
  109. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement