I was about to open a new thread since I have to ask another question, but at this point I continue here. Back to my original code (updated):
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering;
public class ShaderVariantCollector : MonoBehaviour
{
public ShaderVariantCollection collection;
public void CollectShaderVariants()
{
collection.Clear();
// Get all renderers in the scene
Renderer[] renderers = FindObjectsOfType<Renderer>();
// Create a HashSet to store unique shader variants
HashSet<ShaderVariantCollection.ShaderVariant> shaderVariants = new HashSet<ShaderVariantCollection.ShaderVariant>();
// Iterate through all renderers and their materials
foreach (Renderer renderer in renderers)
{
Material[] materials = renderer.materials;
foreach (Material material in materials)
{
// Ensure the material has a shader
if (material.shader != null)
{
// Get the shader and its keywords
Shader shader = material.shader;
// GlobalKeyword[] global = Shader.enabledGlobalKeywords;
// var asd = global.ToArray();
// var enumerable = new List<string>(shader.keywordSpace.keywordNames);
// enumerable.AddRange(asd);
var keywords = material.shaderKeywords.Intersect(shader.keywordSpace.keywordNames).ToList();
try
{
// Create a new ShaderVariantCollection.ShaderVariant
ShaderVariantCollection.ShaderVariant variant = new ShaderVariantCollection.ShaderVariant(
shader, PassType.ScriptableRenderPipeline, keywords.ToArray());
shaderVariants.Add(variant);
Debug.Log($"Shader: {shader.name} Keywords: {string.Join(", ", keywords)}");
if (material.enableInstancing && variant.keywords.Contains("INSTANCING_ON") == false)
{
keywords.Add("INSTANCING_ON");
variant = new ShaderVariantCollection.ShaderVariant(shader, PassType.ScriptableRenderPipeline, keywords.ToArray());
shaderVariants.Add(variant);
Debug.Log($"Shader: {shader.name} Keywords: {string.Join(", ", keywords)}");
}
if (material.GetShaderPassEnabled("ShadowCaster"))
{
variant = new ShaderVariantCollection.ShaderVariant(shader, PassType.ShadowCaster, keywords.ToArray());
shaderVariants.Add(variant);
}
}
catch
{
Debug.LogError($"Skipping Shader: {shader.name} Keywords: {string.Join(", ", keywords)}");
}
}
}
}
// Create a ShaderVariantCollection and add the variants
foreach (var shaderVariant in shaderVariants)
collection.Add(shaderVariant);
}
}
The code is easy to read, as you can see what I am trying to achieve is to populate a shader variant collection with all the shaders variants I can collect from the shaders of the materials of the renderers in the current scene.
OK I thought it was going well until (some points are repeated some point are new)
-
no clue what keywords I actually have to use. My deduction was to use the intersection between the material and the shaders keyword. Seems to work, but am I missing some keywords? e.g. as you can see I have to enable INSTANCING_ON manually because the keyword is nowhere to be found otherwise
-
PassType parameter is NOT the pass type! It is actually the LightMode!! which is annoying because how can the shader variant be based only on the light mode and not also on the pass type? This stuff is very confusing. Even considering it’s just LightMode, some are missing, like Depth and DepthNormal. How am I supposed to create variances for these passes?
If I build a shader variant collection using the graphics panel, I get these variances:
Normal (what is Normal? How do I know if a Shader has a Normal pass?)
ScriptableRenderingPipeline (but some shaders do not have it, have only Normal!)
ShadowCaster (I assume I will add this manually if shadow is on?)
I actually don’t see other PassTypes. Examples

To be clear, I cannot even used the editor generated shader variant collection, because the player wants the INSTANCING_ON keyword that is NOT captured by the editor for some reason.
If I filter using the SVC generated from the editor, I get this:
2023/11/14 18:02:19.910 32130 32230 Error Unity Shader WEO/FoliageVariants, subshader 0, pass 0, stage all: variant INSTANCING_ON _ADDITIONAL_LIGHTS_VERTEX _MAIN_LIGHT_SHADOWS not found.
and in fact in the SVC you will see:
with no INSTANCING_ON for the ScriptableRenderingPipeline variances generated by