| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183 |
- #ifdef _LAYERS_ONE
- #define _LAYER_COUNT 1
- #else
- #ifdef _LAYERS_TWO
- #define _LAYER_COUNT 2
- #elif defined(_LAYERS_EIGHT)
- #define _LAYER_COUNT 8
- #else
- #define _LAYER_COUNT 4
- #endif
- #endif
- #ifndef TERRAIN_BASEGEN
- struct Input
- {
- float3 worldPos;
- #if defined(INTERRA_TERRAIN)
- float4 tc;
- #else
- float4 mainTC_tWeightY_hOffset;
- #if defined(_OBJECT_PARALLAX) || (defined(INTERRA_MESH_TERRAIN) && defined(_TERRAIN_PARALLAX))
- float3 tangentViewDirObject;
- #endif
- #endif
- float3 worldNormal;
- float3 terrainNormals;
- #ifdef _TERRAIN_PARALLAX
- float3 tangentViewDir;
- #endif
- UNITY_FOG_COORDS(0) // needed because finalcolor oppresses fog code generation.
- INTERNAL_DATA
- };
- #endif
- #ifdef INTERRA_TERRAIN
- #if defined(UNITY_INSTANCING_ENABLED) && !defined(SHADER_API_D3D11_9X)
- sampler2D _TerrainHeightmapTexture;
- sampler2D _TerrainNormalmapTexture;
- float4 _TerrainHeightmapRecipSize; // float4(1.0f/width, 1.0f/height, 1.0f/(width-1), 1.0f/(height-1))
- #endif
-
- UNITY_INSTANCING_BUFFER_START(Terrain)
- UNITY_DEFINE_INSTANCED_PROP(float4, _TerrainPatchInstanceData) // float4(xBase, yBase, skipScale, ~)
- UNITY_INSTANCING_BUFFER_END(Terrain)
- #ifdef _ALPHATEST_ON
- sampler2D _TerrainHolesTexture;
- void ClipHoles(float2 uv)
- {
- float hole = tex2D(_TerrainHolesTexture, uv).r;
- clip(hole == 0.0f ? -1 : 1);
- }
- #endif
-
- #if defined(TERRAIN_BASE_PASS) && (defined(UNITY_PASS_META) || defined(TRIPLANAR))
- // When we render albedo for GI baking, we actually need to take the ST, or for triplanar mapping
- float4 _MainTex_ST;
- #endif
- float3 _TerrainSizeXZPosY;
- #endif
- UNITY_DECLARE_TEX2D (_Control);
- #if defined(_LAYERS_EIGHT)
-
- #endif
- UNITY_DECLARE_TEX2D(_Control2);
- UNITY_DECLARE_TEX2D(_Control1);
- float4 _Control_ST, _Control_TexelSize;
- float4 _TerrainHeightmapTexture_TexelSize;
- float4 _TerrainPosition, _TerrainSize;
- float4 _TerrainHeightmapScale; // float4(hmScale.x, hmScale.y / (float)(kMaxHeight), hmScale.z, 0.0f)
- float _NumLayersCount;
- float4 _HT_distance, _MipMapFade;
- int _MipMapLevel;
- float _HT_distance_scale, _HT_cover;
- fixed _HeightTransition, _Distance_HeightTransition, _TriplanarOneToAllSteep, _TriplanarSharpness;
- fixed _ParallaxAffineStepsTerrain;
- #if defined(TERRAIN_BASEGEN) || defined(TERRAIN_BASE_PASS)
- sampler2D _TerrainColorTintTexture;
- #else
- UNITY_DECLARE_TEX2D_NOSAMPLER(_TerrainColorTintTexture);
- UNITY_DECLARE_TEX2D_NOSAMPLER(_TerrainNormalTintTexture);
- #endif
- float _TerrainColorTintStrenght;
- float4 _TerrainColorTintTexture_ST;
- float _TerrainNormalTintStrenght;
- float4 _TerrainNormalTintTexture_ST;
- float4 _TerrainNormalTintDistance;
- float _HeightmapBlending;
- float _GlobalWetness;
- float _Gamma;
- float _Tracks;
- float _Terrain_Parallax;
- float _WorldMapping;
- fixed _ControlNumber;
- float _MipMapMinLod;
- //-----Track Property -----
- float _TrackAO;
- float _TrackEdgeNormals, _TrackEdgeSharpness;
- float _TrackNormalStrenght;
- float _TrackDetailNormalStrenght;
- float _TrackHeightOffset;
- float4 _TrackDetailTexture_ST;
- float _ParallaxTrackAffineSteps;
- float _ParallaxTrackSteps;
- float _TrackHeightTransition;
- float _TrackMultiplyStrenght;
- UNITY_DECLARE_TEX2D_NOSAMPLER(_TrackDetailTexture);
- UNITY_DECLARE_TEX2D_NOSAMPLER(_TrackDetailNormalTexture);
- //----- Global Property -----
- float _InTerra_TrackArea;
- float3 _InTerra_TrackPosition;
- UNITY_DECLARE_TEX2D_NOSAMPLER(_InTerra_TrackTexture);
- float4 _InTerra_TrackTexture_TexelSize;
- float2 _InTerra_GlobalPuddles;
- float3 _InTerra_GlobalRaindropRipples;
- float _InTerra_GlobalWetness;
- float4 _InTerra_GlobalRaindropsDistance;
- #ifndef INTERRA_TERRAIN
- fixed _GlobalWetnessDisabled;
- fixed _Detail;
- UNITY_DECLARE_TEX2D(_MainTex);
- #if !defined(_LAYERS_ONE)
- UNITY_DECLARE_TEX2D_NOSAMPLER(_BumpMap);
- UNITY_DECLARE_TEX2D_NOSAMPLER(_EmissionMap);
- UNITY_DECLARE_TEX2D_NOSAMPLER(_DetailAlbedoMap);
- UNITY_DECLARE_TEX2D_NOSAMPLER(_DetailNormalMap);
- #else
- sampler2D _BumpMap, _EmissionMap;
- sampler2D _DetailAlbedoMap, _DetailNormalMap;
- #endif
- #if !defined(DIFFUSE)
- UNITY_DECLARE_TEX2D_NOSAMPLER(_MainMask);
- #endif
- half4 _Color;
- half _BumpScale, _Ao, _Glossiness, _Metallic, _MipMapCount;
- float4 _MainTex_ST;
- float _EmissionEnabled, _EmissionIntensity;
- float4 _EmissionMap_ST;
- half4 _EmissionColor;
- fixed _HasMask, _PassNumber;
- half4 _MaskMapRemapScale, _MaskMapRemapOffset;
- float4 _DetailAlbedoMap_ST;
- half _DetailStrenght, _DetailNormalMapScale, _DetailNormalStrenght;
- #ifdef _OBJECT_PARALLAX
- float _Object_Parallax, _ParallaxHeight, _ParallaxSteps, _ParallaxAffineSteps;
- #endif
-
- half4 _Intersection, _Intersection2, _NormIntersect;
-
- half _Sharpness;
- half _Steepness, _SteepDistortion, _SteepIntersection;
- half4 _TerrainSmoothness, _TerrainMetallic;
- fixed _DisableOffsetY, _DisableDistanceBlending;
- sampler2D _TerrainHeightmapTexture;
- sampler2D _TerrainNormalmapTexture;
- #if defined(_NORMALMAPS) || defined(_TERRAIN_NORMAL_IN_MASK)
- float4 _TerrainNormalScale;
- #endif
- #endif
- #ifdef INTERRA_MESH_TERRAIN
- fixed _NormalsFromHeightmap;
- fixed _CheckHeight;
- #endif
- fixed _TwoLayersOnly;
- #if defined(INTERRA_OBJECT) //|| defined(TERRAIN_CUSTOM_MESH)
- #define SplatST(n) float4 _SplatUV##n
- #else
- #define SplatST(n) float4 _Splat##n##_ST, _SplatUV##n
- #endif
- float4 _TerrainNormalScale1;
- half4 _TerrainSmoothness1, _TerrainMetallic1;
-
- #define DECLARE_TERRAIN_LAYER_PROPS(n) \
- float _Metallic##n; \
- float _Smoothness##n; \
- float _NormalScale##n; \
- float4 _DiffuseRemapOffset##n; \
- float4 _DiffuseRemapScale##n; \
- float4 _MaskMapRemapOffset##n; \
- float4 _MaskMapRemapScale##n; \
- float _LayerHasMask##n; \
- float4 _Normal##n##_TexelSize; \
- float4 _Splat##n##_TexelSize; \
- float4 _Mask##n##_TexelSize; \
- float4 _Specular##n; \
- SplatST(n); \
- UNITY_DECLARE_TEX2D_NOSAMPLER(_Splat##n); \
- UNITY_DECLARE_TEX2D_NOSAMPLER(_Normal##n); \
- UNITY_DECLARE_TEX2D_NOSAMPLER(_Mask##n); \
-
- DECLARE_TERRAIN_LAYER_PROPS(0)
- #ifndef _LAYERS_ONE
- DECLARE_TERRAIN_LAYER_PROPS(1)
- #ifndef _LAYERS_TWO
- DECLARE_TERRAIN_LAYER_PROPS(2)
- DECLARE_TERRAIN_LAYER_PROPS(3)
- #ifdef _LAYERS_EIGHT
- DECLARE_TERRAIN_LAYER_PROPS(4)
- DECLARE_TERRAIN_LAYER_PROPS(5)
- DECLARE_TERRAIN_LAYER_PROPS(6)
- DECLARE_TERRAIN_LAYER_PROPS(7)
- #endif
- #endif
- #endif
- SamplerState sampler_Splat0;
- SamplerState sampler_Mask0;
- //=======================================================================================
- //=================================== FUNCTIONS =====================================
- //=======================================================================================
- half3 BlendNormal(half3 n1, half3 n2)
- {
- return normalize(half3(n1.xy + n2.xy, n1.z * n2.z));
- }
- float2 ObjectFrontUV(float posOffset, half4 splatUV, float offsetZ)
- {
- return float2((posOffset + splatUV.z) / splatUV.x, (offsetZ + splatUV.w) / splatUV.y);
- }
- float2 ObjectSideUV(float posOffset, half4 splatUV, float offsetX)
- {
- return float2((offsetX + splatUV.z) / splatUV.x, (posOffset + splatUV.w) / splatUV.y);
- }
- half3 WorldTangent(float3 wTangent, float3 wBTangent, half3 mixedNormal)
- {
- mixedNormal.xy = mul(float2x2(wTangent.xz, wBTangent.xz), mixedNormal.xy);
- return half3(mixedNormal);
- }
- half3 WorldTangentFrontSide(float3 wTangent, float3 wBTangent, half3 mixedNormal, half3 normal_front, half3 normal_side, fixed3 flipUV, half3 weights)
- {
- normal_front.y *= -flipUV.z;
- normal_front.xy = mul(float2x2(wTangent.xy, wBTangent.xy), normal_front.xy);
- normal_side.x *= -flipUV.x;
- normal_side.xy = mul(float2x2(wTangent.yz, wBTangent.yz), normal_side.xy);
- return half3(mixedNormal * weights.y + normal_front * weights.z + normal_side * weights.x);
- }
- half2 HeightBlendTwoTextures(float2 splat, float2 heights, fixed sharpness)
- {
- splat *= (1 / (1 * pow(2, heights * (-(sharpness)))) + 1) * 0.5;
- splat /= (splat.r + splat.g);
- return splat;
- }
- #if defined(TRIPLANAR) && defined(INTERRA_TERRAIN)
- float2 TerrainFrontUV(float3 wPos, half4 splatUV, float2 tc, float3 flip)
- {
- return float2(tc.x * -flip.z, (wPos.y - _TerrainSizeXZPosY.z) * (splatUV.y / _TerrainSizeXZPosY.y) + splatUV.w);
- }
- float2 TerrainSideUV(float3 wPos, half4 splatUV, float2 tc, float3 flip)
- {
- return float2(tc.y * flip.x, (wPos.y - _TerrainSizeXZPosY.z) * (splatUV.x / _TerrainSizeXZPosY.x) + splatUV.z);
- }
- #endif
- void TriplanarOneToAllSteep(in out half4 blendMask[2], float weightY, in out half splatWeight)
- {
- if (_TriplanarOneToAllSteep == 1)
- {
- #if !defined(TERRAIN_SPLAT_ADDPASS)
- blendMask[0] = float4(saturate(blendMask[0].r + weightY), saturate((blendMask[0].gba) - weightY));
- blendMask[1] = float4(saturate((blendMask[1].rgba) - weightY));
- splatWeight = saturate(splatWeight + weightY);
- blendMask[0] = float4(saturate(blendMask[0].r + weightY), saturate(blendMask[0].gba - weightY));
- splatWeight = saturate(splatWeight + weightY);
- #else
- blendMask[0] = float4(saturate(blendMask[0].rgba - weightY));
- splatWeight = saturate(splatWeight - weightY);
- #endif
- }
- }
- half3 TriplanarNormal(half3 normal, half3 tangent, half3 bTangent, half3 normal_front, half3 normal_side, float3 weights, fixed3 flipUV)
- {
- #ifndef INTERRA_TERRAIN
- normal_front.y *= -flipUV.z;
- normal_front.xy = mul(float2x2(tangent.xy, bTangent.xy), normal_front.xy);
- normal_side.x *= -flipUV.x;
- normal_side.xy = mul(float2x2(tangent.yz, bTangent.yz), normal_side.xy);
- #else
- normal_side.xy = normal_side.yx; //this is needed because the uv was rotated
- normal_front.xy *= -flipUV.z;
- normal_side.x *= -flipUV.x;
- normal_side.y *= flipUV.x;
- #endif
- return half3 (normal + normal_front + normal_side);
- }
- void TriplanarBase(in out half4 baseMap, half4 front, half4 side, float3 weights, float2 splat, fixed firstToAllSteep)
- {
- baseMap = firstToAllSteep == 1 ? (baseMap * weights.y + front * weights.z + side * weights.x) : (baseMap * saturate(weights.y + (1 - splat.g))) + (((front * weights.z) + (side * weights.x)) * (splat.r));
- }
- #define MipMapLod(i, lod) float(_MipMapLevel + (lod * log2(max(_Mask##i##_TexelSize.z, _Mask##i##_TexelSize.w)) + 1))
- #if defined(INTERRA_OBJECT) || defined(INTERRA_MESH_TERRAIN)
- #define DiffuseRemap(i) float4(_DiffuseRemapScale##i.xyzw)
- #else
- #define DiffuseRemap(i) float4(_DiffuseRemapScale##i.xyzw + _DiffuseRemapOffset##i.xyzw)
- #endif
- #if defined (PARALLAX)
- float3 TangentViewDir(float3 normal, float4 tangent, float3 viewDir)
- {
- float3x3 objectToTangent = float3x3((tangent.xyz), (cross(normal, tangent.xyz)) * tangent.w, (normal));
- return mul(objectToTangent, viewDir);
- }
- float GetParallaxHeight(Texture2D mask, float2 uv, float2 offset, float lod, int invert)
- {
- return abs(mask.SampleLevel(sampler_Splat0, uv + offset, lod).b - invert);
- }
- //this function is based on Parallax Occlusion Mapping from Unity Shader Graph URP/HDRP
- float2 ParallaxOffset(Texture2D mask, int numSteps, float amplitude, float2 uv, float3 tangentViewDir, int affineSteps, int lod, int invert)
- {
- float2 offset = 0;
- if (numSteps > 0)
- {
- float3 viewDir = float3(tangentViewDir.xy * amplitude * -0.01f, tangentViewDir.z);
- float stepSize = (1.0 / numSteps);
- float2 texOffsetPerStep = (stepSize * viewDir);
- // Do a first step before the loop to init all value correctly
- float2 texOffsetCurrent = float2(0.0f, 0.0f);
- float prevHeight = GetParallaxHeight(mask, uv, texOffsetCurrent, lod, invert);
- texOffsetCurrent += texOffsetPerStep;
- float currHeight = GetParallaxHeight(mask, uv, texOffsetCurrent, lod, invert);
- float rayHeight = 1.0f - stepSize; // Start at top less one sample
- for (int stepIndex = 0; stepIndex < numSteps; ++stepIndex)
- {
- // Have we found a height below our ray height ? then we have an intersection
- if (currHeight > rayHeight)
- break; // end the loop
- prevHeight = currHeight;
- rayHeight -= stepSize;
- texOffsetCurrent += texOffsetPerStep;
- currHeight = GetParallaxHeight(mask, uv, texOffsetCurrent, lod, invert);
- }
- if (affineSteps <= 1)
- {
- float delta0 = currHeight - rayHeight;
- float delta1 = (rayHeight + stepSize) - prevHeight;
- float ratio = delta0 / (delta0 + delta1);
- offset = texOffsetCurrent - ratio * texOffsetPerStep;
- }
- else
- {
- float pt0 = rayHeight + stepSize;
- float pt1 = rayHeight;
- float delta0 = pt0 - prevHeight;
- float delta1 = pt1 - currHeight;
- float delta;
- // Secant method to affine the search
- // Ref: Faster Relief Mapping Using the Secant Method - Eric Risser
- for (int i = 0; i < affineSteps; ++i)
- {
- // intersectionHeight is the height [0..1] for the intersection between view ray and heightfield line
- float intersectionHeight = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
- // Retrieve offset require to find this intersectionHeight
- offset = (1 - intersectionHeight) * texOffsetPerStep * numSteps;
- currHeight = GetParallaxHeight(mask, uv, offset, lod, invert);
- delta = intersectionHeight - currHeight;
- if (abs(delta) <= 0.01f)
- break;
- // intersectionHeight < currHeight => new lower bounds
- if (delta < 0.0f)
- {
- delta1 = delta;
- pt1 = intersectionHeight;
- }
- else
- {
- delta0 = delta;
- pt0 = intersectionHeight;
- }
- }
- }
- }
- return offset;
- }
- void ParallaxUV(inout float2 uv[_LAYER_COUNT], float3 tangentViewDir, half4 blendMask[2], int lod, float weight)
- {
- #define uvParallax(i, blendMask) \
- UNITY_BRANCH if (blendMask * weight > 0.0001f) \
- { \
- uv[i] += ParallaxOffset(_Mask##i, _DiffuseRemapOffset##i.w, DiffuseRemap(i).w, uv[i], tangentViewDir, _ParallaxAffineStepsTerrain, _MipMapLevel + (lod * (log2(max(_Mask##i##_TexelSize.z, _Mask##i##_TexelSize.w)) + 1)), 0);\
- }\
-
-
- UNITY_BRANCH if (_Terrain_Parallax == 1)
- {
- uvParallax(0, blendMask[0].r);
- #ifndef _LAYERS_ONE
- uvParallax(1, blendMask[0].g);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- uvParallax(2, blendMask[0].b);
- uvParallax(3, blendMask[0].a);
- #ifdef _LAYERS_EIGHT
- uvParallax(4, blendMask[1].r);
- uvParallax(5, blendMask[1].g);
- uvParallax(6, blendMask[1].b);
- uvParallax(7, blendMask[1].a);
- #endif
- }
- #endif
- #endif
- }
- }
- #endif
- float4 TrackSplatValues(half4 blendMask[2], float4 trackSplats[_LAYER_COUNT])
- {
- #ifdef _LAYERS_ONE
- return trackSplats[0];
- #else
- float4 color = (blendMask[0].r * trackSplats[0])
- + (blendMask[0].g * trackSplats[1]);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- color += (blendMask[0].b * trackSplats[2])
- + (blendMask[0].a * trackSplats[3]);
- #ifdef _LAYERS_EIGHT
- color += (blendMask[1].r * trackSplats[4])
- + (blendMask[1].g * trackSplats[5])
- + (blendMask[1].b * trackSplats[6])
- + (blendMask[1].a * trackSplats[7]);
- #endif
- }
- #endif
- return color;
- #endif
- }
- #ifndef INTERRA_TERRAIN
- #define SpecularValueR(i) _Specular##i.r;
- #define SpecularValueG(i) _Specular##i.g;
- #define SpecularValueB(i) _Specular##i.b;
- #else
- #define SpecularValueR(i) _Gamma ? _Specular##i.r : pow(_Specular##i.r,1/2.2f);
- #define SpecularValueG(i) _Gamma ? _Specular##i.g : pow(_Specular##i.g,1/2.2f);
- #define SpecularValueB(i) _Gamma ? _Specular##i.b : pow(_Specular##i.b,1/2.2f);
- #endif
- void UnpackTrackSplatValues(out float4 trackSplats[_LAYER_COUNT])
- {
- float value;
- int precision = 1024;
-
- #define trackSplat(i) value = SpecularValueR(i); \
- trackSplats[i].z = value % precision; \
- value = floor(value / precision); \
- trackSplats[i].x = value; \
- trackSplats[i] /= (precision - 1); \
- \
- trackSplats[i].y = (_DiffuseRemapOffset##i.w * 10.0f) % 1 ; \
- trackSplats[i].w = floor((_DiffuseRemapOffset##i.w % 1 ) * 10.0f); \
- trackSplat(0);
- #ifndef _LAYERS_ONE
- trackSplat(1);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- trackSplat(2);
- trackSplat(3);
- #ifdef _LAYERS_EIGHT
- trackSplat(4);
- trackSplat(5);
- trackSplat(6);
- trackSplat(7);
- #endif
- }
- #endif
- #endif
- }
- void UnpackTrackSplatColor(out float4 trackSplatsColor[_LAYER_COUNT])
- {
- float color;
- float value;
- int precision = 1024;
- #define trackSplatColor(i) color = SpecularValueG(i) \
- \
- trackSplatsColor[i].y = color % precision; \
- color = floor(color / precision); \
- trackSplatsColor[i].x = color; \
- value = SpecularValueB(i); \
- trackSplatsColor[i].w = value % precision; \
- value = floor(value / precision); \
- trackSplatsColor[i].z = value % precision; \
- trackSplatsColor[i] /= (precision - 1); \
-
- trackSplatColor(0);
- #ifndef _LAYERS_ONE
- trackSplatColor(1);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- trackSplatColor(2);
- trackSplatColor(3);
- #ifdef _LAYERS_EIGHT
- trackSplatColor(4);
- trackSplatColor(5);
- trackSplatColor(6);
- trackSplatColor(7);
- #endif
- }
- #endif
- #endif
- }
- half3 UnpackNormalGAWithScale(half4 packednormal, float scale, float hasMask)
- {
- fixed3 normal;
- UNITY_BRANCH if (hasMask > 0)
- {
- normal.xy = (packednormal.wy * 2 - 1) * scale;
- normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));
- }
- else
- {
- normal = float3(0, 0, 1);
- }
- return normal;
- }
-
-
- float3 BlendNormals(float3 n1, float3 n2)
- {
- #ifdef INTERRA_OBJECT
- float3 t = n1.xyz + float3(0.0, 0.0, 1.0);
- float3 u = n2.xyz * float3(-1.0, -1.0, 1.0);
- float3 r = (t / t.z) * dot(t, u) - u;
- return r;
- #else
- return (float3(n1.xy + n2.xy, n1.z));
- #endif
- }
- float MipLevel(float2 texture_coord)
- {
- float2 dx = ddx(texture_coord);
- float2 dy = ddy(texture_coord);
- float delta_max_sqr = max(dot(dx, dx), dot(dy, dy));
- return max(0, 0.5 * log2(delta_max_sqr)) - 0.75;
- }
- #if defined(_NORMALMAPS) && !defined(_TERRAIN_NORMAL_IN_MASK)
- #define SampleNormals(i) (UnpackNormalWithScale(UNITY_SAMPLE_TEX2D_SAMPLER(_Normal##i, _Splat0, uv[i]), _NormalScale##i).xyz)
- #elif defined(_TERRAIN_NORMAL_IN_MASK)
- #define SampleNormals(i) float3(UnpackNormalGAWithScale(mask[i], _NormalScale##i, _LayerHasMask##i).xyz)
- #else
- #define SampleNormals(i) float3(0, 0, 1)
- #endif
- float3 SmoothMaskOrAlbedo(half mask, half albedo, float hasMask, float smoothness)
- {
- UNITY_BRANCH if (hasMask > 0)
- {
- albedo = mask;
- }
- else
- {
- albedo *= smoothness;
- }
- return albedo;
- }
- #ifdef _TERRAIN_MASK_MAPS
- #define Smoothness(i) SmoothMaskOrAlbedo(mask[i].a, albedo[i].a, _LayerHasMask##i, _Smoothness##i)
- #else
- #define Smoothness(i) albedo[i].a *= _Smoothness##i
- #endif
- #if defined(INTERRA_OBJECT) || defined(INTERRA_MESH_TERRAIN)
- #ifdef INTERRA_OBJECT
- #define UV(i) (posOffset.xz + _SplatUV##i.zw + _SteepDistortion) / _SplatUV##i.xy;
- #else
- #define UV(i) (posOffset.xz + _SplatUV##i.zw) / _SplatUV##i.xy;
- #endif
- #ifdef PARALLAX
- #define fUV(i) ObjectFrontUV(posOffset.x, _SplatUV##i, offsetZ + (_DiffuseRemapScale##i.w * 0.004 * _SplatUV##i.x) * -flip.z);
- #define sUV(i) ObjectSideUV(posOffset.z, _SplatUV##i, offsetX + (_DiffuseRemapScale##i.w * 0.004 * _SplatUV##i.y) * -flip.x);
- #else
- #if defined(TESSELLATION_ON)
- #define fUV(i) ObjectFrontUV(posOffset.x, _SplatUV##i, offsetZ + (-_DiffuseRemapOffset##i.y * 0.005 - _TerrainTessOffset) * -flip.z);
- #define sUV(i) ObjectSideUV(posOffset.z, _SplatUV##i, offsetX + (-_DiffuseRemapOffset##i.y * 0.005 - _TerrainTessOffset) * -flip.x);
- #else
- #define fUV(i) ObjectFrontUV(posOffset.x, _SplatUV##i, offsetZ);
- #define sUV(i) ObjectSideUV(posOffset.z, _SplatUV##i, offsetX);
- #endif
- #endif
- #else
- #define UV(i) splatBaseUV * _Splat##i##_ST.xy + _Splat##i##_ST.zw;
- #define fUV(i) TerrainFrontUV(worldPos, _Splat##i##_ST, uvSplat[i], flip);
- #define sUV(i) TerrainSideUV(worldPos, _Splat##i##_ST, uvSplat[i], flip);
- #endif
- #if defined(INTERRA_OBJECT) || defined(INTERRA_MESH_TERRAIN)
- #ifndef TRIPLANAR
- void UvSplat(out float2 uvSplat[_LAYER_COUNT], float3 posOffset)
- #else
- void UvSplat(out float2 uvSplat[_LAYER_COUNT], out float2 uvFront[_LAYER_COUNT], out float2 uvSide[_LAYER_COUNT], float3 posOffset, float offsetZ, float offsetX, float3 flip)
- #endif
- #else
- #if !defined(TRIPLANAR) || defined(TERRAIN_BASEGEN)
- void UvSplat(out float2 uvSplat[_LAYER_COUNT], float2 splatBaseUV)
- #else
- void UvSplat(out float2 uvSplat[_LAYER_COUNT], out float2 uvFront[_LAYER_COUNT], out float2 uvSide[_LAYER_COUNT], float3 worldPos, float2 splatBaseUV, float3 flip)
- #endif
- #endif
- {
- #if !defined(TRIPLANAR) || defined(TERRAIN_BASEGEN)
- #define SplatUV(i) \
- uvSplat[i] = UV(i);
- #else
- #define SplatUV(i) \
- uvSplat[i] = UV(i); \
- uvFront[i] = fUV(i); \
- uvSide[i] = sUV(i); \
- #endif
- SplatUV(0);
- #ifndef _LAYERS_ONE
- SplatUV(1);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- SplatUV(2);
- SplatUV(3);
- #ifdef _LAYERS_EIGHT
- SplatUV(4);
- SplatUV(5);
- SplatUV(6);
- SplatUV(7);
- #endif
- }
- #endif
- #endif
- }
- void DistantUV(out float2 distantUV[_LAYER_COUNT], float2 uvSplat[_LAYER_COUNT])
- {
- #define uvDistant(i) \
- distantUV[i] = uvSplat[i] * (_DiffuseRemapOffset##i.r + 1) * _HT_distance_scale; \
-
- uvDistant(0);
- #ifndef _LAYERS_ONE
- uvDistant(1);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- uvDistant(2);
- uvDistant(3);
- #ifdef _LAYERS_EIGHT
- uvDistant(4);
- uvDistant(5);
- uvDistant(6);
- uvDistant(7);
- #endif
- }
- #endif
- #endif
- }
- float4 RemapMasks(half4 mask, float4 remapScale, float4 remapOffset)
- {
- #ifdef _TERRAIN_NORMAL_IN_MASK
- mask.rb * remapScale.gb + remapOffset.gb;
- return mask;
- #else
- return mask * remapScale + remapOffset;
- #endif
- }
- #define PI 3.14159265359
- #define TAU 6.283185307
- float random(in float2 st)
- {
- return frac(sin(dot(st.xy, float2(12.9898, 78.233))) * 43758.5453123);
- }
- float2 rotate_2d(float2 p_input, float p_theta)
- {
- float2x2 l_rot_matrix = float2x2(cos(p_theta), -sin(p_theta),
- sin(p_theta), cos(p_theta));
- return mul(l_rot_matrix, p_input);
- }
- float3 RainRipples(float2 uv, float scale, float rotation)
- {
- float3 normal = float3(0, 0, 1);
- uv.xy = rotate_2d(uv.xy, rotation);
- float2 sUV = (uv.xy * scale + scale * 0.1f);
- sUV.x += step(1.0f, (sUV.y % 2.0)) * 0.5f;
- float2 center = float2(0.5f, 0.5f);
- float size = 0.25f;
- float2 tile = floor(sUV);
- float2 fract = frac(sUV);
- float2 offset = (center - fract.xy) * size;
- float2 cUV = (fract - 0.5) / size + offset;
- float2 polarUV = float2(length(cUV), atan2(cUV.y, cUV.x));
- float time = _Time.x * scale * 3.0f;
- float radius = frac(time * 0.9f + (random(floor(sUV) + 5000.0).x)) * 1.25f;
- if (radius < 0.8f)
- {
- float thickness = min((size * 0.5f + 0.25f) * 0.4f, radius);
- float start = radius + thickness;
- float end = max(0., radius - thickness);
- if (radius > 0.15)
- {
- thickness *= (0.9 - (radius * 0.9f));
- }
- float radius2 = radius - thickness * 1.25f;
- float cAngle = smoothstep(start, end, polarUV.x) * PI;
- float start2 = radius2 + thickness;
- float end2 = max(0., radius2 - thickness);
- float cAngle2 = smoothstep(start2, end2, polarUV.x) * PI;
- float rippleMask = smoothstep(thickness, -0.1f, abs(polarUV.x - radius));
- float rippleMask2 = smoothstep(thickness, -0.1f, abs(polarUV.x - radius2));
- float decayMask = min(1., max(0., 1. - polarUV.x));
- cAngle = lerp(cAngle, PI * 0.5f, (1.0f - rippleMask * decayMask));
- cAngle2 = lerp(cAngle2, PI * 0.5f, (1.0f - rippleMask2 * decayMask));
- float c = lerp(cos(cAngle), cos(cAngle2), 0.5f);
- normal = float3(c * sin(polarUV.y), c * cos(polarUV.y), sin(cAngle));
- float opacity = _InTerra_GlobalRaindropRipples.y;
- normal.xy = rotate_2d(normal.xy, rotation) * (opacity - (radius * opacity));
- }
- return normal;
- }
- #if defined(TERRAIN_MASK) || defined(DIFFUSE)
- #ifdef DIFFUSE
- #define Mask(i, blendMask) UNITY_SAMPLE_TEX2D_SAMPLER(_Splat##i, _Splat0, uv[i])
- #else
- #ifdef TERRAIN_MASK
- #define Mask(i, blendMask) UNITY_SAMPLE_TEX2D_SAMPLER(_Mask##i, _Splat0, uv[i])
- #else
- #define Mask(i, blendMask) float4(_Metallic##i, 1, 0.5, 0);
- #endif
- #endif
-
- #if defined(DIFFUSE)
- #define RemapMask(i) mask[i];
- #else
- #ifdef _TERRAIN_NORMAL_IN_MASK
- #define RemapMask(i) mask[i] * float4(_MaskMapRemapScale##i.g, 1, _MaskMapRemapScale##i.b, 1) \
- + float4(_MaskMapRemapOffset##i.g, 0, _MaskMapRemapOffset##i.b, 0);
- #else
- #define RemapMask(i) mask[i] * _MaskMapRemapScale##i + _MaskMapRemapOffset##i;
- #endif
- #endif
- #else
- #define Mask(i, blendMask) float4(_Metallic##i, 1.0f, 0.5f, 0.0f);
- #define RemapMask(i) mask[i];
- #endif
- void SampleMask(out half4 mask[_LAYER_COUNT], float2 uv[_LAYER_COUNT], half4 blendMask[2], float weight)
- {
- #define SampleMasks(i, blendMask) \
- UNITY_BRANCH if (blendMask * weight > 0.0f ) \
- { \
- mask[i] = Mask(i, blendMask); \
- mask[i] = RemapMask(i); \
- } \
- else \
- { \
- mask[i] = float4(_Metallic##i, 1.0f, 0.5f, 0.0f); \
- } \
- SampleMasks(0, blendMask[0].r);
- #ifndef _LAYERS_ONE
- SampleMasks(1, blendMask[0].g);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- SampleMasks(2, blendMask[0].b);
- SampleMasks(3, blendMask[0].a);
- #ifdef _LAYERS_EIGHT
- SampleMasks(4, blendMask[1].r);
- SampleMasks(5, blendMask[1].g);
- SampleMasks(6, blendMask[1].b);
- SampleMasks(7, blendMask[1].a);
- #endif
- }
- #endif
- #endif
- #undef SampleMasks
- }
- void MaskWeight(inout half4 mask[_LAYER_COUNT], half4 mask_front[_LAYER_COUNT], half4 mask_side[_LAYER_COUNT], half4 blendMask[2], inout float3 triplanarWeights, float heightBlendingSharpness)
- {
- for (int i = 0; i < _LAYER_COUNT; ++i)
- {
- mask[i] = (mask[i] * triplanarWeights.y) + (mask_front[i] * triplanarWeights.z) + (mask_side[i] * triplanarWeights.x);
- }
- }
- half4 MaskSplatWeight(half4 mask[_LAYER_COUNT], half4 blendMask[2], out half4 mixedMask)
- {
- float splatWeight[_LAYER_COUNT];
- mixedMask = 0;
- #ifdef _TERRAIN_NORMAL_IN_MASK
- #define MixdMask(i, blendMask) float4(_Metallic##i, mask[i].r, mask[i].b, 0.0f) * blendMask
- #elif defined(_TERRAIN_MASK_HEIGHTMAP_ONLY)
- #define MixdMask(i, blendMask) float4(_Metallic##i, 1.0f, mask[i].b, 0.0f) * blendMask
- #else
- #define MixdMask(i, blendMask) mask[i] * blendMask
- #endif
- #define MixdMasks(i, blendMask) \
- UNITY_BRANCH if (blendMask > 0) \
- { \
- mixedMask += MixdMask(i, blendMask); \
- }
- MixdMasks(0, blendMask[0].r);
- #ifndef _LAYERS_ONE
- MixdMasks(1, blendMask[0].g);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- MixdMasks(2, blendMask[0].b);
- MixdMasks(3, blendMask[0].a);
- #ifdef _LAYERS_EIGHT
- MixdMasks(4, blendMask[1].r);
- MixdMasks(5, blendMask[1].g);
- MixdMasks(6, blendMask[1].b);
- MixdMasks(7, blendMask[1].a);
- #endif
- }
- #endif
- #endif
- return mixedMask;
- }
- #ifndef DIFFUSE
- #define SampleSplt(i) UNITY_SAMPLE_TEX2D_SAMPLER(_Splat##i, _Splat0, uv[i])
- #else
- #define SampleSplt(i) mask[i]
- #endif
- void SampleSplat(float2 uv[_LAYER_COUNT], half4 blendMask[2], float weight, inout half4 mask[_LAYER_COUNT], out float4 mixAlbedo, out float3 mixNormal, out half4 albedo[_LAYER_COUNT])
- {
- float3 normal[_LAYER_COUNT];
- mixAlbedo = float4(0, 0, 0, 0);
- mixNormal = float3(0, 0, 0);
- #define Samples(i, blendMask) blendMask *= weight; \
- UNITY_BRANCH if (blendMask > 1e-5f) \
- { \
- albedo[i] = SampleSplt(i); \
- albedo[i].rgb *= DiffuseRemap(i).xyz; \
- albedo[i].a = Smoothness(i).x; \
- normal[i] = SampleNormals(i).xyz; \
- mixAlbedo += albedo[i].xyzw * blendMask; \
- mixNormal += normal[i].xyz * blendMask; \
- } \
- else \
- { \
- albedo[i] = float4(0, 0, 0, 0); \
- normal[i] = float3(0, 0, 1); \
- } \
- mixNormal.z += +1e-5f;
- Samples(0, blendMask[0].r);
- #ifndef _LAYERS_ONE
- Samples(1, blendMask[0].g);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- Samples(2, blendMask[0].b);
- Samples(3, blendMask[0].a);
- #ifdef _LAYERS_EIGHT
- Samples(4, blendMask[1].r);
- Samples(5, blendMask[1].g);
- Samples(6, blendMask[1].b);
- Samples(7, blendMask[1].a);
- #endif
- }
- #endif
- #endif
- #undef Samples
- }
-
- #ifdef TERRAIN_MASK
- float AmbientOcclusion(half4 mask[_LAYER_COUNT], half4 blendMask[2])
- {
- float occlusion[_LAYER_COUNT];
- #ifdef _TERRAIN_NORMAL_IN_MASK
- UNITY_UNROLL for (int i = 0; i < _LAYER_COUNT; ++i)
- {
- occlusion[i] = mask[i].r;
- }
- #else
- UNITY_UNROLL for (int i = 0; i < _LAYER_COUNT; ++i)
- {
- occlusion[i] = mask[i].g;
- }
- #endif
- float ao = 0;
- ao = occlusion[0] * blendMask[0].r;
- #ifndef _LAYERS_ONE
- ao += occlusion[1] * blendMask[0].g;
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- ao += occlusion[2] * blendMask[0].b
- + occlusion[3] * blendMask[0].a;
- #ifdef _LAYERS_EIGHT
- ao += occlusion[4] * blendMask[1].r
- + occlusion[5] * blendMask[1].g
- + occlusion[6] * blendMask[1].b
- + occlusion[7] * blendMask[1].a;
- #endif
- }
- #endif
- #endif
- return ao;
- }
- #endif
- #ifndef _TERRAIN_MASK_MAPS
- #define Metallic(i, blendMask) _Metallic##i * blendMask;
- #else
- #define Metallic(i, blendMask) mask[i].r * blendMask;
- #endif
- float MetallicMask(half4 mask[_LAYER_COUNT], half4 blendMask[2])
- {
- float metallic = 0;
- #define Metallics(i, blendMask) \
- UNITY_BRANCH if (blendMask > 0.0001f) \
- { \
- metallic += Metallic(i, blendMask); \
- }
- Metallics(0, blendMask[0].r);
- #ifndef _LAYERS_ONE
- Metallics(1, blendMask[0].g);
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- Metallics(2, blendMask[0].b);
- Metallics(3, blendMask[0].a);
- #ifdef _LAYERS_EIGHT
- Metallics(4, blendMask[1].r);
- Metallics(5, blendMask[1].g);
- Metallics(6, blendMask[1].b);
- Metallics(7, blendMask[1].a);
- #endif
- }
- #endif
- #endif
- return metallic;
- }
- float HeightSum(half4 mask[_LAYER_COUNT], half4 blendMask[2])
- {
- float height[_LAYER_COUNT];
- for (int i = 0; i < _LAYER_COUNT; ++i)
- {
- #ifdef DIFFUSE
- height[i] = mask[i].a;
- #else
- height[i] = mask[i].b;
- #endif
- }
- #ifdef _LAYERS_ONE
- return float(height[0]);
- #else
- float heightSum = dot(blendMask[0].rg, float2(height[0], height[1]));
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- heightSum += dot(blendMask[0].ba, float2(height[2], height[3]));
- #ifdef _LAYERS_EIGHT
- heightSum += dot(blendMask[1], float4(height[4], height[5], height[6], height[7]));
- #endif
- }
- #endif
- return heightSum;
- #endif
- }
- #ifdef _TERRAIN_BLEND_HEIGHT
- void HeightBlend(half4 mask[_LAYER_COUNT], inout half4 blendMask[2], float sharpness)
- {
- float heights[_LAYER_COUNT];
- for (int i = 0; i < _LAYER_COUNT; ++i)
- {
- #ifdef DIFFUSE
- heights[i] = mask[i].a;
- #else
- heights[i] = mask[i].b;
- #endif
- }
- #ifdef _LAYERS_TWO
- float2 height = float2(heights[0], heights[1]);
- blendMask[0].rg *= (1 / (pow(2, (height + blendMask[0].rg) * (-(sharpness)))) + 1) * 0.5;
- blendMask[0].rg /= (blendMask[0].r + blendMask[0].g);
- #else
- if (_TwoLayersOnly < 1)
- {
- float4 height = float4 (heights[0], heights[1], heights[2], heights[3]);
- blendMask[0].rgba *= (1 / (pow(2, (height + blendMask[0].rgba) * (-(sharpness)))) + 1) * 0.5;
- float heightSum = blendMask[0].r + blendMask[0].g + blendMask[0].b + blendMask[0].a;
- #ifdef _LAYERS_EIGHT
- float4 height1 = float4 (heights[4], heights[5], heights[6], heights[7]);
- blendMask[1].rgba *= (1 / (pow(2, (height1 + blendMask[1].rgba) * (-(sharpness)))) + 1) * 0.5;
- heightSum += blendMask[1].r + blendMask[1].g + blendMask[1].b + blendMask[1].a;
- blendMask[1].rgba /= heightSum;
- #endif
- blendMask[0].rgba /= heightSum;
- }
- else
- {
- float2 height = float2(heights[0], heights[1]);
- blendMask[0].rg *= (1 / (pow(2, (height + blendMask[0].rg) * (-(sharpness)))) + 1) * 0.5;
- blendMask[0].rg /= (blendMask[0].r + blendMask[0].g);
- }
- #endif
- }
- #endif
- #ifndef _TERRAIN_BASEMAP_GEN
- void SampleSplatTOL(in out half4 mixedAlbedo, in out half3 mixedNormal, float2 uv[_LAYER_COUNT], half4 blendMask[2], float weight, half4 mask[_LAYER_COUNT])
- {
- float4 albedo[1];
- float3 normal[1];
- albedo[0] = float4(0, 0, 0, 0);
- normal[0] = float3(0, 0, 1);
- blendMask[0].r *= weight;
- #ifndef TERRAIN_SPLAT_ADDPASS
- UNITY_BRANCH if (blendMask[0].r > 1e-5f)
- {
- albedo[0] = SampleSplt(0);
- albedo[0].rgb *= DiffuseRemap(0).rgb;
- albedo[0].a = Smoothness(0).x;
- normal[0] = SampleNormals(0);
- }
- mixedAlbedo = (albedo[0] * blendMask[0].r);
- mixedNormal = (normal[0] * blendMask[0].r);
- #else
- mixedAlbedo = float4(0, 0, 0, 0);
- mixedNormal = float3(0, 0, 0);
- #endif
- }
- void SampleMaskTOL(out half4 mask[_LAYER_COUNT], half4 noTriplanarMask[_LAYER_COUNT], float2 uv[_LAYER_COUNT], float weight)
- {
- #ifndef TERRAIN_SPLAT_ADDPASS
- UNITY_BRANCH if (weight > 1e-5f)
- {
- mask[0] = Mask(0, weight);
- mask[0] = RemapMask(0);
- }
- else
- {
- mask[0] = float4(0, 0, 0.5, 0);
- }
- #else
- mask[0] = noTriplanarMask[0];
- #endif
- mask[1] = noTriplanarMask[1];
- #ifndef _LAYERS_TWO
- if (_TwoLayersOnly < 1)
- {
- mask[2] = noTriplanarMask[2];
- mask[3] = noTriplanarMask[3];
- #ifdef _LAYERS_EIGHT
- mask[4] = noTriplanarMask[4];
- mask[5] = noTriplanarMask[5];
- mask[6] = noTriplanarMask[6];
- mask[7] = noTriplanarMask[7];
- #endif
- }
- #endif
- }
- #endif
- void UvSplatDistort(out float2 uvSplat[_LAYER_COUNT], float2 posOffset, fixed distortion)
- {
- uvSplat[0] = ((posOffset + (_SplatUV0.zw + distortion)) / _SplatUV0.xy);
- }
|