1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| using System; using UnityEngine; using Random = UnityEngine.Random;
public class GPUInstancing : MonoBehaviour { public GameObject Prefab; public int Count = 2000; public float Range = 30;
private Material mat; private Mesh mesh; private Matrix4x4[] arrMatrix4X4s; private MaterialPropertyBlock materialPropertyBlock; private void OnGUI() { if (GUI.Button(new Rect(100, 100, 200, 200), "直接创建预制体实例")) { for (int i = 0; i < Count; i++) { Vector2 pos = Random.insideUnitCircle * Range; Quaternion rot = Quaternion.Euler(0, Random.Range(0, 360), 0); Vector3 scale = Vector3.one * Random.Range(0.5f, 2); GameObject tree = Instantiate(Prefab, new Vector3(pos.x, 0, pos.y), rot); tree.transform.localScale = scale;
Color newCol = new Color(Random.value, Random.value, Random.value); MaterialPropertyBlock prop = new MaterialPropertyBlock(); prop.SetColor("_Color", newCol); tree.GetComponentInChildren<MeshRenderer>().SetPropertyBlock(prop); } } else if (GUI.Button(new Rect(100, 400, 200, 200), "Graphics创建实例")) { mesh = Prefab.GetComponentInChildren<MeshFilter>().sharedMesh; mat = Prefab.GetComponentInChildren<MeshRenderer>().sharedMaterial; arrMatrix4X4s = new Matrix4x4[Count];
materialPropertyBlock = new MaterialPropertyBlock(); Vector4[] arrColor = new Vector4[Count]; for (int i = 0; i < Count; i++) { Vector2 pos = Random.insideUnitCircle * Range; Quaternion rot = Quaternion.Euler(0, Random.Range(0, 360), 0); Vector3 scale = Vector3.one * Random.Range(0.5f, 2); arrMatrix4X4s[i] = Matrix4x4.identity; arrMatrix4X4s[i].SetTRS(new Vector3(pos.x, 0, pos.y), rot, scale); arrColor[i] = new Vector4(Random.value, Random.value, Random.value, 1); } materialPropertyBlock.SetVectorArray("_Color", arrColor); } }
private void Update() { if (arrMatrix4X4s == null) { return; } const int GRAPHICS_MESH_NUM = 511 * 2; int remain = arrMatrix4X4s.Length; int times = Mathf.CeilToInt(arrMatrix4X4s.Length * 1.0f / GRAPHICS_MESH_NUM);
for (int i = 0; i < times; i++) { if (remain >= GRAPHICS_MESH_NUM) { Matrix4x4[] m = new Matrix4x4[GRAPHICS_MESH_NUM]; Array.ConstrainedCopy(arrMatrix4X4s, i * GRAPHICS_MESH_NUM, m, 0, GRAPHICS_MESH_NUM); Graphics.DrawMeshInstanced(mesh, 0, mat, m, GRAPHICS_MESH_NUM, materialPropertyBlock); remain -= GRAPHICS_MESH_NUM; } else { Matrix4x4[] m = new Matrix4x4[remain]; Array.ConstrainedCopy(arrMatrix4X4s, i * GRAPHICS_MESH_NUM, m, 0, remain); Graphics.DrawMeshInstanced(mesh, 0, mat, m, remain, materialPropertyBlock); } } } }
|