diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 8450e13..7d551d6 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -98,7 +98,7 @@ LightmapSettings: m_TrainingDataDestination: TrainingData m_LightProbeSampleCountMultiplier: 4 m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 + m_UseShadowmask: 0 --- !u!196 &4 NavMeshSettings: serializedVersion: 2 @@ -131,6 +131,7 @@ GameObject: m_Component: - component: {fileID: 75389716} - component: {fileID: 75389715} + - component: {fileID: 75389717} m_Layer: 0 m_Name: Graph m_TagString: Untagged @@ -145,14 +146,14 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 75389714} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 14cd06bfa92d53e4ebc0cde4a0e39db8, type: 3} m_Name: m_EditorClassIdentifier: pointPrefab: {fileID: 5221897554875366738, guid: d73a635284aa0ca4eb9cc40879b3267d, type: 3} - resolution: 50 + resolution: 200 function: 4 transitionMode: 2 functionDuration: 1 @@ -171,6 +172,23 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &75389717 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 75389714} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e99d61420a0d1f459f961121d6fbe77, type: 3} + m_Name: + m_EditorClassIdentifier: + resolution: 200 + function: 4 + transitionMode: 1 + functionDuration: 1 + transitionDuration: 0 --- !u!1 &705507993 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Script/FunctionLibrary.compute b/Assets/Script/FunctionLibrary.compute new file mode 100644 index 0000000..ef8a549 --- /dev/null +++ b/Assets/Script/FunctionLibrary.compute @@ -0,0 +1,39 @@ +#pragma kernel FuncationKernel + +RWStructuredBuffer _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)); +} diff --git a/Assets/Script/FunctionLibrary.compute.meta b/Assets/Script/FunctionLibrary.compute.meta new file mode 100644 index 0000000..e9edf70 --- /dev/null +++ b/Assets/Script/FunctionLibrary.compute.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c7f7fcb3b4a90614b80aa341489318e7 +ComputeShaderImporter: + externalObjects: {} + currentAPIMask: 4 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/GPUGraph.cs b/Assets/Script/GPUGraph.cs new file mode 100644 index 0000000..42afbc5 --- /dev/null +++ b/Assets/Script/GPUGraph.cs @@ -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); + } +} diff --git a/Assets/Script/GPUGraph.cs.meta b/Assets/Script/GPUGraph.cs.meta new file mode 100644 index 0000000..b945224 --- /dev/null +++ b/Assets/Script/GPUGraph.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e99d61420a0d1f459f961121d6fbe77 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/Graph.cs b/Assets/Script/Graph.cs index de8cef2..cf322c4 100644 --- a/Assets/Script/Graph.cs +++ b/Assets/Script/Graph.cs @@ -5,7 +5,7 @@ public class Graph : MonoBehaviour [SerializeField] Transform pointPrefab = default; - [SerializeField, Range(10, 100)] + [SerializeField, Range(10, 200)] int resolution = 10; [SerializeField]