ClientServer/Client/Assets/Content/TerrainHeightBlend/TerrainHeightBlend-Independent.shader
TG9six 03a642d635 first push
first push
2025-09-06 17:17:39 +04:00

194 lines
10 KiB
GLSL

// The MIT License (MIT) (see LICENSE.txt)
// Copyright © 2021 Jens Neitzel
Shader "Terrain/HeightBlend Independent"
{
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
#include "textureNoTile.cginc"
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);
NoTileUVs ntuvs0 = textureNoTileCalcUVs(uvSplat0);
NoTileUVs ntuvs1 = textureNoTileCalcUVs(uvSplat1);
NoTileUVs ntuvs2 = textureNoTileCalcUVs(uvSplat2);
NoTileUVs ntuvs3 = textureNoTileCalcUVs(uvSplat3);
fixed texture0Height = textureNoTile(_HeightMap0, ntuvs0);
fixed texture1Height = textureNoTile(_HeightMap1, ntuvs1);
fixed texture2Height = textureNoTile(_HeightMap2, ntuvs2);
fixed texture3Height = textureNoTile(_HeightMap3, ntuvs3);
// 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
ntuvs0 = textureNoTileCalcUVs(uvSplat0+paraOffset);
ntuvs1 = textureNoTileCalcUVs(uvSplat1+paraOffset);
ntuvs2 = textureNoTileCalcUVs(uvSplat2+paraOffset);
ntuvs3 = textureNoTileCalcUVs(uvSplat3+paraOffset);
// Sample Textures using the modified UVs
fixed4 texture0 = textureNoTile(_AlbedoMap0, ntuvs0) * half4(1,1,1,_SmoothnessFactor0);
fixed4 texture1 = textureNoTile(_AlbedoMap1, ntuvs1) * half4(1,1,1,_SmoothnessFactor1);
fixed4 texture2 = textureNoTile(_AlbedoMap2, ntuvs2) * half4(1,1,1,_SmoothnessFactor2);
fixed4 texture3 = textureNoTile(_AlbedoMap3, ntuvs3) * 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 = textureNoTileNormal(_NormalMap0, ntuvs0, _NormalScale0);
fixed3 texture1normal = textureNoTileNormal(_NormalMap1, ntuvs1, _NormalScale1);
fixed3 texture2normal = textureNoTileNormal(_NormalMap2, ntuvs2, _NormalScale2);
fixed3 texture3normal = textureNoTileNormal(_NormalMap3, ntuvs3, _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"
}