-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathTerrainHeightBlend-Independent-SimpleTile.shader
187 lines (158 loc) · 9.9 KB
/
TerrainHeightBlend-Independent-SimpleTile.shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// The MIT License (MIT) (see LICENSE.txt)
// Copyright © 2021 Jens Neitzel
Shader "Terrain/HeightBlend Independent, Simple Tiling (Better Performance)"
{
Properties
{
_IndepControl ("Splat Map", 2D) = "red" {}
_AlbedoMap0 ("Layer 0 Albedo Map", 2D) = "grey" {}
_HeightMap0 ("Layer 0 Height Map", 2D) = "grey" {}
_NormalMap0 ("Layer 0 Normal Map", 2D) = "bump" {}
_NormalScale0 ("Layer 0 Normal Map Scale", Float) = 1.0
_MetalFactor0 ("Layer 0 Metallic", Range(0.0, 1.0)) = 0.0
_SmoothnessFactor0 ("Layer 0 Smoothness", Range(0.0, 1.0)) = 1.0
_AlbedoMap1 ("Layer 1 Albedo Map", 2D) = "grey" {}
_HeightMap1 ("Layer 1 Height Map", 2D) = "grey" {}
_NormalMap1 ("Layer 1 Normal Map", 2D) = "bump" {}
_NormalScale1 ("Layer 1 Normal Map Scale", Float) = 1.0
_MetalFactor1 ("Layer 1 Metallic", Range(0.0, 1.0)) = 0.0
_SmoothnessFactor1 ("Layer 1 Smoothness", Range(0.0, 1.0)) = 1.0
_AlbedoMap2 ("Layer 2 Albedo Map", 2D) = "grey" {}
_HeightMap2 ("Layer 2 Height Map", 2D) = "grey" {}
_NormalMap2 ("Layer 2 Normal Map", 2D) = "bump" {}
_NormalScale2 ("Layer 2 Normal Map Scale", Float) = 1.0
_MetalFactor2 ("Layer 2 Metallic", Range(0.0, 1.0)) = 0.0
_SmoothnessFactor2 ("Layer 2 Smoothness", Range(0.0, 1.0)) = 1.0
_AlbedoMap3 ("Layer 3 Albedo Map", 2D) = "grey" {}
_HeightMap3 ("Layer 3 Height Map", 2D) = "grey" {}
_NormalMap3 ("Layer 3 Normal Map", 2D) = "bump" {}
_NormalScale3 ("Layer 3 Normal Map Scale", Float) = 1.0
_MetalFactor3 ("Layer 3 Metallic", Range(0.0, 1.0)) = 0.0
_SmoothnessFactor3 ("Layer 3 Smoothness", Range(0.0, 1.0)) = 1.0
_DistantMap ("Distant Map", 2D) = "grey" {}
_DistantMapSmoothnessFactor ("Distant Map Smoothness", Range(0.0, 1.0)) = 1.0
_DistMapBlendDistance("Distant Map Blend Distance", Range(0.0, 128)) = 64
_DistMapInfluenceMin("Distant Map Influence Min", Range(0.0, 1.0)) = 0.2
_DistMapInfluenceMax("Distant Map Influence Max", Range(0.0, 1.0)) = 0.8
_OverlapDepth("Height Blend Overlap Depth", Range(0.001, 1.0)) = 0.07
_Parallax ("Parallax Height", Range (0.005, 0.08)) = 0.02
}
SubShader
{
Tags {
"RenderType" = "Opaque"
}
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard vertex:SplatmapVert addshadow fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
UNITY_DECLARE_TEX2D(_IndepControl);
float4 _Control_TexelSize;
sampler2D _AlbedoMap0, _AlbedoMap1, _AlbedoMap2, _AlbedoMap3;
float4 _AlbedoMap0_ST, _AlbedoMap1_ST, _AlbedoMap2_ST, _AlbedoMap3_ST;
sampler2D _HeightMap0, _HeightMap1, _HeightMap2, _HeightMap3;
UNITY_DECLARE_TEX2D_NOSAMPLER(_DistantMap);
half _DistMapBlendDistance;
fixed _DistMapInfluenceMin;
fixed _DistMapInfluenceMax;
half _OverlapDepth;
half _Parallax;
sampler2D _NormalMap0, _NormalMap1, _NormalMap2, _NormalMap3;
half _NormalScale0, _NormalScale1, _NormalScale2, _NormalScale3;
half _MetalFactor0, _MetalFactor1, _MetalFactor2, _MetalFactor3;
half _SmoothnessFactor0, _SmoothnessFactor1, _SmoothnessFactor2, _SmoothnessFactor3, _DistantMapSmoothnessFactor;
struct Input
{
float4 tc;
half ViewDist;
half3 viewDir;
};
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void SplatmapVert (inout appdata_full v, out Input data)
{
UNITY_INITIALIZE_OUTPUT(Input, data);
data.ViewDist = length(UnityObjectToViewPos(v.vertex).xyz);
data.viewDir = normalize(ObjSpaceViewDir(v.vertex));
v.tangent.w = -1;
data.tc.xy = v.texcoord;
}
half blendByHeight(half texture1height, half texture2height, half control1height, half control2height, half overlapDepth, out half textureHeightOut, out half controlHeightOut)
{
half texture1heightPrefilter = texture1height * sign(control1height);
half texture2heightPrefilter = texture2height * sign(control2height);
half height1 = texture1heightPrefilter + control1height;
half height2 = texture2heightPrefilter + control2height;
half blendFactor = (clamp(((height1 - height2) / overlapDepth), -1, 1) + 1) / 2;
// Substract positive differences of the other control height to not make one texture height benefit too much from the other.
textureHeightOut = max(0, texture1heightPrefilter - max(0, control2height-control1height)) * blendFactor + max(0, texture2heightPrefilter - max(0, control1height-control2height)) * (1 - blendFactor);
// Propagate sum of control heights to not loose height.
controlHeightOut = control1height + control2height;
return blendFactor;
}
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 splat_control = UNITY_SAMPLE_TEX2D (_IndepControl, IN.tc.xy);
fixed4 texDistantMap = UNITY_SAMPLE_TEX2D_SAMPLER (_DistantMap, _IndepControl, IN.tc.xy) * half4(1,1,1,_DistantMapSmoothnessFactor);
fixed2 uvSplat0 = TRANSFORM_TEX(IN.tc.xy, _AlbedoMap0);
fixed2 uvSplat1 = TRANSFORM_TEX(IN.tc.xy, _AlbedoMap1);
fixed2 uvSplat2 = TRANSFORM_TEX(IN.tc.xy, _AlbedoMap2);
fixed2 uvSplat3 = TRANSFORM_TEX(IN.tc.xy, _AlbedoMap3);
fixed texture0Height = tex2D(_HeightMap0, uvSplat0);
fixed texture1Height = tex2D(_HeightMap1, uvSplat1);
fixed texture2Height = tex2D(_HeightMap2, uvSplat2);
fixed texture3Height = tex2D(_HeightMap3, uvSplat3);
// Calculate Blend factors
half textHeight1, textHeight2, textHeight3;
half ctrlHeight1, ctrlHeight2, ctrlHeight3;
half blendFactor01 = blendByHeight(texture0Height, texture1Height, splat_control.r, splat_control.g, _OverlapDepth, textHeight1, ctrlHeight1);
half blendFactor12 = blendByHeight(textHeight1, texture2Height, ctrlHeight1, splat_control.b, _OverlapDepth, textHeight2, ctrlHeight2);
half blendFactor23 = blendByHeight(textHeight2, texture3Height, ctrlHeight2, splat_control.a, _OverlapDepth, textHeight3, ctrlHeight3);
// Calculate Parallax after final heigth is known
fixed2 paraOffset = ParallaxOffset(textHeight3, _Parallax, IN.viewDir);
// Calculate UVs again, now with Parallax Offset
fixed2 uvs0 = uvSplat0 + paraOffset;
fixed2 uvs1 = uvSplat1 + paraOffset;
fixed2 uvs2 = uvSplat2 + paraOffset;
fixed2 uvs3 = uvSplat3 + paraOffset;
// Sample Textures using the modified UVs
fixed4 texture0 = tex2D(_AlbedoMap0, uvs0) * half4(1,1,1,_SmoothnessFactor0);
fixed4 texture1 = tex2D(_AlbedoMap1, uvs1) * half4(1,1,1,_SmoothnessFactor1);
fixed4 texture2 = tex2D(_AlbedoMap2, uvs2) * half4(1,1,1,_SmoothnessFactor2);
fixed4 texture3 = tex2D(_AlbedoMap3, uvs3) * half4(1,1,1,_SmoothnessFactor3);
// Blend Textures based on calculated blend factors
fixed4 mixedDiffuse = texture0 * blendFactor01 + texture1 * (1 - blendFactor01);
mixedDiffuse = mixedDiffuse * blendFactor12 + texture2 * (1 - blendFactor12);
mixedDiffuse = mixedDiffuse * blendFactor23 + texture3 * (1 - blendFactor23);
// Blend with Distant Map
fixed influenceDist = clamp(IN.ViewDist/_DistMapBlendDistance+_DistMapInfluenceMin, 0, _DistMapInfluenceMax);
mixedDiffuse = texDistantMap * influenceDist + mixedDiffuse * (1-influenceDist);
// Sample Normal Maps using the modified UVs
fixed3 texture0normal = UnpackNormalWithScale( tex2D(_NormalMap0, uvs0), _NormalScale0 );
fixed3 texture1normal = UnpackNormalWithScale( tex2D(_NormalMap1, uvs1), _NormalScale1 );
fixed3 texture2normal = UnpackNormalWithScale( tex2D(_NormalMap2, uvs2), _NormalScale2 );
fixed3 texture3normal = UnpackNormalWithScale( tex2D(_NormalMap3, uvs3), _NormalScale3 );
// Blend Normal maps based on calculated blend factors
fixed3 mixedNormal = texture0normal * blendFactor01 + texture1normal * (1 - blendFactor01);
mixedNormal = mixedNormal * blendFactor12 + texture2normal * (1 - blendFactor12);
mixedNormal = mixedNormal * blendFactor23 + texture3normal * (1 - blendFactor23);
mixedNormal.z += 1e-5f; // to avoid nan after normalizing
// Blend Metallness based on calculated blend factors
fixed mixedMetallic = _MetalFactor0 * blendFactor01 + _MetalFactor1 * (1 - blendFactor01);
mixedMetallic = mixedMetallic * blendFactor12 + _MetalFactor2 * (1 - blendFactor12);
mixedMetallic = mixedMetallic * blendFactor23 + _MetalFactor3 * (1 - blendFactor23);
o.Albedo = mixedDiffuse.rgb;
o.Smoothness = mixedDiffuse.a;
o.Normal = mixedNormal;
o.Metallic = mixedMetallic;
}
ENDCG
}
FallBack "Diffuse"
}