GPU Instancing тестовый скрипт

GPU Instancing тестовый скрипт

Антон Василевский
using System;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

namespace Features.Build.Sandbox
{
    public class GPUInstancingTest : MonoBehaviour
    {
        private const int MAX_OBJECTS_PER_BATCH = 1023;
        
        public Mesh instanceMesh;  // The mesh to be instanced.
        public Material instanceMaterial;  // The material with GPU instancing enabled.
        public int instanceCount = 1000;  // Number of instances.
        public float maxRange = 10f;  // Maximum range for random positions.
        public Vector3 minRotationEuler = Vector3.zero;  // Minimum rotation values.
        public Vector3 maxRotationEuler = new Vector3(360f, 360f, 360f);  // Maximum rotation values.

        private List<Matrix4x4[]> matricesList;  // Array to store instance transformations.

        private void Start()
        {
            Redraw();
        }

        [ContextMenu(nameof(Redraw))]
        private void Redraw()
        {
            matricesList = new List<Matrix4x4[]>();

            // Populate the matrices array with random instance transformations.
            for (int i = 0; i < instanceCount; i++)
            {
                // Generate random positions within the specified range.
                Vector3 randomPosition = new Vector3(
                    Random.Range(-maxRange, maxRange),
                    Random.Range(0, maxRange * 2),
                    Random.Range(-maxRange, maxRange)
                );

                // Generate random rotations within the specified range.
                Quaternion randomRotation = Quaternion.Euler(
                    new Vector3(
                        Random.Range(minRotationEuler.x, maxRotationEuler.x),
                        Random.Range(minRotationEuler.y, maxRotationEuler.y),
                        Random.Range(minRotationEuler.z, maxRotationEuler.z)
                    )
                );

                int matricesListIndex = i / MAX_OBJECTS_PER_BATCH;

                if (i % MAX_OBJECTS_PER_BATCH == 0)
                {
                    int instancePerList = instanceCount - matricesListIndex * MAX_OBJECTS_PER_BATCH;
                    if (instancePerList > MAX_OBJECTS_PER_BATCH)
                    {
                        instancePerList = MAX_OBJECTS_PER_BATCH;
                    }
                    matricesList.Add(new Matrix4x4[instancePerList]);
                }

                // Create a transformation matrix using the position and rotation.
                matricesList[matricesListIndex][i % MAX_OBJECTS_PER_BATCH] = Matrix4x4.TRS( transform.position + randomPosition, randomRotation, Vector3.one);
            }
        }

        private void Update()
        {
            if (matricesList != null)
            {
                foreach (var matrices in matricesList)
                {
                    Graphics.DrawMeshInstanced(instanceMesh, 0, instanceMaterial, matrices);
                }
            }
        }
    }
}

Телеграм-канал Jun GameDev

Report Page