Reputation: 124
How to add lighting support to an existing sprite shader? Now the shader works like "Sprites/Default", but should work like "Sprites/Diffuse". In other words, the current shader does not respond to light sources, it is necessary to add a response to the lighting in real time.
Shader "Sprites/Stencil Mask"
{
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
Fog { Mode Off }
Blend One OneMinusSrcAlpha
Pass
{
Stencil
{
Ref 1
Comp always
Pass replace
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile DUMMY PIXELSNAP_ON
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
};
fixed4 _Color;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
if (c.a<0.1) discard;
c.rgb *= c.a;
return c;
}
ENDCG
}
}
}
The script does not allow me to send a question due to insufficient description of the problem, but I wrote all the necessary information and there is nothing more to add. For this reason, I am writing this text at the bottom of the question. I apologize.
Upvotes: 1
Views: 1068
Reputation: 1268
If you just want to use global illumination/ambient light, you can use ShadeSH9, which gives you light contribution calculated from spherical harmonics. This will also give you support for light probes.
// Add float3 ambient : TEXCOORD1; to your appdata struct and use it to pass SH data
OUT.ambient = ShadeSH9(mul(unity_ObjectToWorld, float4(v.normal, 0.0 )));
This function uses the world normal of the sprite to calculate the angle of incoming light - this may not be what you want, but then again, there is no way of sampling spherical harmonics without the normal.
You can use it to tint your sprite in the fragment function like this:
c.rgb *= IN.ambient;
If you find that you do want attenuation-based lights, i can refer you to the shader in this answer, which adds support for 4 vertex lights independent of normal:
Unity 3d Sprite Shader (How do I limit Max Brightness to 1 with Multiple Lights Hitting)
Upvotes: 1