Created Lightning Gun effect (Uses LineRenderer, very slow) Created GPU Lightning renderer (very fast, still needs integration)
145 lines
5.1 KiB
C#
145 lines
5.1 KiB
C#
using UnityEngine;
|
|
using System.Linq;
|
|
using UnityEngine.Assertions;
|
|
using System.Collections.Generic;
|
|
|
|
/// <summary>
|
|
/// GPUTrailIndirectCulling
|
|
/// cull processing for many camera(same position because GPUTrail faces one point)
|
|
/// </summary>
|
|
public abstract class GPUTrailIndirectCulling : GPUTrailIndirect
|
|
{
|
|
#region TypeDefine
|
|
public class Data
|
|
{
|
|
public ComputeBuffer _trailIsInViews;
|
|
public ComputeBuffer _trailIsInViewsAppend;
|
|
public ComputeBuffer _trailIsInViewArgs;
|
|
|
|
|
|
public Data(int trailNumMax, int indexNumPerTrail, int vertexBuferSize)
|
|
{
|
|
_trailIsInViews = new ComputeBuffer(trailNumMax, 4); // bool buffer but stride must be amultiple of 4
|
|
_trailIsInViewsAppend = new ComputeBuffer(trailNumMax, sizeof(uint), ComputeBufferType.Append);
|
|
_trailIsInViewArgs = new ComputeBuffer(4, sizeof(int), ComputeBufferType.IndirectArguments);
|
|
_trailIsInViewArgs.SetData(new[] { indexNumPerTrail, 1, 0, 0 });
|
|
}
|
|
|
|
public void Release()
|
|
{
|
|
new[] { _trailIsInViews, _trailIsInViewsAppend, _trailIsInViewArgs }
|
|
.Where(b => b != null)
|
|
.ToList()
|
|
.ForEach(b => b.Release());
|
|
}
|
|
|
|
const int NUM_THREAD_X = 32;
|
|
public void Update(ComputeShader cs, Camera camera, ComputeBuffer nodeBuffer, ComputeBuffer vertexBufferOrig)
|
|
{
|
|
var kernel = cs.FindKernel("ClearIsInView");
|
|
cs.SetBuffer(kernel, "_IsInViewW", _trailIsInViews);
|
|
cs.Dispatch(kernel, Mathf.CeilToInt((float)_trailIsInViews.count / NUM_THREAD_X), 1, 1);
|
|
|
|
kernel = cs.FindKernel("UpdateIsInView");
|
|
|
|
var planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
|
var normals = planes.Take(4).Select(p => p.normal).ToList();
|
|
planes.Take(4).ToList().ForEach(plane => Debug.DrawRay(camera.transform.position, plane.normal* 10f));
|
|
var normalsFloat = Enumerable.Range(0, 3).SelectMany(i => normals.Select(n => n[i])).ToArray(); // row major -> column major
|
|
cs.SetFloats("_CameraFrustumNormals", normalsFloat);
|
|
|
|
cs.SetBuffer(kernel, "_IsInViewW", _trailIsInViews);
|
|
cs.SetBuffer(kernel, "_NodeBuffer", nodeBuffer);
|
|
cs.Dispatch(kernel, Mathf.CeilToInt((float)nodeBuffer.count / NUM_THREAD_X), 1, 1);
|
|
|
|
|
|
_trailIsInViewsAppend.SetCounterValue(0);
|
|
|
|
kernel = cs.FindKernel("UpdateTrailAppend");
|
|
cs.SetBuffer(kernel, "_IsInView", _trailIsInViews);
|
|
cs.SetBuffer(kernel, "_IsInViewAppend", _trailIsInViewsAppend);
|
|
cs.Dispatch(kernel, Mathf.CeilToInt((float)_trailIsInViews.count / NUM_THREAD_X), 1, 1);
|
|
|
|
ComputeBuffer.CopyCount(_trailIsInViewsAppend, _trailIsInViewArgs, 4); // int[4]{ indexNumPerNode, trailNum, 0, 0}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
public ComputeShader _cullingCS;
|
|
public bool _cullingEnable = true;
|
|
|
|
protected override void OnRenderObjectInternal()
|
|
{
|
|
var cam = Camera.current;
|
|
if (_cullingEnable && !cam.orthographic)
|
|
{
|
|
if (!_cameraDatas.ContainsKey(cam))
|
|
{
|
|
_cameraDatas[cam] = null; // このフレームは登録だけ
|
|
}
|
|
else {
|
|
var data = _cameraDatas[cam];
|
|
if (data != null)
|
|
{
|
|
|
|
material.EnableKeyword("GPUTRAIL_TRAIL_INDEX_ON");
|
|
SetCommonMaterialParam();
|
|
|
|
material.SetBuffer("_TrailIndexBuffer", data._trailIsInViewsAppend);
|
|
material.SetPass(0);
|
|
|
|
Graphics.DrawProceduralIndirectNow(MeshTopology.Triangles, data._trailIsInViewArgs);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
base.OnRenderObjectInternal();
|
|
}
|
|
}
|
|
|
|
|
|
protected override void LateUpdate()
|
|
{
|
|
base.LateUpdate();
|
|
|
|
if (_cullingEnable)
|
|
{
|
|
_cameraDatas.Keys.Where(cam => cam == null).ToList().ForEach(cam => _cameraDatas.Remove(cam));
|
|
_cameraDatas.Keys
|
|
.Where(cam => cam.isActiveAndEnabled)
|
|
.ToList().ForEach(cam =>
|
|
{
|
|
UpdateVertexBuffer(cam);
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
Dictionary<Camera, Data> _cameraDatas = new Dictionary<Camera, Data>();
|
|
void UpdateVertexBuffer(Camera camera)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (CameraPos != camera.transform.position) {
|
|
Debug.LogWarning("GPUTrail faces to main camera. but different position camera detected! culling operation is uncertain.");
|
|
}
|
|
#endif
|
|
|
|
Data data = _cameraDatas[camera];
|
|
if ( data == null )
|
|
{
|
|
data = _cameraDatas[camera] = new Data(TrailNumMax, IndexNumPerTrail, VertexBufferSize);
|
|
}
|
|
|
|
_SetCommonParameterForCS(_cullingCS);
|
|
data.Update(_cullingCS, camera, nodeBuffer, vertexBuffer);
|
|
}
|
|
|
|
protected override void ReleaseBuffer()
|
|
{
|
|
base.ReleaseBuffer();
|
|
|
|
_cameraDatas.Values.Where(d => d!=null).ToList().ForEach(d => d.Release());
|
|
_cameraDatas.Clear();
|
|
}
|
|
}
|