Hi, I am trying to create 2D billboard grass that could be shaded. Texture contains pixels that are transparent and not. I want to shadow appear only on not transparent pixels but i get strange outcome. If I look on other objects they are also shaded:
Looking at sky works well:
Shader code:
Shader "PixelEngine/Grass"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_Normal("Normal", Vector) = (0.0, 0.0, 0.0, 0.0)
_Position("Normal", Vector) = (0.0, 0.0, 0.0, 0.0)
_Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
_SemiShadowThreshold("Semi-Shadow Threshold", Range(0.0, 1.0)) = 0.4
_SemiShadowColor("Semi-Shadow Color", Color) = (0.5, 0.5, 0.5, 0.5)
_ShadowThreshold("Shadow Threshold", Range(0.0, 1.0)) = 0.0
_ShadowColor("Shadow Color", Color) = (0.0, 0.0, 0.0, 0.0)
}
SubShader
{
Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" "LightMode"="ForwardBase" }
Blend SrcAlpha OneMinusSrcAlpha
AlphaToMask On
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#pragma multi_compile_instancing
#include "UnityCG.cginc"
#include "AutoLight.cginc"
uniform fixed4 _LightColor0;
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform fixed4 _Color;
uniform fixed4 _ShadowColor;
uniform fixed4 _SemiShadowColor;
uniform fixed _ShadowThreshold;
uniform fixed _SemiShadowThreshold;
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float3, _Normal)
UNITY_DEFINE_INSTANCED_PROP(float3, _Position)
UNITY_INSTANCING_BUFFER_END(Props)
struct vertexInput
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct vertexOutput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 normal : TEXCOORD2;
LIGHTING_COORDS(3, 4)
UNITY_VERTEX_INPUT_INSTANCE_ID // necessary only if you want to access instanced properties in fragment Shader.
};
vertexOutput vert(vertexInput v)
{
vertexOutput o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o); // necessary only if you want to access instanced properties in the fragment Shader.
o.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
+ float4(v.vertex.x, v.vertex.y, 0.0, 0.0));
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.normal = normalize(UnityObjectToWorldNormal(UNITY_ACCESS_INSTANCED_PROP(Props, _Normal)));
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
fixed4 frag (vertexOutput i) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(i); // necessary only if any instanced properties are going to be accessed in the fragment Shader.
// Calculate light
float attenuation = LIGHT_ATTENUATION(i);
fixed3 lightDir;
if(_WorldSpaceLightPos0.w == 0.0)
{
lightDir = normalize(_WorldSpaceLightPos0.xyz);
}
else
{
float3 objToLight = _WorldSpaceLightPos0.xyz - i.worldPos;
lightDir = normalize(objToLight);
}
// Calculate shadow
fixed3 diffuse = saturate(dot(lightDir, i.normal)) * attenuation;
// Color ramp
fixed4 color;
color = diffuse.r <= _SemiShadowThreshold ? _SemiShadowColor : _Color;
color = diffuse.r <= _ShadowThreshold ? _ShadowColor : color;
// Add light color
color = color * _LightColor0;
// Apply grass texture and light color
color = fixed4(color.rgb, tex2D(_MainTex, i.uv).a);
return color;
}
ENDCG
}
}
Fallback "VertexLit"
}
Maybe someone will advise me how to do that better. I am trying to achive simillar results to that shown in this video (but shadow receiving got me):