summaryrefslogtreecommitdiff
path: root/Thronefall_v1.0/Decompile/GPUInstancingManager.cs
blob: 99d9dab260b44314775d6231028c6654042a37da (plain)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System.Collections.Generic;
using UnityEngine;

public class GPUInstancingManager : MonoBehaviour
{
	private struct MaterialMeshPair
	{
		public Material material;

		public Mesh mesh;
	}

	private struct TransformMatrixPair
	{
		public List<Transform> transforms;

		public List<Matrix4x4> matrices;
	}

	public static GPUInstancingManager Instance;

	[Tooltip("Do not change this during runtime!")]
	[SerializeField]
	private bool gpuInstancingEnabled = true;

	[SerializeField]
	private bool debugLogs;

	private Dictionary<MaterialMeshPair, TransformMatrixPair> matMeshPairToRenderersDictionary;

	private List<Matrix4x4> transformMatricesBuffer = new List<Matrix4x4>();

	private void Awake()
	{
		if (gpuInstancingEnabled)
		{
			Instance = this;
		}
		else
		{
			Instance = null;
		}
		matMeshPairToRenderersDictionary = new Dictionary<MaterialMeshPair, TransformMatrixPair>();
	}

	private void Update()
	{
		int num = 0;
		int num2 = 0;
		foreach (KeyValuePair<MaterialMeshPair, TransformMatrixPair> item in matMeshPairToRenderersDictionary)
		{
			TransformMatrixPair value = item.Value;
			for (int i = 0; i < value.transforms.Count; i++)
			{
				if (value.transforms[i] != null)
				{
					value.matrices[i] = value.transforms[i].localToWorldMatrix;
				}
			}
			if (value.matrices.Count >= 1024)
			{
				Debug.LogWarning("Drawing too many meshes with mesh: " + item.Key.mesh.ToString());
			}
			try
			{
				Graphics.DrawMeshInstanced(item.Key.mesh, 0, item.Key.material, value.matrices);
			}
			catch
			{
				Debug.LogError("GPU instancing with material failed: " + item.Key.material.ToString());
			}
			num += value.transforms.Count;
			num2++;
		}
	}

	public void AddVirtualMeshRenderer(Mesh mesh, Material material, Transform transform)
	{
		MaterialMeshPair key = default(MaterialMeshPair);
		key.material = material;
		key.mesh = mesh;
		if (!matMeshPairToRenderersDictionary.TryGetValue(key, out var value))
		{
			TransformMatrixPair transformMatrixPair = default(TransformMatrixPair);
			transformMatrixPair.transforms = new List<Transform>();
			transformMatrixPair.matrices = new List<Matrix4x4>();
			value = transformMatrixPair;
			matMeshPairToRenderersDictionary[key] = value;
		}
		value.transforms.Add(transform);
		value.matrices.Add(transform.localToWorldMatrix);
	}

	public void RemoveVirtualMeshRenderer(Mesh mesh, Material material, Transform transform)
	{
		MaterialMeshPair key = default(MaterialMeshPair);
		key.material = material;
		key.mesh = mesh;
		if (matMeshPairToRenderersDictionary.TryGetValue(key, out var value))
		{
			int num = value.transforms.IndexOf(transform);
			if (num != -1)
			{
				value.transforms.RemoveAt(num);
				value.matrices.RemoveAt(num);
			}
			if (value.transforms.Count == 0)
			{
				matMeshPairToRenderersDictionary.Remove(key);
			}
		}
	}

	public void UpdateVirtualMeshRenderer(Mesh oldMesh, Material oldMaterial, Mesh newMesh, Material newMaterial, Transform transform)
	{
		RemoveVirtualMeshRenderer(oldMesh, oldMaterial, transform);
		AddVirtualMeshRenderer(newMesh, newMaterial, transform);
	}
}