Blend ORM materials 2 (+hotspot texturing tutorial)

This is an improved version of my “Blend ORM materials” shader. This is a material blending shader based on Godot’s ORM material. It blends two materials based on the mesh red channel vertex color

In this improved version you can also use a noise texture to make the transition more organic and you can choose how hard/sharp or soft the transition between the materials will be.

I’ve created this for my “how to make hotspot texturing very fast and easily with Material Makervideo tutorial for my youtube channel (its in spanish). You can find the video tutorial and the sample project with a custom material for Material Maker, on my github.

 

Shader code
// NOTE: Shader based on an automatically converted one from Godot Engine 4.6.1.stable's ORMMaterial3D.

shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;

uniform vec4 albedo_a : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform sampler2D texture_albedo_a : source_color, filter_linear_mipmap, repeat_enable;
uniform vec4 albedo_b : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform sampler2D texture_albedo_b : source_color, filter_linear_mipmap, repeat_enable;

uniform sampler2D texture_orm_a : hint_roughness_g, filter_linear_mipmap, repeat_enable;
uniform sampler2D texture_orm_b : hint_roughness_g, filter_linear_mipmap, repeat_enable;

uniform sampler2D texture_normal_a : hint_roughness_normal, filter_linear_mipmap, repeat_enable;
uniform float normal_scale_a : hint_range(-16.0, 16.0) = 1.0;
uniform sampler2D texture_normal_b : hint_roughness_normal, filter_linear_mipmap, repeat_enable;
uniform float normal_scale_b : hint_range(-16.0, 16.0) = 1.0;

uniform sampler2D texture_heightmap_a : hint_default_black, filter_linear_mipmap, repeat_enable;
uniform sampler2D texture_heightmap_b : hint_default_black, filter_linear_mipmap, repeat_enable;
uniform float heightmap_scale : hint_range(-16.0, 16.0, 0.001) = 0.0;
uniform vec2 heightmap_flip = vec2(1.0, 1.0); 

uniform vec3 uv1_scale = vec3(1.0, 1.0, 1.0);
uniform vec3 uv1_offset = vec3(0.0, 0.0, 0.0);

// extra
uniform vec2 blending_add_mul = vec2(0.0, 1.0); // add + mul
uniform vec2 roughness_add_mul = vec2(0.0, 1.0); // add + mul
uniform vec2 metallic_add_mul = vec2(0.0, 1.0); // add + mul
uniform sampler2D blending_noise : filter_linear_mipmap, repeat_enable; // use a seamless texture!
uniform float blending_threshold : hint_range(0.0, 1.0, 0.001) = 0.5;
uniform float blending_softness : hint_range(0.0, 1.0, 0.001) = 0.01;
uniform vec2 noise_scale = vec2(0.123, 0.456);
uniform float noise_strength : hint_range(0.0, 2.0, 0.001) = 1.0;

void vertex() {
	UV = UV * uv1_scale.xy + uv1_offset.xy;
}

void fragment() {
	vec2 base_uv = UV;
	
	// get blending from vertex color red channel
	float blending = clamp( (COLOR.r * blending_add_mul.y) + blending_add_mul.x, 0.0, 1.0 );
	
	// get noise
	float noi1 = texture(blending_noise, UV * noise_scale.x).r; 
	float noi2 = texture(blending_noise, UV * noise_scale.y).r; 
	float noi = clamp( ( ( noi1 - noi2 ) + 0.5 ) * noise_strength, 0.0, 1.0 ); 
	
	// compute final blending value
	blending = smoothstep(blending_threshold - blending_softness, blending_threshold + blending_softness, blending * noi);
	
	// height 
	vec3 view_dir = normalize(normalize(-VERTEX + EYE_OFFSET) * mat3(TANGENT * heightmap_flip.x, -BINORMAL * heightmap_flip.y, NORMAL));
	float depth_a = 1.0 - texture(texture_heightmap_a, base_uv).r;
	float depth_b = 1.0 - texture(texture_heightmap_b, base_uv).r;
	float depth = mix(depth_a, depth_b, blending);
	vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale * 0.01;
	base_uv = ofs;

	// albedo
	vec3 albedo_tex_a = albedo_a.rgb * texture(texture_albedo_a, base_uv).rgb;
	vec3 albedo_tex_b = albedo_b.rgb * texture(texture_albedo_b, base_uv).rgb;
	ALBEDO = mix(albedo_tex_a, albedo_tex_b, blending);

	// orm
	vec4 orm_tex_a = texture(texture_orm_a, base_uv);
	vec4 orm_tex_b = texture(texture_orm_b, base_uv);	
	AO = mix(orm_tex_a.r, orm_tex_b.r, blending); 
	float rough = mix(orm_tex_a.g, orm_tex_b.g, blending);
	ROUGHNESS = clamp( (rough * roughness_add_mul.y) + roughness_add_mul.x, 0.0, 1.0); 
	float metal = mix(orm_tex_a.b, orm_tex_b.b, blending);
 	METALLIC = clamp( (metal * metallic_add_mul.y) + metallic_add_mul.x, 0.0, 1.0);
	
	// normal 
	vec3 normal_a = (texture(texture_normal_a, base_uv).xyz - 0.5) * 2.0;
	vec3 normal_b = (texture(texture_normal_b, base_uv).xyz - 0.5) * 2.0;
	NORMAL_MAP = (normalize(mix(normal_a, normal_b, blending)) * 0.5) + 0.5;
	NORMAL_MAP_DEPTH = mix(normal_scale_a, normal_scale_b, blending);
	
	//test
	//ALBEDO = vec3(blending);
}
Live Preview
Tags
blend, hotspot, material, Mix, orm, textures, Texturing
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from ProfesorShader

Related shaders

guest

0 Comments
Oldest
Newest Most Voted