- Home /
Add Alpha information into the standard toon shader
What I'm trying to do: I have a 2D level set up, and the player starts in a box to protect them from enemies. The side of the box that releases the player into the map slowly fades out and when it turns fully transparent it destroys allowing the player to enter the map. My problem is my level assets are shaded using Unity's Toon/Basic Outline shader, and to get this to work I had to use a shader with Alpha information on the wall I want to have fade out, so it looks slightly different from the rest of the level.
My question Would it then be possible to add alpha information into Unity's Toon/Basic Outline shader so I could have that wall look the same?
If this is a dumb or simple question I apologize, I'm brand new to shaders. As always any help is appreciated.
Answer by skovacs1 · Oct 13, 2010 at 08:04 PM
Shaders are not entirely obvious so it's perfectly reasonable to ask for help with them.
There are three things that you should concern yourself with when making a shader transparent:
- Blend mode. Should be something like
Blend SrcAlpha OneMinusSrcAlpha
- Culling. Should be on.
- Render Queue. Not entirely as breaking, but still important. Your subshader tags should be something like
Tags {"Queue"="Transparent" "RenderType"="Transparent"}
The Toon Outline shaders already take care of blending the alpha for the outlines, although changing the subshaders' render queue wouldn't hurt. All you really need to worry about is the basic shader. If you remove the Cull Off
statements from each pass, add Blend SrcAlpha OneMinusSrcAlpha
to each pass and change the Subshader Tags to Tags {"Queue"="Transparent" "RenderType"="Transparent"}
, you will achieve what you are looking for:
Shader "Toon/Basic" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _MainTex ("Base (RGB)", 2D) = "white" {} _ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { Texgen CubeNormal } }
SubShader {
Tags {"Queue"="Transparent" "RenderType"="Transparent"} //Change this
Pass {
Name "BASE"
//Cull Off //Remove this
Blend SrcAlpha OneMinusSrcAlpha //Add This
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
sampler2D _MainTex;
samplerCUBE _ToonShade;
float4 _MainTex_ST;
float4 _Color;
struct appdata {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : POSITION;
float2 texcoord : TEXCOORD0;
float3 cubenormal : TEXCOORD1;
};
v2f vert (appdata v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
o.cubenormal = mul (UNITY_MATRIX_MV, float4(v.normal,0));
return o;
}
float4 frag (v2f i) : COLOR {
float4 col = _Color * tex2D(_MainTex, i.texcoord);
float4 cube = texCUBE(_ToonShade, i.cubenormal);
return float4(2.0f * cube.rgb * col.rgb, col.a);
}
ENDCG
}
}
SubShader {
Tags {"Queue"="Transparent" "RenderType"="Transparent"} //Change this
Pass {
Name "BASE"
//Cull Off //Remove this
Blend SrcAlpha OneMinusSrcAlpha //Add this
SetTexture [_MainTex] {
constantColor [_Color]
Combine texture * constant
}
SetTexture [_ToonShade] {
combine texture * previous DOUBLE, previous
}
}
}
Fallback "VertexLit"
}
Bear in mind that the outline is using the outline color's alpha while the surface uses the color's alpha. If you want both to use the color's alpha, you would have to adjust the fragment program of the outline to use that value:
Shader "Toon/Basic Outline" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _OutlineColor ("Outline Color", Color) = (0,0,0,1) _Outline ("Outline width", Range (.002, 0.03)) = .005 _MainTex ("Base (RGB)", 2D) = "white" { } _ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { Texgen CubeNormal } }
CGINCLUDE
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : POSITION;
float4 color : COLOR;
};
uniform float4 _Color; //Add This
uniform float _Outline;
uniform float4 _OutlineColor;
v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 norm = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
norm.x *= UNITY_MATRIX_P[0][0];
norm.y *= UNITY_MATRIX_P[1][1];
o.pos.xy += norm.xy * o.pos.z * _Outline;
o.color = float4(_OutlineColor.rgb, _Color.a); //Change this
return o;
}
ENDCG
SubShader {
Tags {"Queue"="Transparent" "RenderType"="Transparent"} //Change this if you like
UsePass "Toon/Basic/BASE"
Pass {
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
half4 frag(v2f i) :COLOR { return i.color; }
ENDCG
}
}
SubShader {
Tags {"Queue"="Transparent" "RenderType"="Transparent"} //Change this if you like
UsePass "Toon/Basic/BASE"
Pass {
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma exclude_renderers gles xbox360 ps3
ENDCG
SetTexture [_MainTex] { combine primary }
}
}
Fallback "Toon/Basic"
}
i tried this, but it only works on the outlines...
i want the alpha on the texture, not the outline..
i want glass, with outlines
any idea?
Thanks! Had some trouble copy-pasting your code because it's separated, but I figured it out and here's your code into a working shader:
// Upgrade NOTE: replaced 'mul(UNITY_$$anonymous$$ATRIX_$$anonymous$$VP,*)' with 'UnityObjectToClipPos(*)'
Shader "Toon/Basic" {
Properties{
_Color("$$anonymous$$ain Color", Color) = (.5,.5,.5,1)
_$$anonymous$$ainTex("Base (RGB)", 2D) = "white" {}
_ToonShade("ToonShader Cubemap(RGB)", CUBE) = "" { }
}
SubShader{
Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" } //Change this
Pass{
Name "BASE"
//Cull Off //Remove this
Blend SrcAlpha One$$anonymous$$inusSrcAlpha //Add This
CGPROGRA$$anonymous$$
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
sampler2D _$$anonymous$$ainTex;
samplerCUBE _ToonShade;
float4 _$$anonymous$$ainTex_ST;
float4 _Color;
struct appdata {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NOR$$anonymous$$AL;
};
struct v2f {
float4 pos : POSITION;
float2 texcoord : TEXCOORD0;
float3 cubenormal : TEXCOORD1;
};
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFOR$$anonymous$$_TEX(v.texcoord, _$$anonymous$$ainTex);
o.cubenormal = mul(UNITY_$$anonymous$$ATRIX_$$anonymous$$V, float4(v.normal,0));
return o;
}
float4 frag(v2f i) : COLOR{
float4 col = _Color * tex2D(_$$anonymous$$ainTex, i.texcoord);
float4 cube = texCUBE(_ToonShade, i.cubenormal);
return float4(2.0f * cube.rgb * col.rgb, col.a);
}
ENDCG
}
}
SubShader{
Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" } //Change this
Pass{
Name "BASE"
//Cull Off //Remove this
Blend SrcAlpha One$$anonymous$$inusSrcAlpha //Add this
SetTexture[_$$anonymous$$ainTex]{
constantColor[_Color]
Combine texture * constant
}
SetTexture[_ToonShade]{
combine texture * previous DOUBLE, previous
}
}
}
Fallback "VertexLit"
}
Answer by No_Username_Found · Apr 08, 2015 at 02:06 AM
I don't mean to necro-post, but this helped me and I want to expand on it for future coders.
The fix mentioned by skovacs1 will create a shader for transparent toon-shading. This shader should NOT be used on non-transparent objects or non-alpha textures - if you do, then the transparent object will cull the objects behind them and you will see straight through the world.
Use skovacs1's code to make a Toony-Basic-Transparency shader. Use the -Transparency shader on the objects than need it, and the normal Toony-Basic on other opaque objects.
Answer by Urre · May 26, 2011 at 12:44 PM
Hi!
I tried adding this shader to my trees, but it has a problem with the leaves behind leaves. Leaves behind planes with transparent parts don't show up. Any way to fix this?
I don't know how to fix it, but I feel safe in saying that this is caused by the culling...
Your answer
![](https://koobas.hobune.stream/wayback/20220613075547im_/https://answers.unity.com/themes/thub/images/avi.jpg)