Я пытаюсь сделать декаль-шейдер для использования с проектором в Unity. Вот что я собрал:
Shader "Custom/color_projector"
{
Properties {
_Color ("Tint Color", Color) = (1,1,1,1)
_MainTex ("Cookie", 2D) = "gray" {}
}
Subshader {
Tags {"Queue"="Transparent"}
Pass {
ZTest Less
ColorMask RGB
Blend One OneMinusSrcAlpha
Offset -1, -1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 uvShadow : TEXCOORD0;
float4 pos : SV_POSITION;
};
float4x4 unity_Projector;
float4x4 unity_ProjectorClip;
v2f vert (float4 vertex : POSITION)
{
v2f o;
o.pos = UnityObjectToClipPos (vertex);
o.uvShadow = mul (unity_Projector, vertex);
return o;
}
sampler2D _MainTex;
fixed4 _Color;
fixed4 frag (v2f i) : SV_Target
{
fixed4 tex = tex2Dproj (_MainTex, UNITY_PROJ_COORD(i.uvShadow));
return _Color * tex.a;
}
ENDCG
}
}
}
Это хорошо работает в большинстве ситуаций:
Однако всякий раз, когда он проецируется на прозрачную поверхность (или несколько поверхностей), для каждой поверхности создается дополнительное время. Здесь я разбил пропасть между травой и дорожным покрытием, используя текстуры травы с прозрачными областями:
Я пробовал многочисленные варианты смешивания и параметры, а также все параметры ZTesting. Это лучшее, что я могу заставить его посмотреть.
Из чтения я понял, что это может быть потому, что прозрачный шейдер не записывает в буфер глубины. Я попытался добавить ZWrite On
и попытался пройти перед основным проходом:
Pass {
ZWrite On
ColorMask 0
}
Но ни один из них не имел никакого эффекта.
Как можно изменить этот шейдер, чтобы он только один раз проецировал текстуру на ближайшие геометрии?
Желаемый результат (фотошоп):