104 lines
2.8 KiB
C#
104 lines
2.8 KiB
C#
using UnityEngine;
|
|
|
|
public class GPUGraph : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
ComputeShader computeShader = default;
|
|
|
|
[SerializeField]
|
|
Material material = default;
|
|
|
|
[SerializeField]
|
|
Mesh mesh = default;
|
|
|
|
const int maxResolution = 1000;
|
|
|
|
[SerializeField, Range(10, maxResolution)]
|
|
int resolution = 10;
|
|
|
|
[SerializeField]
|
|
FunctionLibrary.FunctionName function = default;
|
|
|
|
public enum TransitionMode { Normal, Cycle, Random }
|
|
|
|
[SerializeField]
|
|
TransitionMode transitionMode = TransitionMode.Normal;
|
|
|
|
[SerializeField, Min(0.0f)]
|
|
float functionDuration = 1.0f;
|
|
|
|
[SerializeField, Min(0.0f)]
|
|
float transitionDuration = 1.0f;
|
|
|
|
float duration = 0.0f;
|
|
|
|
bool transitioning;
|
|
|
|
FunctionLibrary.FunctionName transitionFunction;
|
|
|
|
ComputeBuffer positionsBuffer;
|
|
|
|
static readonly int positionsId = Shader.PropertyToID("_Positions");
|
|
static readonly int resolutionId = Shader.PropertyToID("_Resolution");
|
|
static readonly int stepId = Shader.PropertyToID("_Step");
|
|
static readonly int timeId = Shader.PropertyToID("_Time");
|
|
|
|
private void OnEnable()
|
|
{
|
|
positionsBuffer = new ComputeBuffer(maxResolution * maxResolution, 3 * 4);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
positionsBuffer.Release();
|
|
positionsBuffer = null;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
duration += Time.deltaTime;
|
|
if (transitioning)
|
|
{
|
|
if (duration >= transitionDuration)
|
|
{
|
|
duration -= transitionDuration;
|
|
transitioning = false;
|
|
}
|
|
}
|
|
else if (duration >= functionDuration)
|
|
{
|
|
duration -= functionDuration;
|
|
transitioning = true;
|
|
transitionFunction = function;
|
|
PickNextFunction();
|
|
}
|
|
UpdateFunctionOnGPU();
|
|
}
|
|
|
|
private void PickNextFunction()
|
|
{
|
|
if (transitionMode == TransitionMode.Normal) return;
|
|
function = transitionMode == TransitionMode.Cycle ?
|
|
FunctionLibrary.GetNextFunctionName(function) :
|
|
FunctionLibrary.GetRandomFunctionNameOtherThan(function);
|
|
}
|
|
|
|
private void UpdateFunctionOnGPU()
|
|
{
|
|
var step = 2f / resolution;
|
|
computeShader.SetInt(resolutionId, resolution);
|
|
computeShader.SetFloat(stepId, step);
|
|
computeShader.SetFloat(timeId, Time.time);
|
|
|
|
computeShader.SetBuffer(0, positionsId, positionsBuffer);
|
|
|
|
var groups = Mathf.CeilToInt(resolution / 8f);
|
|
computeShader.Dispatch(0, groups, groups, 1);
|
|
|
|
material.SetBuffer(positionsId, positionsBuffer);
|
|
material.SetFloat(stepId, step);
|
|
var bounds = new Bounds(Vector3.zero, Vector3.one * (2f + 2f / resolution));
|
|
Graphics.DrawMeshInstancedProcedural(mesh, 0, material, bounds, resolution * resolution);
|
|
}
|
|
}
|