Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- internal class MarchingCubes
- {
- RenderingDevice myRenderDevice;
- Vector3I mySize;
- uint myMaxTris;
- byte[] myCPUNodeData;
- int myDataSize;
- byte[] myCPUTriData;
- int myTriDataSize;
- static readonly int StaticDataSize = sizeof(uint) * 4;
- static readonly int UniformDataSize = sizeof(uint);
- Rid myComputeShaderId;
- Rid myGPUStaticBufferId;
- Rid myGPUUniformBufferId;
- Rid myGPUDataBufferId;
- Rid myGPUTriBufferOutputId;
- Rid myUniformSetId;
- Rid myPipelineId;
- public MarchingCubes(Vector3I aSize)
- {
- myRenderDevice = RenderingServer.CreateLocalRenderingDevice();
- mySize = aSize;
- myDataSize = Utils.CountPoints(aSize) * sizeof(int);
- myMaxTris = (uint)Math.Max(Utils.CountPoints(aSize - Vector3I.One), 64);
- myTriDataSize = (int)myMaxTris * sizeof(float) * 3 * 3;
- myCPUNodeData = new byte[myDataSize];
- myCPUTriData = new byte[myTriDataSize];
- // Load GLSL shader
- RDShaderFile shaderFile = GD.Load<RDShaderFile>("res://Shaders/Compute/MarchingCubes.glsl");
- RDShaderSpirV shaderBytecode = shaderFile.GetSpirV();
- myComputeShaderId = myRenderDevice.ShaderCreateFromSpirV(shaderBytecode);
- uint[] staticData = [(uint)aSize.X, (uint)aSize.Y, (uint)aSize.Z, (uint)myMaxTris];
- byte[] staticDataRaw = new byte[StaticDataSize];
- Buffer.BlockCopy(staticData, 0, staticDataRaw, 0, StaticDataSize);
- myGPUStaticBufferId = myRenderDevice.StorageBufferCreate((uint)StaticDataSize, staticDataRaw);
- myGPUUniformBufferId = myRenderDevice.StorageBufferCreate((uint)UniformDataSize);
- myGPUDataBufferId = myRenderDevice.StorageBufferCreate((uint)myCPUNodeData.Length);
- myGPUTriBufferOutputId = myRenderDevice.StorageBufferCreate((uint)myCPUTriData.Length);
- RDUniform staticDataBinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 0 };
- staticDataBinding.AddId(myGPUStaticBufferId);
- RDUniform uniformDatabinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 1 };
- uniformDatabinding.AddId(myGPUUniformBufferId);
- RDUniform dataBinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 2 };
- dataBinding.AddId(myGPUDataBufferId);
- RDUniform triOutputbinding = new RDUniform { UniformType = RenderingDevice.UniformType.StorageBuffer, Binding = 3 };
- triOutputbinding.AddId(myGPUTriBufferOutputId);
- myUniformSetId = myRenderDevice.UniformSetCreate([staticDataBinding, uniformDatabinding, dataBinding, triOutputbinding], myComputeShaderId, 0);
- myPipelineId = myRenderDevice.ComputePipelineCreate(myComputeShaderId);
- // TODO: do this
- }
- public Godot.Vector3[] Calculate(int[,,] aValues, uint aSurface = 128, float aScale = 1.0f)
- {
- if (aValues.GetLength(0) != mySize.X) { throw new ArgumentException("X-Axis size missmatch"); }
- if (aValues.GetLength(1) != mySize.Y) { throw new ArgumentException("Y-Axis size missmatch"); }
- if (aValues.GetLength(2) != mySize.Z) { throw new ArgumentException("Z-Axis size missmatch"); }
- uint[] uniformData = [aSurface];
- byte[] uniformRaw = new byte[uniformData.Length * sizeof(uint)];
- Buffer.BlockCopy(uniformData, 0, uniformRaw, 0, uniformRaw.Length);
- myRenderDevice.BufferUpdate(myGPUUniformBufferId, 0, (uint)UniformDataSize, uniformRaw);
- Buffer.BlockCopy(aValues, 0, myCPUNodeData, 0, myDataSize);
- myRenderDevice.BufferUpdate(myGPUDataBufferId, 0, (uint)myCPUNodeData.Length, myCPUNodeData);
- long computeListIndex = myRenderDevice.ComputeListBegin();
- myRenderDevice.ComputeListBindComputePipeline(computeListIndex, myPipelineId);
- myRenderDevice.ComputeListBindUniformSet(computeListIndex, myUniformSetId, 0);
- myRenderDevice.ComputeListDispatch(computeListIndex, xGroups: (uint)mySize.X - 1, yGroups: (uint)mySize.Y - 1, zGroups: (uint)mySize.Z - 1);
- myRenderDevice.ComputeListEnd();
- myRenderDevice.Submit();
- myRenderDevice.Sync();
- byte[] outputBytes = myRenderDevice.BufferGetData(myGPUTriBufferOutputId);
- float[] resultFloats = new float[12 /*TODO figure this one out assumes one tri for now*/];
- Buffer.BlockCopy(outputBytes, 0, resultFloats, 0, resultFloats.Length * sizeof(float));
- Godot.Vector3[] result = new Godot.Vector3[resultFloats.Length / 4];
- for (int i = 0; i < result.Length; i++)
- {
- result[i] = new Godot.Vector3(resultFloats[i * 4 + 0], resultFloats[i * 4 + 1], resultFloats[i * 4 + 2]);
- }
- return result;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement