Initial Compute Shader for Plate Generation.
This commit is contained in:
parent
9d2dd0ca82
commit
47ca1265e6
8 changed files with 214 additions and 29 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABuffer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fade9_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2e87203df15b4d60b9c670dd76fb5ed8dba400_003Fda_003Fba7fca04_003FBuffer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMain_005FScriptMethods_002Egenerated_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fade9_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fb637bee5badc9b536d43ca23ca5744325c67bb7_003FMain_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMain_005FScriptMethods_002Egenerated_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fade9_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fb637bee5badc9b536d43ca23ca5744325c67bb7_003FMain_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARandom_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fade9_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2e87203df15b4d60b9c670dd76fb5ed8dba400_003F3a_003F5188629f_003FRandom_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARandom_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fade9_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2e87203df15b4d60b9c670dd76fb5ed8dba400_003F3a_003F5188629f_003FRandom_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelpers_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fade9_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2e87203df15b4d60b9c670dd76fb5ed8dba400_003F61_003Fd1d5ae77_003FThrowHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelpers_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fade9_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2e87203df15b4d60b9c670dd76fb5ed8dba400_003F61_003Fd1d5ae77_003FThrowHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
|
|
||||||
|
|
@ -50,5 +50,3 @@ mouse_secondary={
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
rendering_device/driver.windows="d3d12"
|
rendering_device/driver.windows="d3d12"
|
||||||
renderer/rendering_method="gl_compatibility"
|
|
||||||
renderer/rendering_method.mobile="gl_compatibility"
|
|
||||||
|
|
|
||||||
40
shaders/compute/PlateExpansion.glsl
Normal file
40
shaders/compute/PlateExpansion.glsl
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#[compute]
|
||||||
|
#version 450
|
||||||
|
// Invocations in the (x, y, z) dimension
|
||||||
|
layout(local_size_x = 1000, 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
shaders/compute/PlateExpansion.glsl.import
Normal file
14
shaders/compute/PlateExpansion.glsl.import
Normal file
|
|
@ -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]
|
||||||
|
|
||||||
17
shaders/compute/compute_example.glsl
Normal file
17
shaders/compute/compute_example.glsl
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
14
shaders/compute/compute_example.glsl.import
Normal file
14
shaders/compute/compute_example.glsl.import
Normal file
|
|
@ -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]
|
||||||
|
|
||||||
40
src/Main.cs
40
src/Main.cs
|
|
@ -1,10 +1,13 @@
|
||||||
#nullable enable
|
#nullable enable
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Godot.Collections;
|
using Godot.Collections;
|
||||||
|
using Array = System.Array;
|
||||||
|
|
||||||
public partial class Main : Control
|
public partial class Main : Control
|
||||||
{
|
{
|
||||||
|
|
@ -39,6 +42,43 @@ public partial class Main : Control
|
||||||
Projector.GatherPoints(_planetHelper, int.Parse(GetNode<LineEdit>("%Resolution").Text));
|
Projector.GatherPoints(_planetHelper, int.Parse(GetNode<LineEdit>("%Resolution").Text));
|
||||||
AxialTiltChanged(GetNode<LineEdit>("%AxialTilt").Text);
|
AxialTiltChanged(GetNode<LineEdit>("%AxialTilt").Text);
|
||||||
UpdateTime();
|
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;
|
Vector3 _pointerPosition = Vector3.Zero;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ public class PlanetHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool StageComplete = true;
|
private bool StageComplete = true;
|
||||||
private int _plateCount = 14;
|
private int _plateCount = 12;
|
||||||
private float _landRatio = 0.4f;
|
private float _landRatio = 0.4f;
|
||||||
|
|
||||||
public List<PlateData> Plates = new List<PlateData>();
|
public List<PlateData> Plates = new List<PlateData>();
|
||||||
|
|
@ -156,7 +156,6 @@ public class PlanetHelper
|
||||||
VertexData vertex = Vertices.Where(v => v.PlateId == -1).OrderBy(v => Guid.NewGuid()).First();
|
VertexData vertex = Vertices.Where(v => v.PlateId == -1).OrderBy(v => Guid.NewGuid()).First();
|
||||||
vertex.PlateId = i;
|
vertex.PlateId = i;
|
||||||
var color = new Color(RandF(0f, 1f), RandF(0f, 1f), RandF(0f, 1f));
|
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]);
|
PlateData plate = new PlateData(i, color, false, [vertex.Id]);
|
||||||
|
|
||||||
plate.MovementAxis = GetRandomVector3();
|
plate.MovementAxis = GetRandomVector3();
|
||||||
|
|
@ -168,7 +167,7 @@ public class PlanetHelper
|
||||||
|
|
||||||
public IEnumerable<int> GetNeighboringVertices(int vertexId, bool blackOnly = true)
|
public IEnumerable<int> GetNeighboringVertices(int vertexId, bool blackOnly = true)
|
||||||
{
|
{
|
||||||
if (Stage != GenerationStage.Initialization)
|
if (Stage != GenerationStage.Initialization && Stage != GenerationStage.NotStarted)
|
||||||
{
|
{
|
||||||
if (blackOnly)
|
if (blackOnly)
|
||||||
return Vertices[vertexId].Neighbours.Where(n => Vertices[n].PlateId == -1);
|
return Vertices[vertexId].Neighbours.Where(n => Vertices[n].PlateId == -1);
|
||||||
|
|
@ -296,34 +295,96 @@ public class PlanetHelper
|
||||||
|
|
||||||
public void PlateGeneration()
|
public void PlateGeneration()
|
||||||
{
|
{
|
||||||
var availableVerts = Vertices.Where(d => d.StageComplete == false && d.PlateId != -1).OrderBy(v => Guid.NewGuid()).ToList();
|
var rd = RenderingServer.CreateLocalRenderingDevice();
|
||||||
foreach (PlateData plateData in Plates)
|
var shaderFile = GD.Load<RDShaderFile>("res://shaders/compute/PlateExpansion.glsl");
|
||||||
{
|
GD.Print(shaderFile.BaseError);
|
||||||
var plateVerts = availableVerts.Where(d => d.PlateId == plateData.Id);
|
var shaderBytecode = shaderFile.GetSpirV();
|
||||||
foreach (VertexData vertexData in plateVerts.Take((int)((5 + plateVerts.Count() / 4) * plateData.PlateExpansion)))
|
GD.Print(shaderBytecode.CompileErrorCompute);
|
||||||
{
|
GD.Print(shaderBytecode.CompileErrorFragment);
|
||||||
int expandTo = GetFreeNeighbourIndex(vertexData);
|
GD.Print(shaderBytecode.CompileErrorVertex);
|
||||||
if (expandTo != -1)
|
GD.Print(shaderBytecode.CompileErrorTesselationEvaluation);
|
||||||
{
|
GD.Print(shaderBytecode.CompileErrorTesselationControl);
|
||||||
Vertices[expandTo].PlateId = plateData.Id;
|
var shader = rd.ShaderCreateFromSpirV(shaderBytecode);
|
||||||
plateData.Vertices.Add(expandTo);
|
GD.Print(shader.IsValid);
|
||||||
ColorVertex(expandTo, plateData.Color);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vertexData.StageComplete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!availableVerts.Any())
|
// 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);
|
||||||
|
|
||||||
|
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)
|
UniformType = RenderingDevice.UniformType.StorageBuffer,
|
||||||
vertexData.StageComplete = false;
|
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 / 1000.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(pointBuffer);
|
||||||
|
rd.FreeRid(plateBuffer);
|
||||||
|
rd.FreeRid(neighborBuffer);
|
||||||
|
rd.FreeRid(pipeline);
|
||||||
|
rd.FreeRid(uniformSet);
|
||||||
|
|
||||||
AssignOceanPlates(Plates);
|
AssignOceanPlates(Plates);
|
||||||
CompleteStage();
|
CompleteStage();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
public void BorderSearch()
|
public void BorderSearch()
|
||||||
{
|
{
|
||||||
var availableVerts = Vertices.Where(d => d.StageComplete == false).Take(2500).ToList();
|
var availableVerts = Vertices.Where(d => d.StageComplete == false).Take(2500).ToList();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue