DotCloud/Assets/PointsDrawer.cs

142 lines
4.5 KiB
C#
Raw Normal View History

2024-12-09 16:51:45 +08:00
using System;
using System.Runtime.InteropServices;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace ZC
{
public class PointsDrawer
{
private static readonly int id_properties = Shader.PropertyToID("_Properties");
private int population;
private float range;
private Mesh mesh;
private Material material;
private ComputeBuffer meshPropertiesBuffer;
private ComputeBuffer argsBuffer;
private NativeArray<MeshProperties> _properties;
[StructLayout(LayoutKind.Explicit, Size = 80)]
private struct MeshProperties
{
[FieldOffset(0)] public float4x4 mat;
[FieldOffset(64)] public float4 color;
public static int Size()
{
return sizeof(float) * 4 * 4 + sizeof(float) * 4;
}
}
public void Setup(Mesh mesh, int population, float range, Material material)
{
this.mesh = mesh;
this.population = population;
this.range = range;
this.material = material;
InitializeBuffers();
}
private void InitializeBuffers()
{
// Argument buffer used by DrawMeshInstancedIndirect.
uint[] args = new uint[5] { 0, 0, 0, 0, 0 };
// Arguments for drawing mesh.
// 0 == number of triangle indices, 1 == population, others are only relevant if drawing submeshes.
args[0] = (uint)mesh.GetIndexCount(0);
args[1] = (uint)population;
args[2] = (uint)mesh.GetIndexStart(0);
args[3] = (uint)mesh.GetBaseVertex(0);
argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
argsBuffer.SetData(args);
this._properties = new NativeArray<MeshProperties>(this.population, Allocator.Persistent);
meshPropertiesBuffer = new ComputeBuffer(population, MeshProperties.Size());
}
public void OnDispose()
{
if (meshPropertiesBuffer != null)
{
meshPropertiesBuffer.Release();
}
meshPropertiesBuffer = null;
if (argsBuffer != null)
{
argsBuffer.Release();
}
argsBuffer = null;
this._properties.Dispose();
}
public void Render(NativeArray<ZPointInfo> frames, int hitCount,Bounds bounds,quaternion quaternion, float3 position)
{
TransformJob job = new TransformJob()
{
properties = this._properties,
frames =frames,
hitCount =hitCount,
position =position,
quaternion =quaternion,
};
job.Schedule(_properties.Length, 1).Complete();
meshPropertiesBuffer.SetData(this._properties);
material.SetBuffer(id_properties, meshPropertiesBuffer);
Graphics.DrawMeshInstancedIndirect(mesh, 0, material, bounds, bufferWithArgs: argsBuffer,receiveShadows: false, castShadows: ShadowCastingMode.Off);
}
[BurstCompile]
struct TransformJob : IJobParallelFor
{
[ReadOnly]
public NativeArray<ZPointInfo> frames;
[ReadOnly]
public int hitCount;
[ReadOnly]
public float3 position;
[ReadOnly]
public quaternion quaternion;
public NativeArray<MeshProperties> properties;
public void Execute(int i)
{
MeshProperties props = new MeshProperties();
if(i>=hitCount)
{
props.color = math.float4(1,0,0,1);
properties[i] = props;
return;
}
var frame = this.frames[i];
float3 localPosition = frame.point - position;
localPosition = math.mul(math.inverse(this.quaternion), localPosition);
const float scale = 0.02f;
props.mat = math.float4x4(math.float3x3(
scale,0,0,
0,scale,0,
0,0,scale
),localPosition);
props.color = math.float4(1,1,1,1);
properties[i] = props;
}
}
}
}