I need some help/advice on how to blend textures in a shader

I have been working on a shader to make all my caves in my 3d generated terrains.
So far I have gotten it working that the top is being smoothed from stone to grass, just the under side I have no clue how to fix.

I have been working on it for a few days now and I am completely clueless on what to do next.

2019-05-20_2141 Here is an image, the top is being smoothed but the underside isn’t yet.

Here the shader I use:

Shader "Custom/TerrainFragment" {
	SubShader{
		Tags { "RenderType" = "Opaque" }
		LOD 200

		CGPROGRAM
		#pragma surface surf Standard fullforwardshadows
		#pragma target 3.0
		
		const static int maxLayerCount = 8;
		const static float epsilon = 1E-4;

		int layerCount;
		float3 baseColors[maxLayerCount];
		float baseStartHeights[maxLayerCount];
		float baseBlends[maxLayerCount];
		float baseColorStrength[maxLayerCount];
		float baseTextureScales[maxLayerCount];
		int tileSize;

		const static int maxTileSize = 32;
		float maxHeightMap[1024]; // maxTileSize * maxTileSize
		
		
		UNITY_DECLARE_TEX2DARRAY(baseTextures);
		
		struct Input {
			float3 worldPos;
			float3 worldNormal;
		};
		
		float inverseLerp(float a, float b, float value) {
			return saturate((value - a) / (b - a));
		}

		float3 triplanar(float3 worldPos, float scale, float3 blendAxes, int textureIndex) {
			float3 scaledWorldPos = worldPos / scale;
			float3 xProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.y, scaledWorldPos.z, textureIndex)) * blendAxes.x;
			float3 yProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.z, textureIndex)) * blendAxes.y;
			float3 zProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.y, textureIndex)) * blendAxes.z;

			return xProjection + yProjection + zProjection;
		}

		void surf(Input IN, inout SurfaceOutputStandard o) {
			float posX = abs(IN.worldPos.x) % tileSize;
			float posZ = abs(IN.worldPos.z) % tileSize;

			float index = int(posX) + (int(posZ) * tileSize);

			float maxHeight = maxHeightMap[index];
			float heightPercent = inverseLerp(0,maxHeight, IN.worldPos.y);

			float3 blendAxes = abs(IN.worldNormal);
			blendAxes /= blendAxes.x + blendAxes.y + blendAxes.z;
			
			for (int i = 0; i < layerCount; i++) {
				float drawStrength = inverseLerp(-baseBlends <em>/ 2 - epsilon, baseBlends _/ 2, heightPercent - baseStartHeights*);*_</em>

float3 baseColor = baseColors * baseColorStrength*;*
float3 textureColor = triplanar(IN.worldPos, baseTextureScales_, blendAxes, i) * (1 - baseColorStrength*);*_

_ o.Albedo = o.Albedo * (1 - drawStrength) + (baseColor + textureColor) * drawStrength;
* }
}*_

* ENDCG*
* }*
* FallBack “Diffuse”*
}
*this is how the settings i use that is being applied on the shader looks: https://www.screencast.com/t/DqmFrrBgJ*_
Any help is appreciated_

With some help from the unity discord I fixed the shader, removed the heightmap and implemented the perlin noise library i used into the shader.

Here is the shader, I hope someone else can use it as well :slight_smile:

Shader "Custom/TerrainFragment" {
	Properties{
	}
	SubShader{
		Tags { "RenderType" = "Opaque" }
		LOD 200

		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		const static int maxLayerCount = 8;
		const static float epsilon = 1E-4;

		int layerCount;
		float3 baseColors[maxLayerCount];
		float baseStartHeights[maxLayerCount];
		float baseBlends[maxLayerCount];
		float baseColorStrength[maxLayerCount];
		float baseTextureScales[maxLayerCount];

		int seed;
		int tileSize;
		int maxTileHeight;
		int minTileHeight;
		
		int heightMapCount;
		float heightMapScales[maxLayerCount];
		float weightScales[maxLayerCount];

		UNITY_DECLARE_TEX2DARRAY(baseTextures);
		
		float perm[257];
		
		struct Input {
			float3 worldPos;
			float3 worldNormal;
		};
		
		
		float Fade(float t)
		{
			return t * t * t * (t * (t * 6 - 15) + 10);
		}
		
		float Lerp(float t, float a, float b)
		{
			return a + t * (b - a);
		}
		
		float Grad(uint hash, float x, float y)
		{
			return ((hash & 1) == 0 ? x : -x) + ((hash & 2) == 0 ? y : -y);
		}
		
		float noise(float x, float y)
		{
			uint X = (uint)floor(x) & 0xff;
			uint Y = (uint)floor(y) & 0xff;
			x -= floor(x);
			y -= floor(y);
			float u = Fade(x);
			float v = Fade(y);
			uint A = (uint)(perm[X  ] + Y) & 0xff;
			uint B = (uint)(perm[X+1] + Y) & 0xff;
			return Lerp(v, Lerp(u, Grad(perm[A  ], x, y  ), Grad(perm[B  ], x-1, y  )),
						Lerp(u, Grad(perm[A+1], x, y-1), Grad(perm[B+1], x-1, y-1)));
		}
		
		float inverseLerp(float a, float b, float value) {
			return saturate((value - a) / (b - a));
		}

		float3 triplanar(float3 worldPos, float scale, float3 blendAxes, int textureIndex) {
			float3 scaledWorldPos = worldPos / scale;
			float3 xProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.y, scaledWorldPos.z, textureIndex)) * blendAxes.x;
			float3 yProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.z, textureIndex)) * blendAxes.y;
			float3 zProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.y, textureIndex)) * blendAxes.z;

			return xProjection + yProjection + zProjection;
		}

		void surf(Input IN, inout SurfaceOutputStandard o) {
			float maxHeightPercentage = 0;
			
			for (int i = 0; i < heightMapCount; i++) {
				float scale = heightMapScales*;*

_ float xPos = (seed + IN.worldPos.x) / tileSize * scale;_
_ float zPos = (seed + IN.worldPos.z) / tileSize * scale;_

_ maxHeightPercentage += (noise(xPos, zPos) + 0.6) * weightScales*;_
_
}*_

_ float maxHeight = ((maxTileHeight - minTileHeight) * maxHeightPercentage) + minTileHeight - 1;_
* float heightPercent = inverseLerp(0,maxHeight, IN.worldPos.y);*

* float3 blendAxes = abs(IN.worldNormal);*
* blendAxes /= blendAxes.x + blendAxes.y + blendAxes.z;*

* for (int li = 0; li < layerCount; li++) {*
* float drawStrength = inverseLerp(-(baseBlends- / 2) - epsilon, baseBlends- / 2, heightPercent - baseStartHeights- );*

_ float3 baseColor = baseColors- * baseColorStrength- ;
float3 textureColor = triplanar(IN.worldPos, baseTextureScales- , blendAxes, li) * (1 - baseColorStrength- );_

_ o.Albedo = o.Albedo * (1 - drawStrength) + (baseColor + textureColor) * drawStrength;_
* }*
* }*

* ENDCG*
* }*
* FallBack “Diffuse”*
}