Hi. I have some subshaders for each render type, opaque, transparent, etc.
How can I select one of them in C# scripts or the inspector like standard shader.
The Standard Shader, and other shaders like it, do not have different subshaders for different render types. Instead they use a single subshader and change the render state and type via material properties and settings, and change the shader code via keywords with a custom editor.
A simple setup for a shader would be something like this:
Shader "Opaque or Alpha Blend Example"
{
Properties {
_MainTex ("Texture", 2D) = "white" {}
[Toggle] _ZWrite ("ZWrite", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("SrcBlend", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("DstBlend", Float) = 0
[Toggle] _AlphaBlend ("Alpha Blend", Float) = 0
}
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
ZWrite [_ZWrite]
Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
#pragma shader_feature _ALPHABLEND_ON
sampler2D _MainTex;
fixed4 frag (v2f_img i) : SV_Target
{
fixed4 color = tex2D(_MainTex, i.uv);
// if opaque, set output alpha to 1.0
#if !defined(_ALPHABLEND_ON)
color.a = 1.0;
#endif
return color;
}
ENDCG
}
}
}
By itself that shader will let you swap between normal opaque and transparent mode, but you have to flip a lot of switches to do so. Toggle ZWrite off, set the blend mode to srcBlend SrcAlpha, dstBlend OneMinusSrcAlpha, toggle alpha blend on, and change the material’s queue to transparent. And that doesn’t change the RenderType unless you use the debug inspector and manually type stuff in.
So instead you want to use a custom shader editor so all that stuff can be toggled from a single GUI element.
So some minor tweaks to the shader, mainly in adding the CustomEditor line at the end …
Shader "Opaque or Alpha Blend Example"
{
Properties {
_MainTex ("Texture", 2D) = "white" {}
[Toggle] _ZWrite ("ZWrite", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("SrcBlend", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("DstBlend", Float) = 0
// [Toggle] _AlphaBlend ("Alpha Blend", Float) = 0 // not needed when using a custom editor
}
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
ZWrite [_ZWrite]
Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
#pragma shader_feature _ALPHABLEND_ON
sampler2D _MainTex;
fixed4 frag (v2f_img i) : SV_Target
{
fixed4 color = tex2D(_MainTex, i.uv);
// if opaque, set output alpha to 1.0
#if !defined(_ALPHABLEND_ON)
color.a = 1.0;
#endif
return color;
}
ENDCG
}
}
CustomEditor "OpaqueOrAlphaBlendGUI"
}
And writing a custom shader GUI script (placed in an “Editor” folder some place in your project) …
using UnityEngine;
using UnityEditor;
using System;
public class OpaqueOrAlphaBlendGUI : ShaderGUI
{
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
Material material = materialEditor.target as Material;
MaterialProperty mainTex = FindProperty("_MainTex", properties);
materialEditor.TextureProperty(mainTex, mainTex.displayName);
bool alphaBlend = Array.IndexOf(material.shaderKeywords, "_ALPHABLEND_ON") != -1;
EditorGUI.BeginChangeCheck();
alphaBlend = EditorGUILayout.Toggle("Alpha Blend Transparency", alphaBlend);
if (EditorGUI.EndChangeCheck())
{
if (alphaBlend)
{
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.EnableKeyword("_ALPHABLEND_ON");
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
}
else
{
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHABLEND_ON");
material.renderQueue = -1;
}
}
}
}
Thank you. I have seen codes like it. So the rendertype does not change(opaque in your example). OK.
I thought I need to change it as well. You handle it by changing ZWrite and Blend.
RenderType is almost a legacy thing. It’s only used by replacement shader passes, of which only the camera depth normals texture (when using the forward rendering path) and motion vector passes use for the built in rendering paths. The new SRPs completely remove the use of them.
Do I also need to change render queue to be consistent, when I change zwrite status or activate alpha and blend.
Yes, both examples above change the queue. Rendering something that uses a transparent blend mode and no zwrite will behave very oddly if part of the opaque queue (other objects will render on top of it, including the skybox!)


