Guys,
I just managed to get it running on my own:
The shader checks the normals of the object, if it exceeds the angle that was set via a property, the projector material is not rendered. The projector material still bends with the surface, if the angle limit is not exceeded. So the shader only removes the ugly stretching of the decal at sharp angles!
I wanted to share my modified version of Unity’s “ProjectorAdditive” shader (please let me know, if the shader could be optimized somehow):
Shader "Custom/ProjectorAdditiveAngleCutoff"
{
Properties
{
_Color ("Main Color", Color) = (1,1,1,1)
_ShadowTex ("Cookie", 2D) = "" {}
_FalloffTex ("FallOff", 2D) = "" {}
_AngleLimit ("Angle Limit (rad)", Float) = 0
}
Subshader
{
Tags {"Queue"="Transparent"}
Pass
{
ZWrite Off
AlphaTest Greater 0
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
Offset -1, -1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct v2f {
float4 uvShadow : TEXCOORD0;
float4 uvFalloff : TEXCOORD1;
half projAngle : TEXCOORD2;
UNITY_FOG_COORDS(2)
float4 pos : SV_POSITION;
};
float4x4 _Projector;
float4x4 _ProjectorClip;
half3 projNormal;
inline half angleBetween(half3 vector1, half3 vector2)
{
return acos(dot(vector1, vector2) / (length(vector1) * length(vector2)));
}
v2f vert (float4 vertex : POSITION, float3 normal : NORMAL)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, vertex);
o.uvShadow = mul (_Projector, vertex);
o.uvFalloff = mul (_ProjectorClip, vertex);
projNormal = mul (_Projector, normal);
o.projAngle = abs(angleBetween(half3(0,0,-1), projNormal));
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
fixed4 _Color;
sampler2D _ShadowTex;
sampler2D _FalloffTex;
half _AngleLimit;
fixed4 frag (v2f i) : SV_Target
{
fixed4 texS = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));
texS.rgba *= _Color.rgba;
fixed4 texF = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));
fixed4 res = texS * texF.a * step(_AngleLimit, i.projAngle);
UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(0,0,0,0));
return res;
}
ENDCG
}
}
}
Edit: Made some optimizations (moved angle calculation into the vertex shader and replaced if statement in the fragment shader with a step() function)!