Files
VR-WuKong/Assets/GameRes/Main/SceneArt/VRScene/Materials/GPUGrass/GrassTest.cs
2025-11-14 18:44:06 +08:00

111 lines
2.8 KiB
C#

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<InstData> dataInfors = new List<InstData>();
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<Transform>())
{
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;
}
}