using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public class GrassTest : MonoBehaviour { public Mesh mesh; public Material material; public Bounds bounds; public float scaleMult; public ShadowCastingMode shadowCastingMode; public bool isReceiveShadow; private ComputeBuffer instDataBuffer; private ComputeBuffer argsBuffer; // Mesh Properties struct to be read from the GPU. // Size() is a convenience funciton which returns the stride of the struct. public Transform root; List dataInfors = new List(); private struct InstData { public Vector3 pos; public Vector3 angle; public Vector3 scale; // public static int GetNum() { return sizeof(float) * 3 + sizeof(float) * 3 + sizeof(float) * 3; } } private void Start() { GetDataInfors(); InitializeBuffers(); } private void Update() { Graphics.DrawMeshInstancedIndirect(mesh, 0, material, bounds, argsBuffer, 0, null, shadowCastingMode, isReceiveShadow, LayerMask.NameToLayer("Instance")); } void GetDataInfors() { foreach (Transform t in root.GetComponentInChildren()) { InstData instData = new InstData(); instData.pos = t.position; instData.angle = t.eulerAngles; instData.scale = t.localScale * scaleMult; dataInfors.Add(instData); // t.gameObject.SetActive(false); } } 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)dataInfors.Count; 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); // Initialize buffer with the given population. instDataBuffer = new ComputeBuffer(dataInfors.Count, InstData.GetNum()); instDataBuffer.SetData(dataInfors); material = Instantiate(material); material.SetBuffer("_InstDataBuffer", instDataBuffer); } private void OnDisable() { // Release gracefully. if (instDataBuffer != null) { instDataBuffer.Release(); } instDataBuffer = null; if (argsBuffer != null) { argsBuffer.Release(); } argsBuffer = null; } }