Basically I want a sprite to apply lighting without taking the incidence angle into consideration. I only want the lighting to take range between light source and surface into consideration, so that a light actually illuminates the back of a wall or sprite.
This would be very easy to do if the surface-shader wasn’t hiding the math behind the lighting. Is there any way to get the shader without the surface part?
Or is there any way to do this in the surface shader?
Or am I screwed because Unity reasons?
Solved it.
You can actually override Unity lighting!
Code that does what I want:
Shader "Sprites/DiffusePoint"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha
CGPROGRAM
#pragma surface surf PointLambert vertex:vert nofog keepalpha
#pragma multi_compile _ PIXELSNAP_ON
#pragma shader_feature ETC1_EXTERNAL_ALPHA
sampler2D _MainTex;
fixed4 _Color;
sampler2D _AlphaTex;
half4 LightingPointLambert(SurfaceOutput s, half3 lightDir, half atten) {
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * atten;
c.a = s.Alpha;
return c;
}
struct Input
{
float2 uv_MainTex;
fixed4 color;
};
void vert (inout appdata_full v, out Input o)
{
#if defined(PIXELSNAP_ON)
v.vertex = UnityPixelSnap (v.vertex);
#endif
UNITY_INITIALIZE_OUTPUT(Input, o);
o.color = v.color * _Color;
}
fixed4 SampleSpriteTexture (float2 uv)
{
fixed4 color = tex2D (_MainTex, uv);
#if ETC1_EXTERNAL_ALPHA
color.a = tex2D (_AlphaTex, uv).r;
#endif //ETC1_EXTERNAL_ALPHA
return color;
}
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color;
o.Albedo = c.rgb * c.a;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Transparent/VertexLit"
}