You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MiniGames/Assets/MudBun/Script/MudLockedMeshRenderer.cs

280 lines
9.0 KiB
C#

/******************************************************************************/
/*
Project - MudBun
Publisher - Long Bunny Labs
http://LongBunnyLabs.com
Author - Ming-Lun "Allen" Chou
http://AllenChou.net
*/
/******************************************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace MudBun
{
[ExecuteInEditMode]
public class MudLockedMeshRenderer : MonoBehaviour, ISerializationCallbackReceiver
{
private class ComputeBufferCache
{
public int RefCount;
public int [] IndirectDrawArgsData;
public GenPoint [] GenPointsData;
public ComputeBuffer IndirectDrawArgsBuffer;
public ComputeBuffer GenPointsBuffer;
public void Release()
{
IndirectDrawArgsData = null;
GenPointsData = null;
IndirectDrawArgsBuffer.Release();
GenPointsBuffer.Release();
IndirectDrawArgsBuffer = null;
GenPointsBuffer = null;
}
}
private static Dictionary<int, ComputeBufferCache> s_bufferCachePool = new Dictionary<int, ComputeBufferCache>();
[SerializeField] [HideInInspector] private int m_numVerts = 0;
[SerializeField] [HideInInspector] private int [] m_indirectDrawArgsData;
[SerializeField] [HideInInspector] private GenPoint [] m_aGenPointData;
[SerializeField] [HideInInspector] private Aabb m_renderBoundsRs;
public Material RenderMaterial;
private Material m_materialCloned;
private Material m_materialUsed;
public Color MasterColor;
public Color MasterEmission;
public float MasterMetallic;
public float MasterSmoothness;
[SerializeField] [HideInInspector] private MudRendererBase.RenderModeEnum m_renderMode = MudRendererBase.RenderModeEnum.SmoothMesh;
[SerializeField] [HideInInspector] private float m_voxelDensity = 1.0f;
[ConditionalField("m_renderMode",
MudRendererBase.RenderModeEnum.CircleSplats,
MudRendererBase.RenderModeEnum.QuadSplats,
Min = 0.0f, Max = 5.0f)]
public float SplatSize = 1.0f;
[ConditionalField("m_renderMode",
MudRendererBase.RenderModeEnum.CircleSplats,
MudRendererBase.RenderModeEnum.QuadSplats,
Min = 0.0f, Max = 360.0f)]
public float SplatRotation = 0.0f;
[ConditionalField("m_renderMode",
MudRendererBase.RenderModeEnum.CircleSplats,
MudRendererBase.RenderModeEnum.QuadSplats,
Min = 0.1f, Max = 10.0f)]
public float SplatRotationNoisiness = 1.0f;
[ConditionalField("m_renderMode",
MudRendererBase.RenderModeEnum.CircleSplats,
MudRendererBase.RenderModeEnum.QuadSplats,
Min = 0.0f, Max = 1.0f)]
public float SplatCameraFacing = 1.0f;
public ShadowCastingMode CastShadows = ShadowCastingMode.On;
public bool ReceiveShadows = true;
private ComputeBuffer m_indirectDrawArgsBuffer;
private ComputeBuffer m_genPointsBuffer;
private MaterialPropertyBlock m_renderMaterialProps;
[SerializeField] [HideInInspector] private int m_hash;
public void Config
(
ComputeBuffer drawArgsBuffer,
ComputeBuffer getPointsBuffer,
MudRendererBase renderer
)
{
m_indirectDrawArgsData = new int[5];
drawArgsBuffer.GetData(m_indirectDrawArgsData);
m_numVerts = m_indirectDrawArgsData[0];
m_aGenPointData = new GenPoint[m_numVerts];
getPointsBuffer.GetData(m_aGenPointData);
RenderMaterial = renderer.RenderMaterial;
MasterColor = renderer.MasterColor;
MasterEmission = renderer.MasterEmission;
MasterMetallic = renderer.MasterMetallic;
MasterSmoothness = renderer.MasterSmoothness;
m_renderBoundsRs = renderer.RenderBoundsRs;
m_renderMode = renderer.RenderMode;
m_voxelDensity = renderer.VoxelDensity;
SplatSize = renderer.SplatSize;
SplatRotation = renderer.SplatRotationJitter;
SplatCameraFacing = renderer.SplatCameraFacing;
CastShadows = renderer.CastShadows;
ReceiveShadows = renderer.ReceiveShadows;
m_hash = Codec.Hash(GetHashCode());
m_hash = Codec.HashConcat(m_hash, DateTime.Now.Ticks);
Validate();
}
public void OnBeforeSerialize()
{
ComputeBufferCache bufferCache;
if (s_bufferCachePool.TryGetValue(m_hash, out bufferCache))
{
m_indirectDrawArgsData = bufferCache.IndirectDrawArgsData;
m_aGenPointData = bufferCache.GenPointsData;
}
}
public void OnAfterDeserialize() { }
private void OnEnable()
{
}
private void OnDisable()
{
m_indirectDrawArgsBuffer = null;
m_genPointsBuffer = null;
ComputeBufferCache bufferCache = null;
if (s_bufferCachePool.TryGetValue(m_hash, out bufferCache))
{
--bufferCache.RefCount;
if (bufferCache.RefCount == 0)
{
bufferCache.Release();
s_bufferCachePool.Remove(m_hash);
}
}
}
private void Validate()
{
if (m_indirectDrawArgsBuffer == null
|| m_genPointsBuffer == null)
{
ComputeBufferCache bufferCache = null;
if (s_bufferCachePool.TryGetValue(m_hash, out bufferCache))
{
m_indirectDrawArgsBuffer = bufferCache.IndirectDrawArgsBuffer;
m_genPointsBuffer = bufferCache.GenPointsBuffer;
m_indirectDrawArgsData = null;
m_aGenPointData = null;
++bufferCache.RefCount;
}
else if (m_indirectDrawArgsData != null
&& m_aGenPointData != null)
{
m_indirectDrawArgsBuffer = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments);
m_indirectDrawArgsBuffer.SetData(m_indirectDrawArgsData);
m_genPointsBuffer = new ComputeBuffer(m_numVerts, GenPoint.Stride);
m_genPointsBuffer.SetData(m_aGenPointData);
s_bufferCachePool.Add
(
m_hash,
new ComputeBufferCache()
{
RefCount = 1,
IndirectDrawArgsData = m_indirectDrawArgsData,
GenPointsData = m_aGenPointData,
IndirectDrawArgsBuffer = m_indirectDrawArgsBuffer,
GenPointsBuffer = m_genPointsBuffer
}
);
m_indirectDrawArgsData = null;
m_aGenPointData = null;
}
else
{
Assert.Warn("Null constant buffers and no data to initialize from.");
}
}
if (m_renderMaterialProps == null)
{
m_renderMaterialProps = new MaterialPropertyBlock();
}
}
private void LateUpdate()
{
Validate();
Render();
}
private void BindRenderResources()
{
MudRendererBase.ValidateShaderConstantId();
m_renderMaterialProps.SetBuffer(MudRendererBase.Const.GenPoints, m_genPointsBuffer);
m_renderMaterialProps.SetColor(MudRendererBase.Const.MasterColor, MasterColor);
m_renderMaterialProps.SetColor(MudRendererBase.Const.MasterEmission, MasterEmission);
m_renderMaterialProps.SetFloat(MudRendererBase.Const.MasterMetallic, MasterMetallic);
m_renderMaterialProps.SetFloat(MudRendererBase.Const.MasterSmoothness, MasterSmoothness);
m_renderMaterialProps.SetFloat(MudRendererBase.Const.SplatSize, SplatSize * (1.5f / m_voxelDensity));
m_renderMaterialProps.SetFloat(MudRendererBase.Const.SplatRotationJitter, SplatRotation * MathUtil.Deg2Rad);
m_renderMaterialProps.SetFloat(MudRendererBase.Const.SplatJitterNoisiness, SplatRotationNoisiness);
m_renderMaterialProps.SetFloat(MudRendererBase.Const.SplatCameraFacing, SplatCameraFacing);
m_renderMaterialProps.SetMatrix(MudRendererBase.Const.LocalToWorld, transform.localToWorldMatrix);
m_renderMaterialProps.SetMatrix(MudRendererBase.Const.LocalToWorldIt, transform.localToWorldMatrix.inverse.transpose);
m_renderMaterialProps.SetVector(MudRendererBase.Const.LocalToWorldScale, transform.localScale);
}
private void Render()
{
if (m_indirectDrawArgsBuffer == null
|| m_genPointsBuffer == null
|| RenderMaterial == null
|| m_renderBoundsRs.IsEmpty
|| RenderMaterial == null)
return;
BindRenderResources();
var renderBounds = m_renderBoundsRs;
renderBounds.Transform(transform);
if (m_materialCloned != RenderMaterial)
{
m_materialUsed = new Material(RenderMaterial);
m_materialCloned = RenderMaterial;
}
m_materialUsed.CopyPropertiesFromMaterial(m_materialCloned);
if (ReceiveShadows)
RenderMaterial.EnableKeyword("MUDBUN_RECEIVE_SHADOWS");
else
RenderMaterial.DisableKeyword("MUDBUN_RECEIVE_SHADOWS");
Graphics.DrawProceduralIndirect
(
RenderMaterial,
new Bounds(renderBounds.Center, renderBounds.Size),
MeshTopology.Triangles,
m_indirectDrawArgsBuffer,
0,
null,
m_renderMaterialProps,
CastShadows,
ReceiveShadows,
gameObject.layer
);
}
}
}