Is there an alternative to Blender's Mix Shader on Godot Visual Shader Editor?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Victoralm

How can I get that same kind of material on Godot, through Visual Shader Editor?
Even better: Is there an alternative, or some way to emulate it, node to the Blender’s Mix Shader (with factor option) on Godot?
I saw that it has a way to be done with splatmaps, coding the shader by hand… So something similar is possible.


:bust_in_silhouette: Reply From: Joel_127

That’s funny, I was doing exactly the same thing some days ago, however I’m not using a visual shader, but you should be able to replicate the code easily:

Here is where the magic happens (taken from the terrain editor plugin):

float color_sum = splat_color.r + splat_color.g + splat_color.b;

ALBEDO = (splat_color.r * col_tex_red.rgb +
          splat_color.g * col_tex_green.rgb +
          splat_color.b * col_tex_blue.rgb) / color_sum;

Full shader code:

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

uniform sampler2D splat_texture;

uniform sampler2D red_texture : hint_albedo;
uniform sampler2D blue_texture : hint_albedo;
uniform sampler2D green_texture : hint_albedo;

uniform float specular;
uniform float roughness : hint_range(0,1);

uniform vec3 uv1_scale;
uniform vec3 uv1_offset;

varying vec3 splat_color;

void vertex() {
	
	splat_color = texture(splat_texture, UV).rgb;
	UV=UV*uv1_scale.xy+uv1_offset.xy;
}

void fragment() {
	
	vec4 albedo_tex = texture(green_texture, UV);
	
	vec3 col_tex_red   = texture(red_texture, UV).rgb;
	vec3 col_tex_green = texture(green_texture, UV).rgb;
	vec3 col_tex_blue  = texture(blue_texture, UV).rgb;
	
	float color_sum = splat_color.r + splat_color.g + splat_color.b;
	
	ALBEDO = (splat_color.r * col_tex_red.rgb +
			  splat_color.g * col_tex_green.rgb +
			  splat_color.b * col_tex_blue.rgb) / color_sum;
	
	METALLIC = 0.0;
	ROUGHNESS = roughness;
	SPECULAR = specular;
}

I hope it helps!

edit
I see you have a base texture on color black as well, not sure how to add this, would love to know (I will test something this evening).

Here is my updated shader. I now use “mix” to blend textures, but I don’t know what is the corresponding node in the Visual Shader editor. I also blend the textures at two different scales to remove the visible patterns, looks really nice (image below).

shader_type spatial;

uniform sampler2D splat_texture;

uniform sampler2D base_texture : hint_albedo;
uniform sampler2D red_texture : hint_albedo;
uniform sampler2D blue_texture : hint_albedo;
uniform sampler2D green_texture : hint_albedo;

uniform float specular;
uniform float roughness : hint_range(0,1);
uniform float mix_factor : hint_range(0,1);

uniform float uv1_scale;
uniform float uv1_macro_scale;

varying vec2 uv1;
varying vec2 uv1_macro;

void vertex() {
	
	uv1=UV*uv1_scale;
	uv1_macro=UV*uv1_macro_scale;
}

void fragment() {
	
	vec3 splat_color = texture(splat_texture, UV).rgb;
	
	//add macro details
	vec3 col_tex_base_macro  = texture(base_texture, uv1_macro).rgb;
	vec3 col_tex_green_macro = texture(green_texture, uv1_macro).rgb;
	
	vec3 albedo_macro = mix(col_tex_base_macro, col_tex_green_macro, splat_color.g);
	
	//tiled small textures
	vec3 col_tex_base  = texture(base_texture, uv1).rgb;
	vec3 col_tex_red   = texture(red_texture, uv1).rgb;
	vec3 col_tex_green = texture(green_texture, uv1).rgb;
	vec3 col_tex_blue  = texture(blue_texture, uv1).rgb;
	
	vec3 albedo = mix(col_tex_base, col_tex_green, splat_color.g);
	albedo = mix(albedo, col_tex_red, splat_color.r);
	albedo = mix(albedo, col_tex_blue, splat_color.b);
	
	ALBEDO = mix(albedo, albedo_macro, mix_factor);
	
	METALLIC = 0.0;
	ROUGHNESS = roughness;
	SPECULAR = specular;
}

Joel_127 | 2019-04-11 20:48

Hi Joel_127, thanks for the response!

Following this tutorial, I’ve managed to make a shader too.
I’m sharing it on gist, because I’ve reach the characters limit for posting it in here…

But now that you showed your code, I’m willing to try out the mix(). Maybe I should create a function, to be less repetitive on my channels filtering stuff… I’m really newby on shaders, that was the very first time I’ve try something with it on Godot…

Victoralm | 2019-04-12 22:43

:bust_in_silhouette: Reply From: Joel_127

The node you are looking for is named “VectorInterp”

:bust_in_silhouette: Reply From: samuel.brunner

Why not simply using the mix fonction ?