I am not sure if I’m missing something obvious, but how do I resolve a shader pass name into an index I can use in Material.SetPass or CommandBuffer.DrawMesh*?
The best I found is Material.passCount to get the number of passes.
Do I need to manually store the correct pass index for each shader, or is there a Shader.PropertyToID equivalent for passes?
So, to answer my own question from years ago: There is now a function
Though I guess the Unity Renderer bases its pass selection on pass tags. So to pick the deferred pass you’ll need to look for the tag “LIGHTMODE” “DEFERRED”.
I found a lot of information is available through serialisation on the shader object, that doesn’t seem to be covered by official API. Some of it is available through
I am not sure at what point these values got added, but for example 2017.3 seems to have parsed shader info:
SerializedObject so = new SerializedObject (shader);
SerializedProperty subShaders = so.FindProperty ("m_ParsedForm.m_SubShaders");
for (int k = 0; k < subShaders.arraySize; k++) {
Debug.Log ("SubShader: " + k);
SerializedProperty subShader = subShaders.GetArrayElementAtIndex (k);
SerializedProperty passes = subShader.FindPropertyRelative ("m_Passes");
for (int i = 0; i < passes.arraySize; i++) {
Debug.Log ("Pass: " + i);
SerializedProperty pass = passes.GetArrayElementAtIndex (i);
SerializedProperty name = pass.FindPropertyRelative("m_State.m_Name");
Debug.Log("Name: " + name.stringValue);
SerializedProperty tags = pass.FindPropertyRelative ("m_State.m_Tags.tags");
for (int j = 0; j < tags.arraySize; j++) {
SerializedProperty tag = tags.GetArrayElementAtIndex (j);
SerializedProperty first = tag.FindPropertyRelative ("first");
SerializedProperty second = tag.FindPropertyRelative ("second");
Debug.Log (first.stringValue + ":" + second.stringValue);
}
}
}
Earlier versions of Unity, for example I looked at 5.4, only allow access to shader sourcecode, so getting name and pass info requires a custom parser. Sigh.
The shader pass name is quite irrelevant and i don’t think there’s any method to convert a pass name to an index. I also don’t see the point for that. A shader executes it’s passes in the order they appear inside the shader. The passes belong to that shader. So if you manually want to render something with a shader that has multiple passes you simply iterate through them starting at index 0 up to (Material.passCount - 1). If you use passes to combine different shaders into one, you use the pass wrong.