From Jobs

This commit is contained in:
2021-01-31 21:03:16 +08:00
parent 7978a33921
commit 4d861c50dd
350 changed files with 60218 additions and 70 deletions

184
Assets/Script/Fractal.cs Normal file
View File

@ -0,0 +1,184 @@
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using static Unity.Mathematics.math;
using quaternion = Unity.Mathematics.quaternion;
public class Fractal : MonoBehaviour
{
[BurstCompile(FloatPrecision.Standard, FloatMode.Fast, CompileSynchronously = true)]
private struct UpdateFractalLevelJob : IJobFor
{
public float spinAngleDelta;
public float scale;
[ReadOnly]
public NativeArray<FractalPart> parents;
public NativeArray<FractalPart> parts;
[WriteOnly]
public NativeArray<float3x4> matrices;
public void Execute(int i)
{
var parent = parents[i / 5];
var part = parts[i];
part.spinAngle += spinAngleDelta;
part.worldRotation = mul(parent.worldRotation,
mul(part.rotation, quaternion.RotateY(part.spinAngle))
);
part.worldPosition =
parent.worldPosition +
mul(parent.worldRotation, 1.5f * scale * part.direction);
parts[i] = part;
float3x3 r = float3x3(part.worldRotation) * scale;
matrices[i] = float3x4(r.c0, r.c1, r.c2, part.worldPosition);
}
}
private struct FractalPart
{
public float3 direction, worldPosition;
public quaternion rotation, worldRotation;
public float spinAngle;
}
NativeArray<FractalPart>[] parts;
NativeArray<float3x4>[] matrices;
[SerializeField, Range(1, 8)]
int depth = 4;
[SerializeField]
Mesh mesh = default;
[SerializeField]
Material material = default;
static float3[] directions =
{
up(), right(), left(), forward(), back()
};
static quaternion[] rotations =
{
quaternion.identity,
quaternion.RotateZ(-0.5f * PI), quaternion.RotateZ(0.5f * PI),
quaternion.RotateX(0.5f * PI), quaternion.RotateX(-0.5f * PI)
};
private FractalPart CreatePart(int childIndex)
{
return new FractalPart()
{
direction = directions[childIndex],
rotation = rotations[childIndex]
};
}
ComputeBuffer[] matricesBuffers;
static readonly int matricesId = Shader.PropertyToID("_Matrices");
static MaterialPropertyBlock propertyBlock;
private void OnEnable()
{
parts = new NativeArray<FractalPart>[depth];
matrices = new NativeArray<float3x4>[depth];
matricesBuffers = new ComputeBuffer[depth];
int stride = 12 * 4;
for (int i = 0, length = 1; i < parts.Length; i++, length *= 5)
{
parts[i] = new NativeArray<FractalPart>(length, Allocator.Persistent);
matrices[i] = new NativeArray<float3x4>(length, Allocator.Persistent);
matricesBuffers[i] = new ComputeBuffer(length, stride);
}
parts[0][0] = CreatePart(0);
for (int li = 1; li < parts.Length; li++)
{
NativeArray<FractalPart> levelParts = parts[li];
for (int fpi = 0; fpi < levelParts.Length; fpi += 5)
{
for (int ci = 0; ci < 5; ci++)
{
levelParts[fpi + ci] = CreatePart(ci);
}
}
}
if (propertyBlock == null)
{
propertyBlock = new MaterialPropertyBlock();
}
}
private void OnDisable()
{
for (int i = 0; i < matricesBuffers.Length; i++)
{
matricesBuffers[i].Release();
parts[i].Dispose();
matrices[i].Dispose();
}
parts = null;
matrices = null;
matricesBuffers = null;
}
void OnValidate()
{
if (parts != null && enabled)
{
OnDisable();
OnEnable();
}
}
private void Update()
{
float spinAngleDelta = 0.125f * PI * Time.deltaTime;
FractalPart rootPart = parts[0][0];
rootPart.spinAngle += spinAngleDelta;
rootPart.worldRotation = mul(transform.rotation,
mul(rootPart.rotation, quaternion.RotateY(rootPart.spinAngle))
);
rootPart.worldPosition = transform.position;
parts[0][0] = rootPart;
float objectScale = transform.lossyScale.x;
float3x3 r = float3x3(rootPart.worldRotation) * objectScale;
matrices[0][0] = float3x4(r.c0, r.c1, r.c2, rootPart.worldPosition);
float scale = objectScale;
JobHandle jobHandle = default;
for (int li = 1; li < parts.Length; li++)
{
scale *= 0.5f;
jobHandle = new UpdateFractalLevelJob
{
spinAngleDelta = spinAngleDelta,
scale = scale,
parents = parts[li - 1],
parts = parts[li],
matrices = matrices[li]
}.ScheduleParallel(parts[li].Length, 5, jobHandle);
}
jobHandle.Complete();
var bounds = new Bounds(rootPart.worldPosition, float3(3f * objectScale));
for (int i = 0; i < matricesBuffers.Length; i++)
{
ComputeBuffer buffer = matricesBuffers[i];
buffer.SetData(matrices[i]);
propertyBlock.SetBuffer(matricesId, buffer);
Graphics.DrawMeshInstancedProcedural(mesh, 0, material, bounds, buffer.count, propertyBlock);
}
}
}

View File

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

View File

@ -0,0 +1,66 @@
using UnityEngine;
using TMPro;
public class FrameRateCounter : MonoBehaviour
{
[SerializeField]
TextMeshProUGUI display = default;
public enum DisplayMode { FPS, MS };
[SerializeField]
DisplayMode displayMode = DisplayMode.FPS;
[SerializeField, Range(0.1f, 2.0f)]
float sampleDuration = 1.0f;
int frames;
float duration;
float bestDuration = float.MaxValue;
float worstDuration = 0.0f;
private void Update()
{
var frameDuration = Time.unscaledDeltaTime;
frames++;
duration += frameDuration;
if (frameDuration < bestDuration)
{
bestDuration = frameDuration;
}
if (frameDuration > worstDuration)
{
worstDuration = frameDuration;
}
if (duration >= sampleDuration)
{
if (displayMode == DisplayMode.FPS)
{
display.SetText(
"FPS\n{0:0}\n{1:0}\n{2:0}",
1.0f / bestDuration,
frames / duration,
1.0f / worstDuration
);
}
else
{
display.SetText(
"FPS\n{0:1}\n{1:1}\n{2:1}",
1000.0f * bestDuration,
1000.0f * duration / frames,
1000.0f * worstDuration
);
}
frames = 0;
duration = 0.0f;
bestDuration = float.MaxValue;
worstDuration = 0.0f;
}
}
}

View File

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

View File

@ -0,0 +1,21 @@
#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
StructuredBuffer<float3x4> _Matrices;
#endif
void ConfigureProcedural () {
#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
float3x4 m = _Matrices[unity_InstanceID];
unity_ObjectToWorld._m00_m01_m02_m03 = m._m00_m01_m02_m03;
unity_ObjectToWorld._m10_m11_m12_m13 = m._m10_m11_m12_m13;
unity_ObjectToWorld._m20_m21_m22_m23 = m._m20_m21_m22_m23;
unity_ObjectToWorld._m30_m31_m32_m33 = float4(0.0, 0.0, 0.0, 1.0);
#endif
}
void ShaderGraphFunction_float (float3 In, out float3 Out) {
Out = In;
}
void ShaderGraphFunction_half (half3 In, out half3 Out) {
Out = In;
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 0ed85852d1001bf44b1fef32640df23b
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant: