Hi, I got a problem when trying to add an outline(just like as a toon shader) to a curved shader with unity 5.
This one is the original curved shader which works fine.
Shader "Custom/Curved" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_QOffset ("Offset", Vector) = (0,0,0,0)
_Brightness ("Brightness", Float) = 0.0
_Dist ("Distance", Float) = 100.0
}
SubShader {
Tags { "Queue" = "Transparent"}
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _QOffset;
float _Dist;
float _Brightness;
struct v2f {
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float3 viewDir : TEXCOORD1;
fixed4 color : COLOR;
};
v2f vert (appdata_full v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f, o);
float4 vPos = mul (UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z/_Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul (UNITY_MATRIX_P, vPos);
o.uv = v.texcoord;
return o;
}
half4 frag (v2f i) : COLOR0
{
half4 col = tex2D(_MainTex, i.uv.xy);
col *= UNITY_LIGHTMODEL_AMBIENT*_Brightness;
return col;
}
ENDCG
}
}
FallBack "Diffuse"
}
What have you tried to make it work?
You can just add a second pass (before the already existing one) with the same vertex code for the curving, but with an additional increase. Most toon shader take the same approach.
Sorry I am a beginner for the shader, I was trying to add the outline (that additional increase) base on the vertex code after curving. Please advise me how to do that instead modify the same vertex?
Thanks a lot!!
Shader "Custom/ToonCurved" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_QOffset ("Offset", Vector) = (0,0,0,0)
_Dist ("Distance", Float) = 100.0
_Alpha ("Alpha", Range(0.0,1.0)) = 1.0
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_Outline ("Outline width", Range (.002, 0.03)) = .005
_Color ("Main Color", Color) = (0.5,0.5,0.5,1)
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100
ZWrite On
Blend SrcAlpha OneMinusSrcAlpha
UsePass "Toon/Lit/FORWARD"
Pass
{
Lighting Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _QOffset;
float _Dist;
float _Alpha;
uniform float4 _MainTex_ST;
uniform float _Outline;
uniform float4 _OutlineColor;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 color : COLOR;
};
v2f vert (appdata_base v)
{
v2f o;
float4 vPos = mul (UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z/_Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul (UNITY_MATRIX_P, vPos);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
float2 offset = TransformViewToProjection(norm.xy);
//o.pos.xy += offset * o.pos.z * _Outline;
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 frag (v2f i) : COLOR
{
return tex2D(_MainTex, i.uv) * float4(1,1,1,_Alpha);
}
ENDCG
}
}
Fallback "Toon/Lit"
}
Add another pass, not just the line 
Something like this:
Shader "Custom/ToonCurved"
{
Properties
{
_MainTex("Base (RGB)", 2D) = "white" {}
_QOffset("Offset", Vector) = (0,0,0,0)
_Dist("Distance", Float) = 100.0
_Alpha("Alpha", Range(0.0,1.0)) = 1.0
_OutlineColor("Outline Color", Color) = (0,0,0,1)
_Outline("Outline width", Range(.002, 0.03)) = .005
_Color("Main Color", Color) = (0.5,0.5,0.5,1)
}
SubShader
{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
LOD 100
ZWrite On
Blend SrcAlpha OneMinusSrcAlpha
// Outline pass
Pass
{
Lighting Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 _QOffset;
float _Dist;
float _Alpha;
uniform float _Outline;
uniform float4 _OutlineColor;
struct v2f
{
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert(appdata_base v)
{
v2f o;
float4 vPos = mul(UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z / _Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul(UNITY_MATRIX_P, vPos);
float3 norm = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, v.normal));
float2 offset = TransformViewToProjection(norm.xy);
o.pos.xy += offset * o.pos.z * _Outline;
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 frag(v2f i) : COLOR
{
return i.color;
}
ENDCG
}
// Normal pass
Pass
{
Lighting Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _QOffset;
float _Dist;
float _Alpha;
uniform float4 _MainTex_ST;
uniform float _Outline;
uniform float4 _OutlineColor;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 color : COLOR;
};
v2f vert(appdata_base v)
{
v2f o;
float4 vPos = mul(UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z / _Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul(UNITY_MATRIX_P, vPos);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 frag(v2f i) : COLOR
{
return tex2D(_MainTex, i.uv) * float4(1,1,1,_Alpha);
}
ENDCG
}
}
Fallback "Toon/Lit"
}
Note that I did not really test this, you might need to adjust some things here and there.
It works!!! Many thanks!!!
One more question, how can this shader have shadow?
Shader "Custom/ToonCurved" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_QOffset ("Offset", Vector) = (0,0,0,0)
_Dist ("Distance", Float) = 100.0
_Alpha ("Alpha", Range(0.0,1.0)) = 1.0
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_Outline ("Outline width", Range (.002, 0.03)) = .005
_Color ("Main Color", Color) = (0.5,0.5,0.5,1)
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100
ZWrite On
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _QOffset;
float _Dist;
float _Alpha;
uniform float4 _MainTex_ST;
uniform float _Outline;
uniform float4 _OutlineColor;
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
v2f vert (appdata v)
{
v2f o;
float4 vPos = mul (UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z/_Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul (UNITY_MATRIX_P, vPos);
float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
float2 offset = TransformViewToProjection(norm.xy);
o.pos.xy += offset * o.pos.z * _Outline;
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 frag (v2f i) : COLOR
{
UNITY_APPLY_FOG(i.fogCoord, i.color);
return i.color;
}
ENDCG
}
// Normal pass
Pass
{
Lighting Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _QOffset;
float _Dist;
float _Alpha;
uniform float4 _MainTex_ST;
uniform float _Outline;
uniform float4 _OutlineColor;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 color : COLOR;
};
v2f vert(appdata_base v)
{
v2f o;
float4 vPos = mul(UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z / _Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul(UNITY_MATRIX_P, vPos);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 frag(v2f i) : COLOR
{
return tex2D(_MainTex, i.uv) * float4(1,1,1,_Alpha);
}
ENDCG
}
}
Fallback "Toon/Lit"
}
I’m not sure if this is still valid for Unity 5.x, but read this:
Thanks again! I tried some tutorials which are almost same with this, but it seems not working
Shader "Custom/ToonCurved" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_QOffset ("Offset", Vector) = (0,0,0,0)
_Dist ("Distance", Float) = 100.0
_Alpha ("Alpha", Range(0.0,1.0)) = 1.0
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_Outline ("Outline width", Range (.002, 0.03)) = .005
_Color ("Main Color", Color) = (0.5,0.5,0.5,1)
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Tags {"LightMode" = "ForwardBase"}
LOD 100
Pass
{
Name "OUTLINE"
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _QOffset;
float _Dist;
float _Alpha;
uniform float4 _MainTex_ST;
uniform float _Outline;
uniform float4 _OutlineColor;
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
v2f vert (appdata v)
{
v2f o;
float4 vPos = mul (UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z/_Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul (UNITY_MATRIX_P, vPos);
float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
float2 offset = TransformViewToProjection(norm.xy);
o.pos.xy += offset * o.pos.z * _Outline;
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 frag (v2f i) : COLOR
{
UNITY_APPLY_FOG(i.fogCoord, i.color);
return i.color;
}
ENDCG
}
// Normal pass
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase
#include "AutoLight.cginc"
sampler2D _MainTex;
float4 _QOffset;
float _Dist;
float _Alpha;
uniform float4 _MainTex_ST;
uniform float _Outline;
uniform float4 _OutlineColor;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 color : COLOR;
LIGHTING_COORDS(0,1)
};
v2f vert(appdata_base v)
{
v2f o;
float4 vPos = mul(UNITY_MATRIX_MV, v.vertex);
float zOff = vPos.z / _Dist;
vPos += _QOffset*zOff*zOff;
o.pos = mul(UNITY_MATRIX_P, vPos);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.color = _OutlineColor;
UNITY_TRANSFER_FOG(o,o.pos);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
fixed4 frag(v2f i) : COLOR
{
float attenuation = LIGHT_ATTENUATION(i);
return tex2D(_MainTex, i.uv) * float4(1,1,1,_Alpha) * attenuation;
}
ENDCG
}
}
Fallback "VertexLit"
}
Could be multiple things:
-
Tags {“LightMode”=“ForwardBase”} is a Pass Tag and should be used in a pass, not the subshader.
-
LIGHTING_COORDS(0,1) - you’re using 0 for your uv coordinates. use 1 and 2 instead.
-
Are shadows enabled? (see Quality Settings)
-
Are you using a directional light? (other light sources require a different Light mode and #pragma multi_compile_fwdadd instead of #pragma multi_compile_fwdbase)
Could be any or all of these things.
You can probably also save yourself a lot of trouble by just using a surface shader with the outline pass added to get shadows.