Terrain Mesh Blending – Godot 4.3

Steps to setup:

 

  • Setup your ground mesh with triplaner setting on “UV1 -> Triplaner” you can still change it’s scale.
  • Add the shader to your mesh that you want to blend with the ground.
  • Add the textures for your mesh, and the ground textures for the blend textures.

Original Godot 3 Shader by : Kmitt91

-I have not made this shader, I just updated it to Godot 4.3.

Shader code
shader_type spatial;

uniform vec3 n = vec3(0.0, 1.0, 0.0);

uniform float triplanar_scale = 1.0;
uniform float blend_size = 1.0;
uniform float blend_offset = 0.0;

uniform sampler2D transition_mask;

uniform sampler2D main_albedo : source_color;
uniform sampler2D main_normal : hint_normal;
uniform sampler2D main_roughness : source_color;
uniform sampler2D main_ao: source_color;

uniform sampler2D blend_albedo : source_color;
uniform sampler2D blend_normal : hint_normal;
uniform sampler2D blend_roughness : source_color;
uniform sampler2D blend_ao: source_color;

varying vec3 uv_triplanar_pos;
varying vec3 uv_power_normal;

void vertex(){
	
	TANGENT = vec3(0.0,0.0,-1.0) * abs(NORMAL.x);
	TANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.y);
	TANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.z);
	TANGENT = normalize(TANGENT);
	BINORMAL = vec3(0.0,1.0,0.0) * abs(NORMAL.x);
	BINORMAL+= vec3(0.0,0.0,-1.0) * abs(NORMAL.y);
	BINORMAL+= vec3(0.0,1.0,0.0) * abs(NORMAL.z);
	BINORMAL = normalize(BINORMAL);
	
	uv_power_normal = pow(abs(mat3(MODEL_MATRIX) * NORMAL), vec3(1.0));
	uv_triplanar_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0f)).xyz * triplanar_scale;
	uv_power_normal /= dot(uv_power_normal, vec3(1.0));
	uv_triplanar_pos *= vec3(1.0, -1.0, 1.0);
}

vec4 triplanar_texture(sampler2D p_sampler,vec3 p_triplanar_pos, vec3 p_weights) {
	vec4 samp = vec4(0.0);
	samp+= texture(p_sampler,p_triplanar_pos.xy) * p_weights.z;
	samp+= texture(p_sampler,p_triplanar_pos.xz) * p_weights.y;
	samp+= texture(p_sampler,p_triplanar_pos.zy * vec2(-1.0,1.0)) * p_weights.x;
	return samp;
}

float overlay(float a, float b){
	if(a < 0.5){
		return a * b * 2.0;
	}else{
		return 1.0- 2.0 * (1.0 - a)*(1.0 - b);
	}
}

void fragment(){
	vec3 p = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
	float dist = dot(p, n);
	dist = max(min((dist + blend_offset) * blend_size - 0.5, 1.0), 0.0);
	
	
	vec4 m_col = texture(main_albedo, UV);
	vec3 m_norm = texture(main_normal, UV).rgb;
	float m_rough = texture(main_roughness, UV).r;
	float m_ao = texture(main_ao, UV).r;
	
	vec4 b_col = triplanar_texture(blend_albedo, uv_triplanar_pos, uv_power_normal);
	vec3 b_norm = triplanar_texture(blend_normal, uv_triplanar_pos, uv_power_normal).rgb;
	float b_rough = triplanar_texture(blend_roughness, uv_triplanar_pos, uv_power_normal).r;
	float b_ao = triplanar_texture(blend_ao, uv_triplanar_pos, uv_power_normal).r;
	
	
	float blend_mask = texture(transition_mask, UV).r;
	float blend = overlay(dist, blend_mask);
	
	ALBEDO = mix(b_col.rgb, m_col.rgb, blend);
	NORMAL_MAP = mix(b_norm, m_norm, blend);
	ROUGHNESS = mix(b_rough, m_rough, blend);
	AO = mix(b_ao, m_ao, blend);
	AO_LIGHT_AFFECT = 0.5;
}
Tags
3d
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Terrain Mesh Blending with Dithering

mesh-terrain blending

Mesh Blending with Alpha

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments