2020-12-04 01:53:23 +00:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using UnityEngine.Rendering;
|
2026-06-30 19:14:49 +01:00
|
|
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class Stardust : MonoBehaviour
|
|
|
|
|
|
{
|
2026-06-30 19:14:49 +01:00
|
|
|
|
private static readonly List<Stardust> Instances = new List<Stardust>();
|
|
|
|
|
|
|
2020-12-04 01:53:23 +00:00
|
|
|
|
#region variables
|
|
|
|
|
|
//public bool debugLog = false;
|
|
|
|
|
|
//public float proxyPersistTime = 2;
|
2021-06-18 12:32:03 +01:00
|
|
|
|
public GameSettings Settings;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
public Camera TargetCamera;
|
|
|
|
|
|
public ComputeShader ParticleCalculation;
|
|
|
|
|
|
public Material ParticleMaterial;
|
|
|
|
|
|
public int Span = 512;
|
2022-07-17 05:27:50 +01:00
|
|
|
|
public float Period = .25f;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
|
|
|
|
|
|
public float MinimumSize = .1f;
|
|
|
|
|
|
public float MaximumSize = 2;
|
|
|
|
|
|
|
|
|
|
|
|
public float Spacing = 4.0f;
|
|
|
|
|
|
public float Ceiling = -250.0f;
|
|
|
|
|
|
public float Floor = -25.0f;
|
2022-07-21 21:40:44 +01:00
|
|
|
|
public float MinHeadroom = 25;
|
|
|
|
|
|
public float MaxHeadroom = 100;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
public float HeightExponent = 4;
|
|
|
|
|
|
|
2021-06-18 12:32:03 +01:00
|
|
|
|
public RenderTexture NebulaSurfaceHeight;
|
|
|
|
|
|
public RenderTexture NebulaPatchHeight;
|
|
|
|
|
|
public RenderTexture NebulaPatch;
|
|
|
|
|
|
public RenderTexture NebulaTint;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
public Texture Heightmap;
|
|
|
|
|
|
public Texture2D ParticleColors;
|
|
|
|
|
|
//public Transform TargetTransform;
|
|
|
|
|
|
public Camera GravityCamera;
|
|
|
|
|
|
|
2021-06-18 12:32:03 +01:00
|
|
|
|
private float _flowScroll;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
private const int GROUP_SIZE = 128;
|
|
|
|
|
|
private int _updateParticlesKernel;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Structs
|
|
|
|
|
|
//Notice that this struct has to match the one in the compute shader exactly.
|
|
|
|
|
|
struct Particle
|
|
|
|
|
|
{
|
|
|
|
|
|
public Vector3 Position;
|
|
|
|
|
|
public Vector3 Color; //Color is a float3 in the compute shader, we need a Vector3 to match that layout, not a Color!
|
|
|
|
|
|
public float Size;
|
|
|
|
|
|
};
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region buffers
|
|
|
|
|
|
private ComputeBuffer _particlesBuffer;
|
|
|
|
|
|
private const int PARTICLE_STRIDE = 28;
|
|
|
|
|
|
|
|
|
|
|
|
private ComputeBuffer _quadPoints;
|
|
|
|
|
|
private const int QUAD_STRIDE = 12;
|
2026-06-30 19:14:49 +01:00
|
|
|
|
private bool _buffersReady;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-06-30 19:14:49 +01:00
|
|
|
|
public static void RenderForCamera(UnsafeCommandBuffer cmd, Camera camera, TextureHandle colorTarget, TextureHandle depthTarget)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (var i = 0; i < Instances.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var stardust = Instances[i];
|
|
|
|
|
|
if (stardust == null || !stardust.isActiveAndEnabled || stardust.TargetCamera != camera)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
stardust.RenderStardust(cmd, colorTarget, depthTarget);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-04 01:53:23 +00:00
|
|
|
|
#region setup
|
2026-06-30 19:14:49 +01:00
|
|
|
|
private void OnEnable()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Instances.Contains(this))
|
|
|
|
|
|
Instances.Add(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnDisable()
|
|
|
|
|
|
{
|
|
|
|
|
|
Instances.Remove(this);
|
|
|
|
|
|
ReleaseBuffers();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-04 01:53:23 +00:00
|
|
|
|
// Use this for initialization
|
|
|
|
|
|
void Start()
|
|
|
|
|
|
{
|
2026-06-30 19:14:49 +01:00
|
|
|
|
EnsureBuffers();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void EnsureBuffers()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_buffersReady && (_particlesBuffer == null || _quadPoints == null))
|
|
|
|
|
|
_buffersReady = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (_buffersReady)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (ParticleCalculation == null || ParticleMaterial == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2020-12-04 01:53:23 +00:00
|
|
|
|
//Find compute kernel
|
|
|
|
|
|
_updateParticlesKernel = ParticleCalculation.FindKernel("UpdateParticles");
|
|
|
|
|
|
|
|
|
|
|
|
//Create particle buffer
|
|
|
|
|
|
_particlesBuffer = new ComputeBuffer(Span * Span, PARTICLE_STRIDE);
|
|
|
|
|
|
|
|
|
|
|
|
Particle[] particles = new Particle[Span * Span];
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < Span * Span; ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
particles[i].Position = Random.insideUnitSphere * 100;
|
2021-06-18 12:32:03 +01:00
|
|
|
|
particles[i].Color = Vector3.one; //white
|
2020-12-04 01:53:23 +00:00
|
|
|
|
particles[i].Size = Random.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_particlesBuffer.SetData(particles);
|
|
|
|
|
|
|
|
|
|
|
|
//Create quad buffer
|
|
|
|
|
|
_quadPoints = new ComputeBuffer(6, QUAD_STRIDE);
|
|
|
|
|
|
|
|
|
|
|
|
_quadPoints.SetData(new[] {
|
|
|
|
|
|
new Vector3(-.5f, .5f),
|
|
|
|
|
|
new Vector3(.5f, .5f),
|
|
|
|
|
|
new Vector3(.5f, -.5f),
|
|
|
|
|
|
new Vector3(.5f, -.5f),
|
|
|
|
|
|
new Vector3(-.5f, -.5f),
|
|
|
|
|
|
new Vector3(-.5f, .5f)
|
|
|
|
|
|
});
|
2026-06-30 19:14:49 +01:00
|
|
|
|
|
|
|
|
|
|
_buffersReady = true;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Compute update
|
|
|
|
|
|
// Update is called once per frame
|
|
|
|
|
|
void Update()
|
|
|
|
|
|
{
|
2026-06-30 19:14:49 +01:00
|
|
|
|
EnsureBuffers();
|
|
|
|
|
|
if (!_buffersReady || GravityCamera == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (_particlesBuffer == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_buffersReady = false;
|
|
|
|
|
|
EnsureBuffers();
|
|
|
|
|
|
if (!_buffersReady)
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-04 01:53:23 +00:00
|
|
|
|
//Bind resources to compute shader
|
|
|
|
|
|
ParticleCalculation.SetBuffer(_updateParticlesKernel, "particles", _particlesBuffer);
|
|
|
|
|
|
|
2022-07-17 05:27:50 +01:00
|
|
|
|
ParticleCalculation.SetFloat("time", Time.time);
|
2020-12-04 01:53:23 +00:00
|
|
|
|
|
|
|
|
|
|
var pos = GravityCamera.transform.position;
|
2022-07-17 05:27:50 +01:00
|
|
|
|
ParticleCalculation.SetFloat("period", Period);
|
2020-12-04 01:53:23 +00:00
|
|
|
|
ParticleCalculation.SetFloat("spacing", Spacing);
|
|
|
|
|
|
ParticleCalculation.SetFloat("ceilingHeight", Ceiling);
|
|
|
|
|
|
ParticleCalculation.SetFloat("floorHeight", Floor);
|
|
|
|
|
|
ParticleCalculation.SetFloat("heightExponent", HeightExponent);
|
|
|
|
|
|
ParticleCalculation.SetFloat("maximumSize", MaximumSize);
|
|
|
|
|
|
ParticleCalculation.SetFloat("minimumSize", MinimumSize);
|
2022-07-21 21:40:44 +01:00
|
|
|
|
ParticleCalculation.SetFloat("minHeadroom", MinHeadroom);
|
|
|
|
|
|
ParticleCalculation.SetFloat("maxHeadroom", MaxHeadroom);
|
2020-12-04 01:53:23 +00:00
|
|
|
|
ParticleCalculation.SetInt("span", Span);
|
|
|
|
|
|
|
|
|
|
|
|
ParticleCalculation.SetTexture(_updateParticlesKernel, "HueTexture", ParticleColors);
|
|
|
|
|
|
|
|
|
|
|
|
//Dispatch, launch threads on GPU
|
|
|
|
|
|
int numberOfGroups = Mathf.CeilToInt((float)Span * Span / GROUP_SIZE);
|
|
|
|
|
|
ParticleCalculation.Dispatch(_updateParticlesKernel, numberOfGroups, 1, 1);
|
2026-06-30 19:14:49 +01:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RenderStardust(UnsafeCommandBuffer cmd, TextureHandle colorTarget, TextureHandle depthTarget)
|
|
|
|
|
|
{
|
|
|
|
|
|
EnsureBuffers();
|
|
|
|
|
|
if (!_buffersReady || ParticleMaterial == null || _particlesBuffer == null || _quadPoints == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2020-12-04 01:53:23 +00:00
|
|
|
|
ParticleMaterial.SetBuffer("particles", _particlesBuffer);
|
|
|
|
|
|
ParticleMaterial.SetBuffer("quadPoints", _quadPoints);
|
2026-06-30 19:14:49 +01:00
|
|
|
|
|
|
|
|
|
|
if (depthTarget.IsValid())
|
|
|
|
|
|
cmd.SetRenderTarget(colorTarget, depthTarget);
|
|
|
|
|
|
else
|
|
|
|
|
|
cmd.SetRenderTarget(colorTarget);
|
|
|
|
|
|
|
|
|
|
|
|
cmd.DrawProcedural(Matrix4x4.identity, ParticleMaterial, 0, MeshTopology.Triangles, 6, Span * Span);
|
2020-12-04 01:53:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region rendering
|
|
|
|
|
|
// void OnRenderObject()
|
|
|
|
|
|
// {
|
|
|
|
|
|
// if (Camera.current == TargetCamera || Camera.current.name == "SceneCamera")
|
|
|
|
|
|
// {
|
|
|
|
|
|
// //Bind resources to material
|
|
|
|
|
|
// ParticleMaterial.SetBuffer("particles", _particlesBuffer);
|
|
|
|
|
|
// ParticleMaterial.SetBuffer("quadPoints", _quadPoints);
|
|
|
|
|
|
// // ParticleMaterial.SetFloat("velocityStretch", ParticleVelocityStretch);
|
|
|
|
|
|
// // ParticleMaterial.SetVector("velocity", PlayerVelocity);
|
|
|
|
|
|
//
|
|
|
|
|
|
// //Set the pass
|
|
|
|
|
|
// ParticleMaterial.SetPass(0);
|
|
|
|
|
|
//
|
|
|
|
|
|
// //Draw
|
|
|
|
|
|
// Graphics.DrawProceduralNow(MeshTopology.Triangles, 6, Span * Span);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region cleanup
|
|
|
|
|
|
void OnDestroy()
|
|
|
|
|
|
{
|
2026-06-30 19:14:49 +01:00
|
|
|
|
ReleaseBuffers();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ReleaseBuffers()
|
|
|
|
|
|
{
|
|
|
|
|
|
_particlesBuffer?.Release();
|
|
|
|
|
|
_quadPoints?.Release();
|
|
|
|
|
|
_particlesBuffer = null;
|
|
|
|
|
|
_quadPoints = null;
|
|
|
|
|
|
_buffersReady = false;
|
2020-12-04 01:53:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|