// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Max820/Cel Shader" { Properties{ // _Color("Color", Color) = (1,1,1,1) _MainTex("Base Texture (RGB)", 2D) = "white" {} _SSSTex("SSS Texture (RGB)", 2D) = "white" {} _ILMTex("ILM Texture (RGB)", 2D) = "white" {} _OutlineColor("Outline Color", Color) = (0,0,0,1) _Outline("Outline Width", Range(.0, 2)) = .5 _ShadowContrast("Shadow Contrast", Range(0, 20)) = 1 _DarkenInnerLine("Darken Inner Line", Range(0, 1)) = 0.2 // _LightDirection("Light Direction", Vector) = (0,0,1) } CGINCLUDE #include "UnityCG.cginc" sampler2D _MainTex; sampler2D _SSSTex; struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float4 texCoord : TEXCOORD0; //float4 vertexColor : COLOR; }; struct v2f { float4 pos : POSITION; float4 color : COLOR; float4 tex : TEXCOORD0; }; uniform float _Outline; uniform float4 _OutlineColor; uniform float _ShadowContrast; uniform float _DarkenInnerLine; // uniform half3 _LightDirection; v2f vert(appdata v) { // just make a copy of incoming vertex data but scaled according to normal direction v2f o; o.pos = UnityObjectToClipPos(v.vertex); float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal); float2 offset = TransformViewToProjection(norm.xy); o.pos.xy += offset * _Outline * 0.5 ; o.tex = v.texCoord; o.color = _OutlineColor ; return o; } ENDCG SubShader { //Tags {"Queue" = "Geometry+100" } CGPROGRAM #pragma surface surfA Lambert //fixed4 _Color; struct Input { float2 uv_MainTex; }; void surfA(Input IN, inout SurfaceOutput o) { half4 c2 = half4(1, 0, 1, 1); o.Albedo = c2.rgb ; o.Alpha = c2.a; } ENDCG // note that a vertex shader is specified here but its using the one above Pass{ Name "OUTLINE" Tags{ "LightMode" = "Always" } Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha //Offset 50,50 //Lighting Off CGPROGRAM #pragma vertex vert #pragma fragment frag half4 frag(v2f i) :COLOR { fixed4 cLight = tex2D(_MainTex, i.tex.xy); fixed4 cSSS = tex2D(_SSSTex, i.tex.xy); fixed4 cDark = cLight * cSSS; cDark = cDark *0.5f;// *cDark * cDark; cDark.a = 1; // weapon had alpha? //return cDark; return (i.color + cDark ); } ENDCG } // Pass // ############################### CGPROGRAM // noforwardadd: important to remove multiple light passes #pragma surface surf CelShadingForward vertex:vertB #pragma target 3.0 sampler2D _ILMTex; struct Input { float2 uv_MainTex; float3 vertexColor; // Vertex color stored here by vert() method }; struct v2fB { float4 pos : SV_POSITION; fixed4 color : COLOR; }; void vertB(inout appdata_full v, out Input o) { UNITY_INITIALIZE_OUTPUT(Input, o); o.vertexColor = v.color ; // Save the Vertex Color in the Input for the surf() method } struct SurfaceOutputCustom { fixed3 Albedo; fixed3 Normal; fixed3 Emission; fixed Alpha; half3 BrightColor; half3 ShadowColor; half3 InnerLineColor; half ShadowThreshold; half SpecularIntensity; half SpecularSize; //fixed4 ILM; }; half4 LightingCelShadingForward(SurfaceOutputCustom s, half3 lightDir, /*half3 viewDir,*/ half atten) { // lightDir = _LightDirection; // Cell shading: Threshold (<=0, > 90 deg away from light), light vector, normal vector [control] half NdotL = dot(lightDir, s.Normal); // NdotL = smoothstep(0, 1.0f, NdotL); // NdotL = smoothstep(0, 0.025f, NdotL); half testDot = (NdotL + 1) / 2.0; // color 0 to 1. black = shadow, white = light half4 c = half4(0, 0, 0, 1); half4 specColor = half4(s.SpecularIntensity, s.SpecularIntensity, s.SpecularIntensity, 1); half blendArea = 0.04; NdotL -= s.ShadowThreshold; half specStrength = s.SpecularIntensity;// = 0.1f + s.SpecularIntensity;// > 1 = brighter, < 1 = darker if (NdotL < 0) // <= s.ShadowThreshold) { if ( NdotL < - s.SpecularSize -0.5f && specStrength <= 0.5f) // -0.5f) { c.rgb = s.ShadowColor *(0.5f + specStrength);// (specStrength + 0.5f);// 0.5f; // *s.ShadowColor; } else { c.rgb = s.ShadowColor; } } else { if (s.SpecularSize < 1 && NdotL * 1.8f > s.SpecularSize && specStrength >= 0.5f) // 0.5f) // 1.0f) { c.rgb = s.BrightColor * (0.5f + specStrength);// 1.5f;// *(specStrength * 2);// 2; // lighter } else { c.rgb = s.BrightColor; } } // add inner lines c.rgb = c.rgb * s.InnerLineColor ; return c; } void surf(Input IN, inout SurfaceOutputCustom o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D(_MainTex, IN.uv_MainTex); fixed4 cSSS = tex2D(_SSSTex, IN.uv_MainTex); fixed4 cILM = tex2D(_ILMTex, IN.uv_MainTex); o.BrightColor = c.rgb; o.ShadowColor = c.rgb * cSSS.rgb; float clampedLineColor = cILM.a; if (clampedLineColor < _DarkenInnerLine) clampedLineColor = _DarkenInnerLine; o.InnerLineColor = half3(clampedLineColor, clampedLineColor, clampedLineColor); float vertColor = (IN.vertexColor.r - 0.5) * _ShadowContrast + 0.5; //IN.vertexColor.r; // easier to combine black dark areas o.ShadowThreshold = cILM.g; o.ShadowThreshold *= vertColor; o.ShadowThreshold = 1 - o.ShadowThreshold; // flip black / white o.SpecularIntensity = cILM.r;// 1 + (1 - cILM.r);// +cILM.r;// *2; // make whiter o.SpecularSize = 1-cILM.b;// * 0.25f); } ENDCG } FallBack "Diffuse" }