| | 1 | | using System.Collections.Generic; |
| | 2 | | using UnityEngine; |
| | 3 | |
|
| | 4 | | namespace DCL.Helpers |
| | 5 | | { |
| | 6 | | public static class SRPBatchingHelper |
| | 7 | | { |
| | 8 | | public static System.Action<Material> OnMaterialProcess; |
| 1 | 9 | | static Dictionary<int, int> crcToQueue = new Dictionary<int, int>(); |
| | 10 | |
|
| | 11 | | public static void OptimizeMaterial(Material material) |
| | 12 | | { |
| | 13 | | //NOTE(Brian): Just enable these keywords so the SRP batcher batches more stuff. |
| 154 | 14 | | material.EnableKeyword("_EMISSION"); |
| 154 | 15 | | material.EnableKeyword("_NORMALMAP"); |
| | 16 | |
|
| 154 | 17 | | if (!material.IsKeywordEnabled("_ALPHATEST_ON")) |
| 77 | 18 | | material.SetFloat(ShaderUtils.Cutoff, 0); |
| | 19 | |
|
| 154 | 20 | | material.EnableKeyword("_ALPHATEST_ON"); |
| 154 | 21 | | material.DisableKeyword("_ALPHABLEND_ON"); |
| 154 | 22 | | material.DisableKeyword("_ENVIRONMENTREFLECTIONS_OFF"); |
| 154 | 23 | | material.DisableKeyword("_SPECULARHIGHLIGHTS_OFF"); |
| 154 | 24 | | material.DisableKeyword("VERTEX_COLOR_ON"); |
| | 25 | |
|
| 154 | 26 | | material.enableInstancing = false; |
| | 27 | |
|
| 154 | 28 | | if (material.HasProperty(ShaderUtils.ZWrite)) |
| | 29 | | { |
| 152 | 30 | | int zWrite = (int) material.GetFloat(ShaderUtils.ZWrite); |
| | 31 | |
|
| | 32 | | //NOTE(Brian): for transparent meshes skip further variant optimization. |
| | 33 | | // Transparency needs clip space z sorting to be displayed correctly. |
| 152 | 34 | | if (zWrite == 0) |
| | 35 | | { |
| 0 | 36 | | material.SetInt("_Surface", 1); |
| 0 | 37 | | material.DisableKeyword("_SCREEN_SPACE_OCCLUSION"); |
| 0 | 38 | | material.SetShaderPassEnabled("DepthNormals", false); |
| 0 | 39 | | material.renderQueue = (int) UnityEngine.Rendering.RenderQueue.Transparent; |
| 0 | 40 | | OnMaterialProcess?.Invoke(material); |
| 0 | 41 | | return; |
| | 42 | | } |
| | 43 | | } |
| | 44 | |
|
| 154 | 45 | | material.SetInt("_Surface", 0); |
| | 46 | |
|
| 154 | 47 | | int cullMode = (int) UnityEngine.Rendering.CullMode.Off; |
| | 48 | |
|
| 154 | 49 | | if (material.HasProperty(ShaderUtils.Cull)) |
| | 50 | | { |
| 152 | 51 | | cullMode = 2 - (int) material.GetFloat(ShaderUtils.Cull); |
| | 52 | | } |
| | 53 | |
|
| | 54 | | int baseQueue; |
| | 55 | |
|
| 154 | 56 | | if (material.renderQueue == (int) UnityEngine.Rendering.RenderQueue.AlphaTest) |
| 13 | 57 | | baseQueue = (int) UnityEngine.Rendering.RenderQueue.Geometry + 600; |
| | 58 | | else |
| 141 | 59 | | baseQueue = (int) UnityEngine.Rendering.RenderQueue.Geometry; |
| | 60 | |
|
| | 61 | | //NOTE(Brian): This guarantees grouping calls by same shader keywords. Needed to take advantage of SRP batch |
| 154 | 62 | | string appendedKeywords = material.shader.name + string.Join("", material.shaderKeywords); |
| 154 | 63 | | int crc = Shader.PropertyToID(appendedKeywords); |
| | 64 | |
|
| 154 | 65 | | if (!crcToQueue.ContainsKey(crc)) |
| 4 | 66 | | crcToQueue.Add(crc, crcToQueue.Count + 1); |
| | 67 | |
|
| | 68 | | //NOTE(Brian): we use 0, 100, 200 to group calls by culling mode (must group them or batches will break). |
| 154 | 69 | | int queueOffset = (cullMode + 1) * 150; |
| 154 | 70 | | material.renderQueue = baseQueue + crcToQueue[crc] + queueOffset; |
| 154 | 71 | | OnMaterialProcess?.Invoke(material); |
| 0 | 72 | | } |
| | 73 | | } |
| | 74 | | } |