Cut 8b. The Unity project compiles with 0 errors in 6000.3.24f1 batchmode. Packages: manifest.json pins org.gamecult.cultlib at cultlib-unity-v1.0.57 and org.gamecult.caching.unity at caching-unity-v1.2.0, next to the 8a CultMath tag. Aetheria.Shared.Unity references GameCult.CultLib and keeps noEngineReferences. The Database Tools (Assets/Scripts/CultCache/Editor) are deleted in this commit, alongside their five ported drawers in Assets/Scripts/Editor/CultCacheDrawers.cs, each an [CultInspectorDrawer] ICultInspectorDrawer: - InspectableType: popup of the attribute type's [Union] member names, writing the string. - InspectableColor: float3 and float4 through ColorField. - InspectableAnimationCurve: float4[] and BezierCurve through CurveField. - InspectableTemperature: Kelvin, Celsius and Fahrenheit fields over one value. - InspectableSchematicShape: size and cell toggles. The old drawer also drew the item's schematic texture and tinted hull hardpoints, which need the parent document. The tagged Studio hands a drawer only the value, so those wait on the Studio exposing the open record. Unity call sites: - ActionGameManager opens the catalog through AetheriaStores; Cut 10 adds the run and player stores. - Refs resolve through ItemManager.GetData or Get(ref); orbit, planet and belt maps key by CultRecordKey; identity is compared by reference or key. - The PlayerSettings.msgpack reader and writer, which Cut 10 deletes, pass CultDocumentMessagePackSerialization.OptionsFor, since the embedded run reaches CultMath values and refs. Keyboard layouts need no resolver and keep MessagePack's defaults until Cut 10. - The input map uses the nested action to binding shape. - PropertiesPanel reads CultInspectorRangeAttribute. - NameTools loses its legacy name-file writer. - Slime compares serialized settings instead of the deleted SHA1 helper. - FieldDriver drops InspectorHeader. - .gitignore covers the test project's build output. Builds: Aetheria.Shared, AetherDb, Aetheria.Shared.Tests (6/6), Unity batchmode (0 errors). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
307 lines
11 KiB
C#
307 lines
11 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using MessagePack;
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering;
|
|
using Random = UnityEngine.Random;
|
|
using static CultMath.math;
|
|
|
|
public class Slime : MonoBehaviour
|
|
{
|
|
#region variables
|
|
|
|
[Header("Scene Links")]
|
|
public Camera TargetCamera;
|
|
|
|
[Header("Materials")]
|
|
public ComputeShader SlimeCompute;
|
|
public Material AccumulationMaterial;
|
|
public Material ParticleMaterial;
|
|
public RenderTexture GravityTexture;
|
|
|
|
[Header("Performance")]
|
|
public int TextureSize = 1024;
|
|
public float ZoneRadius = 512;
|
|
public int AgentCount = 524288;
|
|
public int ParticleCount = 65536;
|
|
public int TrailPoints = 8;
|
|
|
|
[Header("Parameters")]
|
|
public SlimeSettings SlimeSettings;
|
|
public float ZoneCeiling;
|
|
public float ZoneFloor;
|
|
public float NoiseFrequency = 1;
|
|
public float NoiseAmplitude = 5;
|
|
public float ParticleHeightRange;
|
|
public float ParticleHeightOffset;
|
|
public float TrailStartWidth = .5f;
|
|
public float TrailEndWidth = .1f;
|
|
public float TrailDamping = .05f;
|
|
public Vector2[] SpawnPositions;
|
|
|
|
private const int GROUP_SIZE = 64;
|
|
private int _updateAgentsKernel;
|
|
private int _diffuseKernel;
|
|
private int _particleKernel;
|
|
private int _trailKernel;
|
|
private int _geometryKernel;
|
|
private string _settingsHash;
|
|
private int _spawnBufferSize = 1;
|
|
|
|
private int IndexBufferSize => ParticleCount * 6 * (TrailPoints - 1);
|
|
|
|
#endregion
|
|
|
|
#region buffers
|
|
|
|
private ComputeBuffer _agentsBuffer;
|
|
private RenderTexture _accumulationTexture;
|
|
private RenderTexture _previousAccumulationTexture;
|
|
|
|
private ComputeBuffer _spawnBuffer;
|
|
private ComputeBuffer _parameterBuffer;
|
|
private ComputeBuffer _particlesBuffer;
|
|
|
|
private ComputeBuffer _trailBuffer;
|
|
private ComputeBuffer _trailPreviousBuffer;
|
|
|
|
private ComputeBuffer _indexBuffer;
|
|
private ComputeBuffer _vertexBuffer;
|
|
|
|
#endregion
|
|
|
|
#region Structs
|
|
|
|
struct Agent
|
|
{
|
|
public Vector2 Position;
|
|
public float Angle;
|
|
}
|
|
|
|
struct Particle
|
|
{
|
|
public Vector3 Start;
|
|
public float Intensity;
|
|
}
|
|
|
|
struct Vertex
|
|
{
|
|
public Vector3 Position;
|
|
public Vector2 UV;
|
|
public float Intensity;
|
|
}
|
|
|
|
#endregion
|
|
|
|
void Start()
|
|
{
|
|
_updateAgentsKernel = SlimeCompute.FindKernel("UpdateAgents");
|
|
_diffuseKernel = SlimeCompute.FindKernel("Diffuse");
|
|
_particleKernel = SlimeCompute.FindKernel("CreateAgentParticles");
|
|
_trailKernel = SlimeCompute.FindKernel("UpdateTrailPoints");
|
|
_geometryKernel = SlimeCompute.FindKernel("CreateTrailGeometry");
|
|
|
|
_accumulationTexture = new RenderTexture(TextureSize, TextureSize, 1, RenderTextureFormat.RFloat);
|
|
_accumulationTexture.enableRandomWrite = true;
|
|
_previousAccumulationTexture = new RenderTexture(TextureSize, TextureSize, 1, RenderTextureFormat.RFloat);
|
|
_previousAccumulationTexture.enableRandomWrite = true;
|
|
AccumulationMaterial.SetTexture("_MainTex", _accumulationTexture);
|
|
|
|
_agentsBuffer = new ComputeBuffer(AgentCount, Marshal.SizeOf(typeof(Agent)));
|
|
var agents = new Agent[AgentCount];
|
|
for (var i = 0; i < agents.Length; i++)
|
|
{
|
|
agents[i] = new Agent
|
|
{
|
|
Position = Random.insideUnitCircle * ZoneRadius,
|
|
Angle = Random.value * Mathf.PI * 2
|
|
};
|
|
}
|
|
_agentsBuffer.SetData(agents);
|
|
|
|
_parameterBuffer = new ComputeBuffer(1, Marshal.SizeOf(typeof(SlimeSettings)));
|
|
_spawnBuffer = new ComputeBuffer(1, Marshal.SizeOf(typeof(Vector2)));
|
|
_spawnBuffer.SetData(new [] {Vector2.zero});
|
|
|
|
_trailBuffer = new ComputeBuffer(ParticleCount * TrailPoints, Marshal.SizeOf(typeof(Vector3)));
|
|
_trailPreviousBuffer = new ComputeBuffer(ParticleCount * TrailPoints, Marshal.SizeOf(typeof(Vector3)));
|
|
var trailData = Enumerable.Repeat(Vector3.zero, _trailBuffer.count).ToArray();
|
|
_trailBuffer.SetData(trailData);
|
|
_trailPreviousBuffer.SetData(trailData);
|
|
|
|
_particlesBuffer = new ComputeBuffer(ParticleCount, Marshal.SizeOf(typeof(Particle)));
|
|
|
|
_vertexBuffer = new ComputeBuffer(ParticleCount * 2 * TrailPoints, Marshal.SizeOf(typeof(Vertex)));
|
|
|
|
var indexData = new int[IndexBufferSize];
|
|
var index = 0;
|
|
for (int iTrail = 0; iTrail < ParticleCount; iTrail++)
|
|
{
|
|
var trailOffset = iTrail * TrailPoints * 2;
|
|
for (int iTrailPoint = 0; iTrailPoint < TrailPoints - 1; iTrailPoint++)
|
|
{
|
|
var offset = trailOffset + iTrailPoint * 2;
|
|
indexData[index++] = 0 + offset;
|
|
indexData[index++] = 1 + offset;
|
|
indexData[index++] = 2 + offset;
|
|
indexData[index++] = 2 + offset;
|
|
indexData[index++] = 1 + offset;
|
|
indexData[index++] = 3 + offset;
|
|
}
|
|
}
|
|
|
|
_indexBuffer = new ComputeBuffer(indexData.Length, Marshal.SizeOf(typeof(uint))); // 1 trail point to 2 triangles (6 vertices)
|
|
_indexBuffer.SetData(indexData);
|
|
}
|
|
|
|
void UpdateSettings()
|
|
{
|
|
var hash = System.Convert.ToBase64String(MessagePackSerializer.Serialize(SlimeSettings));
|
|
if(hash != _settingsHash)
|
|
{
|
|
_settingsHash = hash;
|
|
_parameterBuffer.SetData(new[] {SlimeSettings});
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
UpdateSettings();
|
|
|
|
if (SpawnPositions != null && SpawnPositions.Length > 0)
|
|
{
|
|
if (SpawnPositions.Length != _spawnBufferSize)
|
|
{
|
|
_spawnBuffer.Release();
|
|
_spawnBuffer = new ComputeBuffer(SpawnPositions.Length, Marshal.SizeOf(typeof(Vector2)));
|
|
_spawnBufferSize = SpawnPositions.Length;
|
|
}
|
|
_spawnBuffer.SetData(SpawnPositions);
|
|
}
|
|
|
|
SlimeCompute.SetInt("randomOffset", Random.Range(0,65536));
|
|
SlimeCompute.SetInt("textureSize", TextureSize);
|
|
SlimeCompute.SetInt("gravityTextureSize", GravityTexture.width);
|
|
SlimeCompute.SetInt("numAgents", AgentCount);
|
|
SlimeCompute.SetFloat("zoneRadius", ZoneRadius);
|
|
SlimeCompute.SetFloat("deltaTime", Time.deltaTime);
|
|
SlimeCompute.SetInt("spawnPositionCount", _spawnBufferSize);
|
|
|
|
SlimeCompute.SetBuffer(_updateAgentsKernel, "agents", _agentsBuffer);
|
|
SlimeCompute.SetBuffer(_updateAgentsKernel, "spawnPositions", _spawnBuffer);
|
|
SlimeCompute.SetBuffer(_updateAgentsKernel, "parameters", _parameterBuffer);
|
|
SlimeCompute.SetTexture(_updateAgentsKernel, "accumulation", _accumulationTexture);
|
|
SlimeCompute.SetTexture(_updateAgentsKernel, "Heightmap", GravityTexture);
|
|
|
|
var numberOfGroups = Mathf.CeilToInt((float)AgentCount / GROUP_SIZE);
|
|
SlimeCompute.Dispatch(_updateAgentsKernel, numberOfGroups, 1, 1);
|
|
|
|
Graphics.Blit(_accumulationTexture, _previousAccumulationTexture);
|
|
SlimeCompute.SetBuffer(_diffuseKernel, "parameters", _parameterBuffer);
|
|
SlimeCompute.SetTexture(_diffuseKernel, "Heightmap", GravityTexture);
|
|
SlimeCompute.SetTexture(_diffuseKernel, "accumulation", _previousAccumulationTexture);
|
|
SlimeCompute.SetTexture(_diffuseKernel, "diffusedAccumulation", _accumulationTexture);
|
|
numberOfGroups = Mathf.CeilToInt((float)TextureSize / 8);
|
|
SlimeCompute.Dispatch(_diffuseKernel, numberOfGroups, numberOfGroups, 1);
|
|
|
|
SlimeCompute.SetBuffer(_particleKernel, "parameters", _parameterBuffer);
|
|
SlimeCompute.SetTexture(_particleKernel, "Heightmap", GravityTexture);
|
|
SlimeCompute.SetBuffer(_particleKernel, "agents", _agentsBuffer);
|
|
SlimeCompute.SetBuffer(_particleKernel, "particles", _particlesBuffer);
|
|
SlimeCompute.SetFloat("time", Time.time * NoiseFrequency);
|
|
SlimeCompute.SetFloat("noiseAmplitude", NoiseAmplitude);
|
|
SlimeCompute.SetFloat("heightRange", ParticleHeightRange);
|
|
SlimeCompute.SetFloat("heightOffset", ParticleHeightOffset);
|
|
SlimeCompute.SetFloat("trailDamping", TrailDamping);
|
|
SlimeCompute.SetInt("particleCount", ParticleCount);
|
|
|
|
numberOfGroups = ParticleCount / GROUP_SIZE;
|
|
SlimeCompute.Dispatch(_particleKernel, numberOfGroups, 1, 1);
|
|
|
|
SlimeCompute.SetInt("trailPoints", TrailPoints);
|
|
|
|
numberOfGroups = ParticleCount * TrailPoints / GROUP_SIZE;
|
|
SlimeCompute.SetBuffer(_trailKernel, "previousTrailBuffer", _trailPreviousBuffer);
|
|
SlimeCompute.SetBuffer(_trailKernel, "particles", _particlesBuffer);
|
|
SlimeCompute.SetBuffer(_trailKernel, "trailBuffer", _trailBuffer);
|
|
SlimeCompute.Dispatch(_trailKernel, numberOfGroups, 1, 1);
|
|
var tempTrailBuffer = _trailBuffer;
|
|
_trailBuffer = _trailPreviousBuffer;
|
|
_trailPreviousBuffer = tempTrailBuffer;
|
|
|
|
SlimeCompute.SetFloat("trailStartWidth", TrailStartWidth);
|
|
SlimeCompute.SetFloat("trailEndWidth", TrailEndWidth);
|
|
SlimeCompute.SetVector("cameraPos", TargetCamera.transform.position);
|
|
SlimeCompute.SetBuffer(_geometryKernel, "particles", _particlesBuffer);
|
|
SlimeCompute.SetBuffer(_geometryKernel, "trailBuffer", _trailBuffer);
|
|
SlimeCompute.SetBuffer(_geometryKernel, "vertexBuffer", _vertexBuffer);
|
|
|
|
SlimeCompute.Dispatch(_geometryKernel, numberOfGroups, 1, 1);
|
|
|
|
ParticleMaterial.SetBuffer("_IndexBuffer", _indexBuffer);
|
|
ParticleMaterial.SetBuffer("_VertexBuffer", _vertexBuffer);
|
|
Graphics.DrawProcedural(
|
|
ParticleMaterial,
|
|
new Bounds(Vector3.zero, ZoneRadius * 2 * Vector3.one),
|
|
MeshTopology.Triangles,
|
|
IndexBufferSize,
|
|
1,
|
|
TargetCamera,
|
|
null,
|
|
ShadowCastingMode.Off,
|
|
false,
|
|
0);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
_agentsBuffer.Release();
|
|
_accumulationTexture.Release();
|
|
_previousAccumulationTexture.Release();
|
|
|
|
_spawnBuffer.Release();
|
|
_parameterBuffer.Release();
|
|
_particlesBuffer.Release();
|
|
|
|
_trailBuffer.Release();
|
|
_trailPreviousBuffer.Release();
|
|
|
|
_indexBuffer.Release();
|
|
_vertexBuffer.Release();
|
|
}
|
|
}
|
|
|
|
[Serializable, MessagePackObject(keyAsPropertyName:true)]
|
|
public struct SlimeSettings
|
|
{
|
|
public SlimeParameter Deposition;
|
|
public SlimeParameter Diffusion;
|
|
public SlimeParameter Decay;
|
|
public SlimeParameter TurnSpeed;
|
|
public SlimeParameter Speed;
|
|
public SlimeParameter Drive;
|
|
public SlimeParameter SensorDistance;
|
|
public SlimeParameter SensorSpread;
|
|
public SlimeParameter TrailDamping;
|
|
public SlimeParameter Intensity;
|
|
}
|
|
|
|
[Serializable, MessagePackObject(keyAsPropertyName:true)]
|
|
public struct SlimeParameter
|
|
{
|
|
public float SlopeThreshold;
|
|
public float SlopeBlend;
|
|
public float HighValue;
|
|
public float LowValue;
|
|
public float Exponent;
|
|
|
|
public float Evaluate(float slope)
|
|
{
|
|
return lerp(LowValue, HighValue, pow(smoothstep(SlopeThreshold - SlopeBlend, SlopeThreshold + SlopeBlend, slope), Exponent));
|
|
}
|
|
}
|