123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- using System;
- using System.Collections.Generic;
- using UnityEngine.Assertions;
- using UnityEngine.Rendering;
- using Unity.Mathematics;
-
- #if UNITY_EDITOR
- using UnityEditor;
- #endif
-
- namespace UnityEngine.Rendering.UnifiedRayTracing
- {
- internal class AccelStructAdapter : IDisposable
- {
- private IRayTracingAccelStruct _accelStruct;
- AccelStructInstances _instances;
-
- internal AccelStructInstances Instances { get => _instances; }
-
- struct InstanceIDs
- {
- public int InstanceID;
- public int AccelStructID;
- }
-
- private readonly Dictionary<int, InstanceIDs[]> _objectHandleToInstances = new();
-
- public AccelStructAdapter(IRayTracingAccelStruct accelStruct, GeometryPool geometryPool)
- {
- _accelStruct = accelStruct;
- _instances = new AccelStructInstances(geometryPool);
- }
-
- public AccelStructAdapter(IRayTracingAccelStruct accelStruct, RayTracingResources resources)
- : this(accelStruct, new GeometryPool(GeometryPoolDesc.NewDefault(), resources.geometryPoolKernels, resources.copyBuffer))
- { }
-
- public IRayTracingAccelStruct GetAccelerationStructure()
- {
- return _accelStruct;
- }
-
- public GeometryPool GeometryPool => _instances.geometryPool;
-
- public void Bind(CommandBuffer cmd, string propertyName, IRayTracingShader shader)
- {
- shader.SetAccelerationStructure(cmd, propertyName, _accelStruct);
- _instances.Bind(cmd, shader);
- }
-
- public void Dispose()
- {
- _instances?.Dispose();
- _instances = null;
- _accelStruct?.Dispose();
- _accelStruct = null;
- _objectHandleToInstances.Clear();
- }
-
- public void AddInstance(int objectHandle, Component meshRendererOrTerrain, uint[] perSubMeshMask, uint[] perSubMeshMaterialIDs)
- {
- if (meshRendererOrTerrain is Terrain terrain)
- {
- Debug.Assert(terrain.enabled, "Terrains are expected to be enabled.");
- var terrainDesc = new TerrainDesc();
- terrainDesc.terrain = terrain;
- terrainDesc.mask = perSubMeshMask[0];
- terrainDesc.materialID = perSubMeshMaterialIDs[0];
- AddInstance(objectHandle, terrainDesc);
- }
- else
- {
- var meshRenderer = (MeshRenderer)meshRendererOrTerrain;
- Debug.Assert(meshRenderer.enabled, "Mesh renderers are expected to be enabled.");
- Debug.Assert(!meshRenderer.isPartOfStaticBatch, "Mesh renderers are expected to not be part of static batch.");
- var mesh = meshRenderer.GetComponent<MeshFilter>().sharedMesh;
- AddInstance(objectHandle, mesh, meshRenderer.transform.localToWorldMatrix, perSubMeshMask, perSubMeshMaterialIDs);
- }
- }
-
- public void AddInstance(int objectHandle, Mesh mesh, Matrix4x4 localToWorldMatrix, uint[] perSubMeshMask, uint[] perSubMeshMaterialIDs)
- {
- int subMeshCount = mesh.subMeshCount;
-
- var instances = new InstanceIDs[subMeshCount];
- for (int i = 0; i < subMeshCount; ++i)
- {
- var instanceDesc = new MeshInstanceDesc(mesh, i)
- {
- localToWorldMatrix = localToWorldMatrix,
- mask = perSubMeshMask[i],
- };
-
- instances[i].InstanceID = _instances.AddInstance(instanceDesc, perSubMeshMaterialIDs[i]);
- instanceDesc.instanceID = (uint)instances[i].InstanceID;
- instances[i].AccelStructID = _accelStruct.AddInstance(instanceDesc);
- }
-
- _objectHandleToInstances.Add(objectHandle, instances);
- }
-
- private void AddInstance(int objectHandle, TerrainDesc terrainDesc)
- {
- List<InstanceIDs> instanceHandles = new List<InstanceIDs>();
-
- AddHeightmap(terrainDesc, ref instanceHandles);
- AddTrees(terrainDesc, ref instanceHandles);
-
- _objectHandleToInstances.Add(objectHandle, instanceHandles.ToArray());
-
- }
-
- void AddHeightmap(TerrainDesc terrainDesc, ref List<InstanceIDs> instanceHandles)
- {
- var terrainMesh = TerrainToMesh.Convert(terrainDesc.terrain);
- var instanceDesc = new MeshInstanceDesc(terrainMesh);
- instanceDesc.localToWorldMatrix = terrainDesc.localToWorldMatrix;
- instanceDesc.mask = terrainDesc.mask;
- instanceDesc.enableTriangleCulling = terrainDesc.enableTriangleCulling;
- instanceDesc.frontTriangleCounterClockwise = terrainDesc.frontTriangleCounterClockwise;
-
- instanceHandles.Add(AddInstance(instanceDesc, terrainDesc.materialID));
-
- }
-
- void AddTrees(TerrainDesc terrainDesc, ref List<InstanceIDs> instanceHandles)
- {
- TerrainData terrainData = terrainDesc.terrain.terrainData;
- float4x4 terrainLocalToWorld = terrainDesc.localToWorldMatrix;
- float3 positionScale = new float3((float)terrainData.heightmapResolution, 1.0f, (float)terrainData.heightmapResolution) * terrainData.heightmapScale;
- float3 positionOffset = new float3(terrainLocalToWorld[3].x, terrainLocalToWorld[3].y, terrainLocalToWorld[3].z);
-
- foreach (var treeInstance in terrainData.treeInstances)
- {
- var localToWorld = Matrix4x4.TRS(
- positionOffset + new float3(treeInstance.position) * positionScale,
- Quaternion.AngleAxis(treeInstance.rotation, Vector3.up),
- new Vector3(treeInstance.widthScale, treeInstance.heightScale, treeInstance.widthScale));
-
- var prefab = terrainData.treePrototypes[treeInstance.prototypeIndex].prefab;
- var mesh = prefab.gameObject.GetComponent<MeshFilter>().sharedMesh;
- if (!mesh)
- continue;
-
- for (int i = 0; i < mesh.subMeshCount; ++i)
- {
- var instanceDesc = new MeshInstanceDesc(mesh, i);
- instanceDesc.localToWorldMatrix = localToWorld;
- instanceDesc.mask = terrainDesc.mask;
- instanceDesc.enableTriangleCulling = terrainDesc.enableTriangleCulling;
- instanceDesc.frontTriangleCounterClockwise = terrainDesc.frontTriangleCounterClockwise;
- instanceHandles.Add(AddInstance(instanceDesc, terrainDesc.materialID));
- }
- }
- }
-
- InstanceIDs AddInstance(MeshInstanceDesc instanceDesc, uint materialID)
- {
- InstanceIDs res = new InstanceIDs();
- res.InstanceID = _instances.AddInstance(instanceDesc, materialID);
- instanceDesc.instanceID = (uint)res.InstanceID;
- res.AccelStructID = _accelStruct.AddInstance(instanceDesc);
-
- return res;
- }
-
-
- public void RemoveInstance(int objectHandle)
- {
- bool success = _objectHandleToInstances.TryGetValue(objectHandle, out var instances);
- Assert.IsTrue(success);
-
- foreach (var instance in instances)
- {
- _instances.RemoveInstance(instance.InstanceID);
- _accelStruct.RemoveInstance(instance.AccelStructID);
- }
-
- _objectHandleToInstances.Remove(objectHandle);
- }
-
- public void UpdateInstanceTransform(int objectHandle, Matrix4x4 localToWorldMatrix)
- {
- bool success = _objectHandleToInstances.TryGetValue(objectHandle, out var instances);
- Assert.IsTrue(success);
-
- foreach(var instance in instances)
- {
- _instances.UpdateInstanceTransform(instance.InstanceID, localToWorldMatrix);
- _accelStruct.UpdateInstanceTransform(instance.AccelStructID, localToWorldMatrix);
- }
- }
-
- public void UpdateInstanceMaterialIDs(int objectHandle, uint[] perSubMeshMaterialIDs)
- {
- bool success = _objectHandleToInstances.TryGetValue(objectHandle, out var instances);
- Assert.IsTrue(success);
- Assert.IsTrue(perSubMeshMaterialIDs.Length >= instances.Length);
- int i = 0;
- foreach (var instance in instances)
- {
- _instances.UpdateInstanceMaterialID(instance.InstanceID, perSubMeshMaterialIDs[i++]);
- }
- }
-
- public void UpdateInstanceMask(int objectHandle, uint[] perSubMeshMask)
- {
- bool success = _objectHandleToInstances.TryGetValue(objectHandle, out var instances);
- Assert.IsTrue(success);
- Assert.IsTrue(perSubMeshMask.Length >= instances.Length);
- int i = 0;
- foreach (var instance in instances)
- {
- _instances.UpdateInstanceMask(instance.InstanceID, perSubMeshMask[i]);
- _accelStruct.UpdateInstanceMask(instance.AccelStructID, perSubMeshMask[i]);
- i++;
- }
- }
-
- public void Build(CommandBuffer cmd, ref GraphicsBuffer scratchBuffer)
- {
- RayTracingHelper.ResizeScratchBufferForBuild(_accelStruct, ref scratchBuffer);
- _accelStruct.Build(cmd, scratchBuffer);
- }
-
- public void NextFrame()
- {
- _instances.NextFrame();
- }
-
- public bool GetInstanceIDs(int rendererID, out int[] instanceIDs)
- {
- if (!_objectHandleToInstances.TryGetValue(rendererID, out InstanceIDs[] instIDs))
- {
- // This should never happen as long as the renderer was already added to the acceleration structure
- instanceIDs = null;
- return false;
- }
- instanceIDs = Array.ConvertAll(instIDs, item => item.InstanceID);
- return true;
- }
-
- }
-
- internal struct TerrainDesc
- {
- public Terrain terrain;
- public Matrix4x4 localToWorldMatrix;
- public uint mask;
- public uint materialID;
- public bool enableTriangleCulling;
- public bool frontTriangleCounterClockwise;
-
- public TerrainDesc(Terrain terrain)
- {
- this.terrain = terrain;
- localToWorldMatrix = Matrix4x4.identity;
- mask = 0xFFFFFFFF;
- materialID = 0;
- enableTriangleCulling = true;
- frontTriangleCounterClockwise = false;
- }
- }
- }
|