Is it possible to make a surface shader like that?
My objective is to create a ‘toon shader’ that has 3 light levels, fully lighted, medium and dark.
Each light level has it’s own color, defined in 3 different albedo textures
Multiple lights should be able to affect the shader, the atten of the pixel should be the highest (default implementation seems to add all lights)
Light color should be weighted average of all light colors based on their respective attens.
Is it possible at all? reading the generated frag_surf code it seems to run once per light source, making it impossible?
So far I’ve almost achieved what I want, the issue being that I can’t seem to change the default shadow color (ambient light) to the per pixel target shadow color.
This is the shader I have so far
Code So Far
Shader "Custom/Surface Toon Shader"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_BumpMap ("Normals ", 2D) = "bump" {}
_HeightMap("Height Map", 2D) = "white" {}
_Color("Color", Color) = (1, 1, 1, 1)
_SColor1("ShadowColor 1", Color) = (1, 1, 1, 1)
_SColor2("ShadowColor 2", Color) = (1, 1, 1, 1)
_SHADOW_SATURATOR1("Saturate Shadows 1", Range(1, 4)) = 1.3
_SHADOW_SATURATOR2("Saturate Shadows 2", Range(1, 4)) = 1.6
_SHADOW_NERF("Nerf/Buff Shadows", Range(-1, 1)) = 0.40
_BaseColor_Step("Shadow Step", Range(0, 1)) = 0.66
_BaseShade_Feather("Shadow Feather", Range(0, 1)) = 0
_ShadeColor_Step("Shadow 2 Step", Range(0, 2)) = 1.03
_1st2nd_Shades_Feather("Shadow 2 Feather", Range(0, 1)) = 0
_HeightPower("Height Power", Range(0,.125)) = 0.0226
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
}
LOD 200
ZWrite on
CGPROGRAM
#include "AutoLight.cginc"
#pragma surface surf CelShadingForward addshadow fullforwardshadows
#pragma target 3.0
#include "Lighting.cginc"
fixed _numofshadows;
fixed _cheat;
fixed4 _Color;
fixed4 _SColor1;
fixed4 _SColor2;
fixed _SHADOW_SATURATOR1;
fixed _SHADOW_SATURATOR2;
fixed _SHADOW_NERF;
fixed _BaseColor_Step;
fixed _BaseShade_Feather;
fixed _ShadeColor_Step;
fixed _1st2nd_Shades_Feather;
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _HeightMap;
float _HeightPower;
float3 shift_col(float3 RGB, float3 shift)
{
float3 RESULT = float3(RGB);
float VSU = shift.z * shift.y * cos(shift.x * 3.14159265 / 180);
float VSW = shift.z * shift.y * sin(shift.x * 3.14159265 / 180);
RESULT.x = (.299 * shift.z + .701 * VSU + .168 * VSW) * RGB.x
+ (.587 * shift.z - .587 * VSU + .330 * VSW) * RGB.y
+ (.114 * shift.z - .114 * VSU - .497 * VSW) * RGB.z;
RESULT.y = (.299 * shift.z - .299 * VSU - .328 * VSW) * RGB.x
+ (.587 * shift.z + .413 * VSU + .035 * VSW) * RGB.y
+ (.114 * shift.z - .114 * VSU + .292 * VSW) * RGB.z;
RESULT.z = (.299 * shift.z - .3 * VSU + 1.25 * VSW) * RGB.x
+ (.587 * shift.z - .588 * VSU - 1.05 * VSW) * RGB.y
+ (.114 * shift.z + .886 * VSU - .203 * VSW) * RGB.z;
return (RESULT);
}
struct SurfaceOutput2
{
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Specular;
fixed Gloss;
fixed Alpha;
};
inline fixed4 LightingCelShadingForward(SurfaceOutput2 s, half3 lightDir, half atten) // * (atten)
{
const float Set_LightColor = length(saturate(_LightColor0.rgb) * atten);
const float3 Set_BaseColor = s.Albedo * _Color;
float4 _1st_ShadeMap_var = float4(s.Albedo * _SColor1, 1);//This version of the shader auto calculates the shadow 1 and shadow 2 colors instead of taking it from a texture
_1st_ShadeMap_var.rgb = shift_col(_1st_ShadeMap_var.rgb, float3(1, _SHADOW_SATURATOR1, 1));
float4 _2nd_ShadeMap_var = float4(s.Albedo * _SColor2, 1);
_2nd_ShadeMap_var.rgb = shift_col(_2nd_ShadeMap_var.rgb, float3(1, _SHADOW_SATURATOR2, 1));
const float NoTL = dot(s.Normal, lightDir);
const float ShadowNerfed = (1 - _SHADOW_NERF) * NoTL + _SHADOW_NERF;
const float _HalfLambert_var = 1 - min(ShadowNerfed, ShadowNerfed * Set_LightColor);
const float Set_FinalShadowMask = saturate(
1.0 + (_HalfLambert_var - (_BaseColor_Step - _BaseShade_Feather)) / (_BaseColor_Step - (_BaseColor_Step
- _BaseShade_Feather)));
float3 Set_FinalBaseColor = lerp(
Set_BaseColor,
lerp(
_1st_ShadeMap_var,
_2nd_ShadeMap_var,
saturate(
(1.0 + ((_HalfLambert_var - (_ShadeColor_Step - _1st2nd_Shades_Feather))) / (_ShadeColor_Step -
(_ShadeColor_Step - _1st2nd_Shades_Feather))))),
Set_FinalShadowMask);//This logic was taken form the Unity Toon Shader package
return lerp(half4(Set_FinalBaseColor, 1), half4(0, 0, 0, 1), 1-saturate(atten*100));
}
struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
float3 worldNormal;
float2 uv_HeightMap;
float3 viewDir;
INTERNAL_DATA
};
inline void surf(Input IN, inout SurfaceOutput2 o)
{
const float2 texOffset = ParallaxOffset(tex2D(_HeightMap, IN.uv_HeightMap).r, _HeightPower, IN.viewDir);
fixed4 c = tex2D(_MainTex, IN.uv_MainTex + texOffset);
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap + texOffset));
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}