diff --git a/.forgejo/01plates.png b/.forgejo/01plates.png
new file mode 100644
index 0000000..e4f2679
--- /dev/null
+++ b/.forgejo/01plates.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4474dfe2656785d8df368dfc61a0b6dd11021c229669c64f9eddd2f790fb6c68
+size 126061
diff --git a/.forgejo/02oceans.png b/.forgejo/02oceans.png
new file mode 100644
index 0000000..2103f65
--- /dev/null
+++ b/.forgejo/02oceans.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c8d2626d214f70432668b55e5a17960f3519a8ef0f3f2cf968f7f4d5147220ea
+size 137088
diff --git a/.forgejo/03stresses.png b/.forgejo/03stresses.png
new file mode 100644
index 0000000..67479dd
--- /dev/null
+++ b/.forgejo/03stresses.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:53835e85efba47bcaa1a281bae7ae418260a521bb6bf3264a895d8f850656707
+size 140915
diff --git a/.forgejo/04planet.png b/.forgejo/04planet.png
new file mode 100644
index 0000000..b731a90
--- /dev/null
+++ b/.forgejo/04planet.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:283cfaaec5b21c34108035f533be87dcb4a13cef421427830f4a0a800291c6b6
+size 224211
diff --git a/.forgejo/export.png b/.forgejo/export.png
index 7fc3e36..c35cfe3 100644
--- a/.forgejo/export.png
+++ b/.forgejo/export.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:47b72f11557cf5b2060054f1d640bb42279a58ba34b3d9b37e25af10101e6bbb
-size 102368
+oid sha256:41ae2d919475771f50b155aab54e2dc6b2c3add357f3883908701f67c6922348
+size 613281
diff --git a/.forgejo/planet.png b/.forgejo/planet.png
deleted file mode 100644
index 99fb00b..0000000
--- a/.forgejo/planet.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:2ce30336f743e552d2820d9b328c530d2de2666d0fa748c27a9255917c6b1909
-size 262214
diff --git a/.forgejo/projection.png b/.forgejo/projection.png
index 8b2fe90..6d39d60 100644
--- a/.forgejo/projection.png
+++ b/.forgejo/projection.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5a3dc6ce3038331d578f5f804ce02cda5cc4e7a722c0dc8bf63240a23b7e5839
-size 770350
+oid sha256:71b10ccdc61002f7d6bd9ed1c6e0276db0422b5216cd0dbff92b026d70c9dc3f
+size 601515
diff --git a/.forgejo/time.png b/.forgejo/time.png
new file mode 100644
index 0000000..77424a3
--- /dev/null
+++ b/.forgejo/time.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9afa68b8851ca555076b0780734b0a03fe7af1ef4bfd6fed168d2c3c59518cd7
+size 208412
diff --git a/PlanetLow.mtl b/PlanetLow.mtl
deleted file mode 100644
index 84f636a..0000000
--- a/PlanetLow.mtl
+++ /dev/null
@@ -1,2 +0,0 @@
-# Blender 5.0.1 MTL File: 'None'
-# www.blender.org
diff --git a/README.md b/README.md
index c8dfb02..de93358 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
# Adatonics
-
+
+
+
+
+

Planet generation with simple plate tectonics.
diff --git a/adatonic.sln.DotSettings.user b/adatonic.sln.DotSettings.user
index ceb9423..5f589d5 100644
--- a/adatonic.sln.DotSettings.user
+++ b/adatonic.sln.DotSettings.user
@@ -1,6 +1,8 @@
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
- ForceIncluded
\ No newline at end of file
+ ForceIncluded
+ ForceIncluded
\ No newline at end of file
diff --git a/project.godot b/project.godot
index 23d21db..414f41a 100644
--- a/project.godot
+++ b/project.godot
@@ -50,5 +50,3 @@ mouse_secondary={
[rendering]
rendering_device/driver.windows="d3d12"
-renderer/rendering_method="gl_compatibility"
-renderer/rendering_method.mobile="gl_compatibility"
diff --git a/shaders/compute/PlateExpansion.glsl b/shaders/compute/PlateExpansion.glsl
new file mode 100644
index 0000000..32990c4
--- /dev/null
+++ b/shaders/compute/PlateExpansion.glsl
@@ -0,0 +1,40 @@
+#[compute]
+#version 450
+// Invocations in the (x, y, z) dimension
+layout(local_size_x = 25, local_size_y = 1, local_size_z = 1) in;
+
+// A binding to the buffer we create in our script
+layout(set = 0, binding = 0, std430) restrict buffer PointBuffer {
+ int points[];
+}
+pointbuffer;
+layout(set = 0, binding = 1, std430) restrict buffer NeighborBuffer {
+ int neighbors[];
+}
+neighborbuffer;
+layout(set = 0, binding = 2, std430) restrict buffer PlateBuffer {
+ int plateid[];
+}
+platebuffer;
+
+// The code we want to execute in each invocation
+void main() {
+ // Iteration is gl_GlobalInvocationID.x
+ // Neighbors for Point gl_GlobalInvocationID.y
+ for (int point = 0; point < int(gl_WorkGroupSize.x); point++)
+ {
+ int localpoint = int(gl_WorkGroupID.x)*int(gl_WorkGroupSize.x) + point;
+ for (int neighbor = 0; neighbor < 6; neighbor++) {
+ if (neighborbuffer.neighbors[localpoint*6+neighbor] == -1)
+ {
+ continue;
+ }
+ if (platebuffer.plateid[localpoint] != -1 && platebuffer.plateid[neighborbuffer.neighbors[localpoint*6+neighbor]] == -1)
+ {
+ // Neighbor unclaimed, and we can claim it.
+ platebuffer.plateid[neighborbuffer.neighbors[localpoint*6+neighbor]] = platebuffer.plateid[localpoint];
+ }
+ }
+ }
+
+}
diff --git a/shaders/compute/PlateExpansion.glsl.import b/shaders/compute/PlateExpansion.glsl.import
new file mode 100644
index 0000000..8be2164
--- /dev/null
+++ b/shaders/compute/PlateExpansion.glsl.import
@@ -0,0 +1,14 @@
+[remap]
+
+importer="glsl"
+type="RDShaderFile"
+uid="uid://cypd2lshixd17"
+path="res://.godot/imported/PlateExpansion.glsl-9047ef54068b6d1a50f93c2cd303b382.res"
+
+[deps]
+
+source_file="res://shaders/compute/PlateExpansion.glsl"
+dest_files=["res://.godot/imported/PlateExpansion.glsl-9047ef54068b6d1a50f93c2cd303b382.res"]
+
+[params]
+
diff --git a/shaders/compute/compute_example.glsl b/shaders/compute/compute_example.glsl
new file mode 100644
index 0000000..c3e3ce3
--- /dev/null
+++ b/shaders/compute/compute_example.glsl
@@ -0,0 +1,17 @@
+#[compute]
+#version 450
+
+// Invocations in the (x, y, z) dimension
+layout(local_size_x = 2, local_size_y = 1, local_size_z = 1) in;
+
+// A binding to the buffer we create in our script
+layout(set = 0, binding = 0, std430) restrict buffer MyDataBuffer {
+ float data[];
+}
+my_data_buffer;
+
+// The code we want to execute in each invocation
+void main() {
+ // gl_GlobalInvocationID.x uniquely identifies this invocation across all work groups
+ my_data_buffer.data[gl_GlobalInvocationID.x] *= 2.0;
+}
diff --git a/shaders/compute/compute_example.glsl.import b/shaders/compute/compute_example.glsl.import
new file mode 100644
index 0000000..4dbf9d7
--- /dev/null
+++ b/shaders/compute/compute_example.glsl.import
@@ -0,0 +1,14 @@
+[remap]
+
+importer="glsl"
+type="RDShaderFile"
+uid="uid://du2kf2vmf800w"
+path="res://.godot/imported/compute_example.glsl-3f04b63d0b43774004ed10776fd05117.res"
+
+[deps]
+
+source_file="res://shaders/compute/compute_example.glsl"
+dest_files=["res://.godot/imported/compute_example.glsl-3f04b63d0b43774004ed10776fd05117.res"]
+
+[params]
+
diff --git a/src/Main.cs b/src/Main.cs
index 7d79a6d..9932642 100644
--- a/src/Main.cs
+++ b/src/Main.cs
@@ -1,10 +1,13 @@
#nullable enable
using Godot;
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
using Godot.Collections;
+using Array = System.Array;
public partial class Main : Control
{
@@ -39,6 +42,43 @@ public partial class Main : Control
Projector.GatherPoints(_planetHelper, int.Parse(GetNode("%Resolution").Text));
AxialTiltChanged(GetNode("%AxialTilt").Text);
UpdateTime();
+
+ _planetHelper.InitializeGeneration();
+ _planetHelper.Plates[0].Color = _planetHelper.GetInitialColor(true);
+ //_planetHelper.Plates[1].Color = _planetHelper.GetInitialColor(true);
+ //_planetHelper.Plates[2].Color = _planetHelper.GetInitialColor(false);
+ //_planetHelper.Plates[3].Color = _planetHelper.GetInitialColor(false);
+
+ // for (int i = 0; i < 1; i++)
+ // {
+ // for (int point = 0; point < points.Length; point++)
+ // {
+ // for (int neighbor = 0; neighbor < 6; neighbor++)
+ // {
+ // if (neighbors[point * 6 + neighbor] == -1)
+ // {
+ // continue;
+ // }
+ //
+ // int x = plateids[point];
+ // int y = neighbors[point * 6 + neighbor];
+ // int z = plateids[y];
+ // if (x != -1 && z == -1)
+ // {
+ // // Neighbor unclaimed, and we can claim it.
+ // plateids[neighbors[point * 6 +neighbor]] = plateids[point];
+ // }
+ // }
+ // }
+ // }
+ // int index = 0;
+ // foreach (int plate in plateids)
+ // {
+ // if (plate != -1)
+ // _planetHelper.Mdt.SetVertexColor(index, _planetHelper.Plates[plate].Color);
+ // index++;
+ // }
+ // _planetHelper.UpdateMesh();
}
Vector3 _pointerPosition = Vector3.Zero;
diff --git a/src/Oct.cs b/src/Oct.cs
index ce1722a..f1bf1fb 100644
--- a/src/Oct.cs
+++ b/src/Oct.cs
@@ -139,6 +139,10 @@ public class Oct
}
public bool IsInside(Vector3 position)
{
- return position > Start && position < Start + Extent;
+ Vector3 max = Start + Extent;
+
+ return position.X >= Start.X && position.X <= max.X &&
+ position.Y >= Start.Y && position.Y <= max.Y &&
+ position.Z >= Start.Z && position.Z <= max.Z;
}
}
\ No newline at end of file
diff --git a/src/PlanetHelper.cs b/src/PlanetHelper.cs
index 29efbf0..04f9a71 100644
--- a/src/PlanetHelper.cs
+++ b/src/PlanetHelper.cs
@@ -56,7 +56,7 @@ public class PlanetHelper
}
private bool StageComplete = true;
- private int _plateCount = 14;
+ private int _plateCount = 12;
private float _landRatio = 0.4f;
public List Plates = new List();
@@ -101,6 +101,9 @@ public class PlanetHelper
public Oct Octree = new Oct();
private Curve _remapCurve;
+ private RenderingDevice _rd;
+ private Rid _shader;
+
public PlanetHelper(MeshInstance3D meshInstance, TextureRect textureRect, Curve remapCurve)
{
_meshInstance = meshInstance;
@@ -132,6 +135,11 @@ public class PlanetHelper
textureShaderMaterial.SetShaderParameter("mode", 1);
}
UpdateMesh();
+
+ _rd = RenderingServer.CreateLocalRenderingDevice();
+ var shaderFile = GD.Load("res://shaders/compute/PlateExpansion.glsl");
+ var shaderBytecode = shaderFile.GetSpirV();
+ _shader = _rd.ShaderCreateFromSpirV(shaderBytecode);
}
public void InitializeGeneration()
@@ -156,7 +164,6 @@ public class PlanetHelper
VertexData vertex = Vertices.Where(v => v.PlateId == -1).OrderBy(v => Guid.NewGuid()).First();
vertex.PlateId = i;
var color = new Color(RandF(0f, 1f), RandF(0f, 1f), RandF(0f, 1f));
- ColorVertex(vertex.Id, color);
PlateData plate = new PlateData(i, color, false, [vertex.Id]);
plate.MovementAxis = GetRandomVector3();
@@ -168,7 +175,7 @@ public class PlanetHelper
public IEnumerable GetNeighboringVertices(int vertexId, bool blackOnly = true)
{
- if (Stage != GenerationStage.Initialization)
+ if (Stage != GenerationStage.Initialization && Stage != GenerationStage.NotStarted)
{
if (blackOnly)
return Vertices[vertexId].Neighbours.Where(n => Vertices[n].PlateId == -1);
@@ -296,33 +303,84 @@ public class PlanetHelper
public void PlateGeneration()
{
- var availableVerts = Vertices.Where(d => d.StageComplete == false && d.PlateId != -1).OrderBy(v => Guid.NewGuid()).ToList();
- foreach (PlateData plateData in Plates)
- {
- var plateVerts = availableVerts.Where(d => d.PlateId == plateData.Id);
- foreach (VertexData vertexData in plateVerts.Take((int)((5 + plateVerts.Count() / 4) * plateData.PlateExpansion)))
- {
- int expandTo = GetFreeNeighbourIndex(vertexData);
- if (expandTo != -1)
- {
- Vertices[expandTo].PlateId = plateData.Id;
- plateData.Vertices.Add(expandTo);
- ColorVertex(expandTo, plateData.Color);
- }
- else
- {
- vertexData.StageComplete = true;
- }
- }
- }
+ // Prepare our data. We use floats in the shader, so we need 32 bit.
+ int[] points = Enumerable.Range(0, Mdt.GetVertexCount()).ToArray();
+ var sizePoints = points.Length * sizeof(int);
+
+ int[] neighbors = Vertices.SelectMany(v => v.Neighbours.Count < 6 ? [..v.Neighbours.ToArray(),-1] : v.Neighbours.ToArray()).ToArray();
+ var sizeNeighbors = neighbors.Length * sizeof(int);
+ int[] plateids = Vertices.Select(v => v.PlateId).ToArray();
+
+ var sizePlateids = plateids.Length * sizeof(int);
- if (!availableVerts.Any())
+ var pointBytes = new byte[sizePoints];
+ byte[] neighborBytes = new byte[sizeNeighbors];
+ var plateBytes = new byte[sizePlateids];
+ Buffer.BlockCopy(points, 0, pointBytes, 0, pointBytes.Length);
+ Buffer.BlockCopy(neighbors, 0, neighborBytes, 0, neighborBytes.Length);
+ Buffer.BlockCopy(plateids, 0, plateBytes, 0, plateBytes.Length);
+
+ // Create a uniform to assign the buffer to the rendering device
+ var pointUniform = new RDUniform
{
- foreach (VertexData vertexData in Vertices)
- vertexData.StageComplete = false;
- AssignOceanPlates(Plates);
- CompleteStage();
+ UniformType = RenderingDevice.UniformType.StorageBuffer,
+ Binding = 0
+ };
+ var pointBuffer = _rd.StorageBufferCreate((uint)pointBytes.Length, pointBytes);
+ pointUniform.AddId(pointBuffer);
+
+ var neighborUniform = new RDUniform
+ {
+ UniformType = RenderingDevice.UniformType.StorageBuffer,
+ Binding = 1
+ };
+ var neighborBuffer = _rd.StorageBufferCreate((uint)neighborBytes.Length, neighborBytes);
+ neighborUniform.AddId(neighborBuffer);
+
+ var plateUniform = new RDUniform
+ {
+ UniformType = RenderingDevice.UniformType.StorageBuffer,
+ Binding = 2
+ };
+ var plateBuffer = _rd.StorageBufferCreate((uint)plateBytes.Length, plateBytes);
+ plateUniform.AddId(plateBuffer);
+
+ var uniformSet = _rd.UniformSetCreate([pointUniform, neighborUniform, plateUniform], _shader, 0);
+
+ // Create a compute pipeline
+ var pipeline = _rd.ComputePipelineCreate(_shader);
+ var computeList = _rd.ComputeListBegin();
+ _rd.ComputeListBindComputePipeline(computeList, pipeline);
+ _rd.ComputeListBindUniformSet(computeList, uniformSet, 0);
+ uint xgroups = (uint)(Mathf.Ceil((double)points.Length / 25.0));
+ _rd.ComputeListDispatch(computeList, xGroups: xgroups, yGroups: 50, zGroups: 1);
+ _rd.ComputeListEnd();
+ _rd.Submit();
+ _rd.Sync();
+ // Read back the data from the buffers
+ var outputBytes = _rd.BufferGetData(plateBuffer);
+ var output = new int[plateids.Length];
+ Buffer.BlockCopy(outputBytes, 0, output, 0, plateBytes.Length);
+
+ int index = 0;
+ foreach (int plate in output)
+ {
+ if (plate != -1)
+ {
+ Mdt.SetVertexColor(index, Plates[plate].Color);
+ Vertices[index].PlateId = plate;
+ }
+ index++;
}
+
+ _rd.FreeRid(pipeline);
+ _rd.FreeRid(uniformSet);
+ _rd.FreeRid(pointBuffer);
+ _rd.FreeRid(plateBuffer);
+ _rd.FreeRid(neighborBuffer);
+
+ AssignOceanPlates(Plates);
+ CompleteStage();
}
public void BorderSearch()
{