- Home /
Shader error: output TEXCOORD1 used more than once
Hi there! I am trying to make a Alpha cutout shader with a toon effect so that I can use it on character. The compiler is giving me an error in unity in 2020.3.2f1 with URP
What should I do about my shader? Am I missing something? I would have used shader graph, except it wasn't working with zwrite or something so the character kept showing up weird with the skin rendered in front of the clothes... a whole other issue that I couldn't figure out. If you have any other recommendations, please let me know.
Thank you for your help in advance!
//This is a toon cutout shader that applies an alpha clip with a toon shader.
Shader "Toon/ToonCutout"
{
Properties {
_Color("Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
[HDR]
_AmbientColor("Ambient Color", Color) = (0.4,0.4,0.4,1)
[HDR]
_SpecularColor("Specular Color", Color) = (0.9,0.9,0.9,1)
_Glossiness("Glossiness", Float) = 32
[HDR]
_ShadowColor("ShadowColor", Color) = (0.1,0.1,0.1,1)
[HDR]
_RimColor("Rim Color", Color) = (1,1,1,1)
_RimAmount("Rim Amount", Range(0, 1)) = 0.716
_RimThreshold("Rim Threshold", Range(0, 1)) = 0.1
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" "LightMode" = "UniversalForward" "PassFlags" = "OnlyDirectional"}
LOD 100
Lighting Off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct appdata_t {
float4 pos : POSITION;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD0;
float3 worldNormal : NORMAL;
float3 viewDir : TEXCOORD1;
UNITY_FOG_COORDS(1)
UNITY_VERTEX_OUTPUT_STEREO
SHADOW_COORDS(2)
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _Cutoff;
v2f vert (appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos(v.pos);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.viewDir = WorldSpaceViewDir(v.pos);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
UNITY_TRANSFER_FOG(o,o.pos);
TRANSFER_SHADOW(o)
return o;
}
float4 _Color;
float4 _AmbientColor;
float4 _SpecularColor;
float _Glossiness;
float4 _RimColor;
float _RimAmount;
float _RimThreshold;
float4 _ShadowColor;
fixed4 frag (v2f i) : SV_Target
{
float3 normal = normalize(i.worldNormal);
float3 viewDir = normalize(i.viewDir);
float NdotL = dot(_WorldSpaceLightPos0, normal);
float shadow = SHADOW_ATTENUATION(i);
float lightIntensity = smoothstep(0, 0.01, NdotL * shadow);
float4 light = lightIntensity * _LightColor0;
float3 halfVector = normalize(_WorldSpaceLightPos0 + viewDir);
float NdotH = dot(normal, halfVector);
float specularIntensity = pow(NdotH * lightIntensity, _Glossiness * _Glossiness);
float specularIntensitySmooth = smoothstep(0.005, 0.01, specularIntensity);
float4 specular = specularIntensitySmooth * _SpecularColor;
float rimDot = 1 - dot(viewDir, normal);
float rimIntensity = rimDot * pow(NdotL, _RimThreshold);
rimIntensity = smoothstep(_RimAmount - 0.01, _RimAmount + 0.01, rimIntensity);
float4 rim = rimIntensity * _RimColor;
float4 sample = tex2D(_MainTex, i.texcoord);
fixed4 col = tex2D(_MainTex, i.texcoord);
clip(col.a - _Cutoff);
UNITY_APPLY_FOG(i.fogCoord, col);
return (light + _AmbientColor + specular + rim + ( (1-light) * _ShadowColor)) * _Color * col;
}
ENDCG
}
UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
}
}
Answer by Eno-Khaon · Aug 19, 2021 at 02:52 AM
To address the problem of your subject line, "Shader error: output TEXCOORD1 used more than once":
Unity's Shader struct macros look different, but still use input based on which TEXCOORD number you'll be getting back out of it.
float3 viewDir : TEXCOORD1;
UNITY_FOG_COORDS(1)
SHADOW_COORDS(2)
Specifically, UNITY_FOG_COORDS(1)
and SHADOW_COORDS(2)
are building one of many different data-type sets based on the hardware requirements/capabilities and settings, then sending them through using TEXCOORD# (1 for fog and 2 for shadows in this case).
Right "UNITY_FOG_COORDS" is a classical C-style macro and is defined inside "UnityCG.cginc" file as such:
#define UNITY_FOG_COORDS_PACKED(idx, vectype) vectype fogCoord : TEXCOORD##idx;
#define UNITY_FOG_COORDS(idx) UNITY_FOG_COORDS_PACKED(idx, float1)
So when you use
UNITY_FOG_COORDS(1)
What you actually have in that line is this:
float1 fogCoord : TEXCOORD1;
Macros represent a pure replace mechanism. The great thing about such macros is that they can have different implementations depending on other preprocessor defines. So whenever you want to use fog you use this macro to define the actual fogCoord member. However if fog is disabled, this macro will not define anything. So it makes the actual shader code much more versatile and flexible.
Though you are still responsible to use the different texture coordinates properly. That's why those macros have parameters ^^.