Moving Work to the GPU

This commit is contained in:
2021-01-31 11:17:44 +08:00
parent 8f4b9e2ae2
commit a64346ee62
6 changed files with 170 additions and 4 deletions

View File

@ -0,0 +1,39 @@
#pragma kernel FuncationKernel
RWStructuredBuffer<float3> _Positions;
uint _Resolution;
float _Step;
float _Time;
float2 GetUV(uint3 id)
{
return (id.xy + 0.5) * _Step - 1.0;
}
void SetPositions(uint3 id, float3 positions)
{
if (id.x < _Resolution && id.y < _Resolution)
{
_Positions[id.x + id.y * _Resolution] = positions;
}
}
#define PI 3.14159265358979323846
float3 Wave(float u, float v, float t)
{
float3 p;
p.x = u;
p.y = sin(PI * (u + v + t));
p.z = v;
return p;
}
[numthreads(8, 8, 1)]
void FuncationKernel(uint3 id : SV_DISPATCHTHREADID)
{
float2 uv = GetUV(id);
SetPositions(id, Wave(uv.x, uv.y, _Time));
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c7f7fcb3b4a90614b80aa341489318e7
ComputeShaderImporter:
externalObjects: {}
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

90
Assets/Script/GPUGraph.cs Normal file
View File

@ -0,0 +1,90 @@
using UnityEngine;
public class GPUGraph : MonoBehaviour
{
[SerializeField]
ComputeShader computeShader = default;
[SerializeField, Range(10, 200)]
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(resolution * resolution, 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);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e99d61420a0d1f459f961121d6fbe77
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -5,7 +5,7 @@ public class Graph : MonoBehaviour
[SerializeField]
Transform pointPrefab = default;
[SerializeField, Range(10, 100)]
[SerializeField, Range(10, 200)]
int resolution = 10;
[SerializeField]