Unity Auto Tiling с картой нормалей
Никак не мог найти скрипт или шейдер для автоматической подгонки параметра Tiling, чтоб использовать одну текстуру и один материал для всех объектов с сохранением изначального масштаба текстуры. Сейчас я нашел довольно не плохой шейдер, но в нём нет поддержки карты нормалей, а сам я в шейдерах вообще не понимаю(
Вот сам шейдер:
Shader "Tri-Planar World" {
Properties{
_Side("Side", 2D) = "white" {}
_Top("Top", 2D) = "white" {}
_Bottom("Bottom", 2D) = "white" {}
_SideScale("Side Scale", Float) = 2
_TopScale("Top Scale", Float) = 2
_BottomScale("Bottom Scale", Float) = 2
}
SubShader{
Tags{
"Queue" = "Geometry"
"IgnoreProjector" = "False"
"RenderType" = "Opaque"
}
Cull Back
ZWrite On
CGPROGRAM
#pragma surface surf Lambert
#pragma exclude_renderers flash
sampler2D _Side, _Top, _Bottom;
float _SideScale, _TopScale, _BottomScale;
struct Input {
float3 worldPos;
float3 worldNormal;
};
void surf(Input IN, inout SurfaceOutput o) {
float3 projNormal = saturate(pow(IN.worldNormal * 1.4, 4));
float3 x = tex2D(_Side, frac(IN.worldPos.zy * _SideScale)) * abs(IN.worldNormal.x);
float3 y = 0;
if (IN.worldNormal.y > 0) {
y = tex2D(_Top, frac(IN.worldPos.zx * _TopScale)) * abs(IN.worldNormal.y);
} else {
y = tex2D(_Bottom, frac(IN.worldPos.zx * _BottomScale)) * abs(IN.worldNormal.y);
}
float3 z = tex2D(_Side, frac(IN.worldPos.xy * _SideScale)) * abs(IN.worldNormal.z);
o.Albedo = z;
o.Albedo = lerp(o.Albedo, x, projNormal.x);
o.Albedo = lerp(o.Albedo, y, projNormal.y);
}
ENDCG
}
Fallback "Diffuse"
}
И моя попытка его переделать:
Shader "Tri-Planar World" {
Properties{
_Side("Side", 2D) = "white" {}
_Top("Top", 2D) = "white" {}
_Bottom("Bottom", 2D) = "white" {}
_SideNormal("Side", 2D) = "bump" {}
_TopNormal("Top", 2D) = "bump" {}
_BottomNormal("Bottom", 2D) = "bump" {}
_SideScale("Side Scale", Float) = 2
_TopScale("Top Scale", Float) = 2
_BottomScale("Bottom Scale", Float) = 2
}
SubShader{
Tags{
"Queue" = "Geometry"
"IgnoreProjector" = "False"
"RenderType" = "Opaque"
}
Cull Back
ZWrite On
CGPROGRAM
#pragma surface surf Lambert
#pragma exclude_renderers flash
sampler2D _Side, _Top, _Bottom;
sampler2D _SideNormal, _TopNormal, _BottomNormal;
float _SideScale, _TopScale, _BottomScale;
struct Input {
float3 worldPos;
float3 worldNormal;
float2 uv_BumpMap;
};
void surf(Input IN, inout SurfaceOutput o) {
float3 projNormal = saturate(pow(IN.worldNormal * 1.4, 4));
float3 x = tex2D(_Side, frac(IN.worldPos.zy * _SideScale)) * abs(IN.worldNormal.x);
float3 y = 0;
if (IN.worldNormal.y > 0) {
y = tex2D(_Top, frac(IN.worldPos.zx * _TopScale)) * abs(IN.worldNormal.y);
} else {
y = tex2D(_Bottom, frac(IN.worldPos.zx * _BottomScale)) * abs(IN.worldNormal.y);
}
float3 z = tex2D(_Side, frac(IN.worldPos.xy * _SideScale)) * abs(IN.worldNormal.z);
o.Albedo = z;
o.Albedo = lerp(o.Albedo, x, projNormal.x);
o.Albedo = lerp(o.Albedo, y, projNormal.y);
float3 xNormal = tex2D(_SideNormal, frac(IN.worldPos.zy * _SideScale)) * abs(IN.worldNormal.x);
float3 yNormal = 0;
if (IN.worldNormal.y > 0) {
yNormal = tex2D(_TopNormal, frac(IN.worldPos.zx * _TopScale)) * abs(IN.worldNormal.y);
} else {
yNormal = tex2D(_BottomNormal, frac(IN.worldPos.zx * _BottomScale)) * abs(IN.worldNormal.y);
}
float3 zNormal = tex2D(_Side, frac(IN.worldPos.xy * _SideScale)) * abs(IN.worldNormal.z);
sampler2D tmp;
tmp.z = zNormal;
tmp = lerp(tmp, xNormal, projNormal.x);
tmp = lerp(tmp, yNormal, projNormal.x);
o.Normal = UnpackNormal(tex2D(tmp, IN.uv_BumpMap));
}
ENDCG
}
Fallback "Diffuse"
}
UPD Посидел ночью, попытался изучить хоть что-то. Вот как теперь выглядит мой код:
Shader "Custom/T"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_BumpMap ("Bumpmap", 2D) = "bump" {}
_Scale ("Scale", float) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
float _Scale;
struct Input {
float3 worldPos;
float3 worldNormal;INTERNAL_DATA
};
sampler2D _MainTex;
sampler2D _BumpMap;
void surf (Input IN, inout SurfaceOutputStandard o)
{
float3 projNormal = saturate(pow(IN.worldNormal * 1.4, 4));
fixed4 x = tex2D(_MainTex, frac(IN.worldPos.yz * _Scale));
fixed4 y = tex2D(_MainTex, frac(IN.worldPos.xz * _Scale));
fixed4 z = tex2D(_MainTex, frac(IN.worldPos.xy * _Scale));
fixed3 _tc = z;
_tc = lerp(_tc, x, projNormal.x);
_tc = lerp(_tc, y, projNormal.y);
o.Albedo = _tc;
fixed4 xn = tex2D(_BumpMap, frac(IN.worldPos.yz * _Scale));
fixed4 yn = tex2D(_BumpMap, frac(IN.worldPos.xz * _Scale));
fixed4 zn = tex2D(_BumpMap, frac(IN.worldPos.xy * _Scale));
fixed3 _tcn = zn;
_tcn = lerp(_tcn, xn, projNormal.x);
_tcn = lerp(_tcn, yn, projNormal.y);
o.Normal = _tcn;
}
ENDCG
}
FallBack "Diffuse"
}
Это уже ближе к тому, что мне было нужно, но есть одно но - на строчке o.Normal = _tcn; всё ломается.