How do I include Standard Shader and Standard Shader (Specular setup) in ShaderVariantCollections?
Playing the game, doesn’t seem to allow them to be tracked.
My VR game is using Single Pass Instanced and for some reason, I can’t choose STEREO_INSTANCING_ON…because it cannot be selected and doesn’t appear in the Shader. Yet when I look at the keywords in the Frame Debugger or the Profiler (image attached) it shows up there when it issuing a createGPUProgram call.
How are others getting these compiled if the keyword doesnt show up in the shader?
STEREO_ keywords are automatically added when compiling shader variants. They do show up in 2021.2+ where we refactored how the keywords work.
If you can’t add a variant that uses this keyword to a shader variant collection, please report a bug.
Btw, I wrote a quick and dirty script in an attempt to try and populate and warm the shader with the STEREO_INSTANCING_ON (Which DID NOT work) keyword at runtime, but it doesn’t seem to be recognized as a keyword (probably why it was refactored).
I’m all open to some other work around if possible.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
public enum ShaderKeyWordsFFS {
NONE,
DIRECTIONAL,
DIRLIGHTMAP_COMBINED,
LIGHTMAP_SHADOW_MIXING,
LIGHTPROBE_SH,
LIGHTMAP_ON,
SHADOWS_SCREEN,
_ALPHATEST_ON,
_NORMALMAP,
_SPECGLOSSMAP,
SHADOWS_SHADOWMASK,
_METALLICGLOSSMAP,
_ALPHAPREMULTIPLY_ON,
_EMISSION,
STEREO_INSTANCING_ON
};
public class CreateAndWarmShaderVariants : MonoBehaviour {
public ShaderVariantFFS[] shaderVariant;
void OnEnable() {
Load();
}
private void Load() {
var shaderVariantCollection = new ShaderVariantCollection();
List<string> keywordList = new List<string>();
for (int i = 0; i < shaderVariant.Length; i++) {
keywordList.Clear();
for (int x = 0; x < shaderVariant[i].shaderKeywords.Length; x++) {
keywordList.Add(shaderVariant[i].shaderKeywords[x].ToString());
//Debug.Log(" Add " + shaderVariant[i].shaderKeywords[x].ToString());
}
Debug.Log("Try: " + i);
try {
var variant = new ShaderVariantCollection.ShaderVariant(Shader.Find(shaderVariant[i].shader), shaderVariant[i].passType, keywordList.ToArray());
shaderVariantCollection.Add(variant);
} catch {
Debug.LogError(i + " Error for Shader " + shaderVariant[i].shader + " Keywords" + shaderVariant[i].passType);
}
}
shaderVariantCollection.WarmUp();
}
[System.Serializable]
public class ShaderVariantFFS {
public string shader;
public PassType passType;
public ShaderKeyWordsFFS[] shaderKeywords;
}
}
In UNITY 2021.3.17f1 this still seems to be an issue.
I can see a variant in the collection already which has STEREO_INSTANCING_ON but if I try to add that myself, it says passed shader keyword variant not found in shader
I’m trying to read two ShaderVariantCollections and merge them together. I may have to do it via the SerializedObject API instead.
VariantCollectionWrapper.Variant variant = new VariantCollectionWrapper.Variant(shader, PassType.ScriptableRenderPipeline,"STEREO_INSTANCING_ON");
shaderVariantCollection.Add(variant.ShaderVariant);
This is an extension method I’ve made to add the shader variant directly, which bypasses the shader keyword check it seems, but it allows me to add STEREO_INSTANCING_ON keywords which I need when merging two perfectly valid collections together.
public static bool AddShader(this ShaderVariantCollection svc, Shader shader, PassType passType, string keywords)
{
var serializedObject = new SerializedObject(svc);
SerializedProperty m_Shaders = serializedObject.FindProperty("m_Shaders");
//check if the shader is already in the collection
SerializedProperty pairProperty = null;
SerializedProperty shaderProperty = null;
SerializedProperty variantProperty = null;
for (int shaderIndex = 0; shaderIndex < m_Shaders.arraySize; shaderIndex++)
{
pairProperty = m_Shaders.GetArrayElementAtIndex(shaderIndex);
var foundShader = pairProperty.FindPropertyRelative("first");
if(foundShader.objectReferenceValue == shader)
{
shaderProperty = foundShader;
variantProperty = pairProperty.FindPropertyRelative("second.variants");
break;
}
}
//Otherwise add it
if (shaderProperty == null)
{
//add this shader to the property
int index = m_Shaders.arraySize;
m_Shaders.InsertArrayElementAtIndex(index);
pairProperty = m_Shaders.GetArrayElementAtIndex(index);
shaderProperty = pairProperty.FindPropertyRelative("first");
shaderProperty.objectReferenceValue = shader;
variantProperty = pairProperty.FindPropertyRelative("second.variants");
//clear the variants
variantProperty.ClearArray();
}
if (variantProperty != null)
{
//insert the variant
int index = variantProperty.arraySize;
variantProperty.InsertArrayElementAtIndex(index);
var variant = variantProperty.GetArrayElementAtIndex(index);
variant.FindPropertyRelative("passType").intValue = (int) passType;
variant.FindPropertyRelative("keywords").stringValue = keywords;
if (serializedObject.ApplyModifiedProperties())
{
return true;
}
}
return false;
}