Hello wonderful Godot community! I have been trying to make a terrain for my game made the mesh separated into chunks, Wrote a little LOD script and so on. But came across a problem when I was writing a shader for my terrain. I'm using the splat map method and mixing different sets of textures, preferably I want to mix Albedo, Normal and Roughness. But have a problem doing that with Roughness maps.

Here's the code example to make things more clear:

    shader_type spatial;
    render_mode cull_disabled;
	
    uniform sampler2D splatmap;
    uniform sampler2D tex_base;
    uniform sampler2D tex_r;
    uniform sampler2D tex_g;
    uniform sampler2D tex_b;
    uniform sampler2D tex_a;
	
    uniform sampler2D norm_base;
    uniform sampler2D norm_r;
    uniform sampler2D norm_g;
    uniform sampler2D norm_b;
    uniform sampler2D norm_a;
	
    uniform sampler2D rough_base;
    uniform sampler2D rough_r;
    uniform sampler2D rough_g;
    uniform sampler2D rough_b;
    uniform sampler2D rough_a;
	
	
    uniform float base_res = 5; 
    uniform float r_res = 5; 
    uniform float g_res = 5;
    uniform float b_res = 5;
    uniform float a_res = 5;
	
	
    void fragment() {
		
        vec3 base_col;
        vec3 r_col;
        vec3 g_col;
        vec3 b_col;
        vec3 a_col;
		
	vec3 base_norm;
        vec3 r_norm;
        vec3 g_norm;
        vec3 b_norm;
        vec3 a_norm;
		
	vec3 base_rough;
        vec3 r_rough;
        vec3 g_rough;
        vec3 b_rough;
        vec3 a_rough;
		
        vec4 texs=texture(splatmap,UV);
        float rval = texs.r;
        float gval = texs.g;
        float bval = texs.b;
        float aval = 1.0-texs.a;
		
        float baseval = max(0.0,1.0-(rval+gval+bval+aval));
		
        base_col = texture(tex_base,UV*base_res).rgb * baseval;
        r_col = texture(tex_r,UV*r_res).rgb * rval;
        g_col = texture(tex_g,UV*g_res).rgb * gval;
        b_col = texture(tex_b,UV*b_res).rgb * bval;
        a_col = texture(tex_a,UV*a_res).rgb * aval;
		
        ALBEDO = base_col + r_col + g_col + b_col + a_col;
		
	base_norm = texture(norm_base,UV*base_res).rgb * baseval;
	r_norm = texture(norm_r,UV*r_res).rgb * rval;
	g_norm = texture(norm_g,UV*g_res).rgb * gval;
	b_norm = texture(norm_b,UV*b_res).rgb * bval;
        a_norm = texture(norm_a,UV*a_res).rgb * aval;
		
	NORMALMAP = base_norm + r_norm + g_norm + b_norm + a_norm;
 
 	base_rough = texture(rough_base,UV*base_res).rgb * baseval;
 	r_rough = texture(rough_r,UV*r_res).rgb * rval;
 	g_rough = texture(rough_g,UV*g_res).rgb * gval;
 	b_rough = texture(rough_b,UV*b_res).rgb * bval;
a_rough = texture(rough_a,UV*a_res).rgb * aval;
		
	ROUGHNESS = base_rough + r_rough + g_rough + b_rough + a_rough;

    }

naturally upon running the code I get an error:

:81 - Invalid arguments to operator '=' :float and vec3

Is there a way to mix roughness maps or I can only use a float value in the code? Which will basically assign the same value for every different texture set and will kill the whole point of using splat maps in a way... If someone has an answer to this please let me know...

If I remove the roughness part and only retain a line something like ROUGHNESS = 0.5 it will run perfectly, but it's a float value for all the texture which kills the whole look to be honest.

Hi wonderful person!

First of all it looks like the indentation might be a bit of a mess there, second of all, why are you inputting a vec3 into roughness? It's a grayscale/scalar value(a gradient if you will).

void fragment() {
  METALLIC = 0.0;
  ROUGHNESS = 0.01;
  ALBEDO = vec3(0.1, 0.3, 0.5);
}

edit: Just so you are not confused, the roughness value being a scalar in no way invalidates the usefulness of splat-maps. You should use your splats as masks for the different roughness values to mix them together, or layer them over each other rather, based on your splats.

Hello! Thank you for your reply! I'm sorry for indentation got screwed during the copy pasting phase.

I have made some tweaks to the code:


	shader_type spatial;
	render_mode cull_disabled;
	
	uniform sampler2D splatmap;
	uniform sampler2D tex_base;
	uniform sampler2D tex_r;
	uniform sampler2D tex_g;
	uniform sampler2D tex_b;
	uniform sampler2D tex_a;
	
	uniform sampler2D norm_base;
	uniform sampler2D norm_r;
	uniform sampler2D norm_g;
	uniform sampler2D norm_b;
	uniform sampler2D norm_a;
	
	uniform sampler2D rough_base;
	uniform sampler2D rough_r;
	uniform sampler2D rough_g;
	uniform sampler2D rough_b;
	uniform sampler2D rough_a;
	
	
	uniform float base_res = 5; 
	uniform float r_res = 5; 
	uniform float g_res = 5;
	uniform float b_res = 5;
	uniform float a_res = 5;
		
		
		void fragment() {
		
		vec3 base_col;
		vec3 r_col;
		vec3 g_col;
		vec3 b_col;
		vec3 a_col;
		
		vec3 base_norm;
		vec3 r_norm;
		vec3 g_norm;
		vec3 b_norm;
		vec3 a_norm;
		
		vec3 base_norm_depth;
		vec3 r_norm_depth;
		vec3 g_norm_depth;
		vec3 b_norm_depth;
		vec3 a_norm_depth;
		
		vec4 texs=texture(splatmap,UV);
		float rval = texs.r;
		float gval = texs.g;
		float bval = texs.b;
		float aval = 1.0-texs.a;
		
		
		float base_rough;
		float r_rough;
		float g_rough;
		float b_rough;
		float a_rough;
		
		float baseval = max(0.0,1.0-(rval+gval+bval+aval));
		
		base_col = texture(tex_base,UV*base_res).rgb * baseval;
		r_col = texture(tex_r,UV*r_res).rgb * rval;
		g_col = texture(tex_g,UV*g_res).rgb * gval;
		b_col = texture(tex_b,UV*b_res).rgb * bval;
		a_col = texture(tex_a,UV*a_res).rgb * aval;
		
		ALBEDO = base_col + r_col + g_col + b_col + a_col;
		
		base_norm = texture(norm_base,UV*base_res).rgb * baseval;
		r_norm = texture(norm_r,UV*r_res).rgb * rval;
		g_norm = texture(norm_g,UV*g_res).rgb * gval;
		b_norm = texture(norm_b,UV*b_res).rgb * bval;
		a_norm = texture(norm_a,UV*a_res).rgb * aval;
		
		NORMALMAP = base_norm + r_norm + g_norm + b_norm + a_norm;
		
		base_rough = texture(rough_base,UV*base_res).a * baseval;
		r_rough = texture(rough_r,UV*r_res).a * rval;
		g_rough = texture(rough_g,UV*g_res).a * gval;
		b_rough = texture(rough_b,UV*b_res).a * bval;
		a_rough = texture(rough_a,UV*a_res).a * aval;

		ROUGHNESS = base_rough + r_rough + g_rough + b_rough + a_rough;
		//ROUGHNESS = 0.05;

    }

And still it won't work, I'm so confused about roughness... Currently It will take alpha value of each roughness map which is pure white I presume. If I assign every roughness float variable to different float numbers and then add it together I will get a uniform value for everything and it will defeat the whole purpose of having different textures and a splat map... Clueless how to proceed next... =(

Should have deleted norm_depth lines, oh well...

Sorry, my bad it seems to be working, this time the problem where in the roughness image files I used, the code above is viable, sorry to bother. Thank you for your help!

I suppose you might need to normalize your output so it would properly fall within the 0 to 1 range, but I also have no clue what your roughness maps are like. They should obviously be catered to godot specifically.

In as far as adding the values together, that isn't really the way I'd go. I'd use the splats as mixing factors to mix between two of the different respective surface rougnesses if putting it that way makes sense.

vec_type mix ( float a, float b, float c ) 	Linear Interpolate
vec_type mix ( vec_type a, vec_type b, float c ) 	Linear Interpolate (Scalar Coef.)
vec_type mix ( vec_type a, vec_type b, vec_type c ) 	Linear Interpolate (Vector Coef.)
vec_type mix ( vec_type a, vec_type b, bvec_type c ) 	Linear Interpolate (Boolean-Vector Selection)

Note the third input of the mix should be the mixing factor between the first two.

edit: the way I'd proceed right now, would be to either comment out or even remove all the other data and focus on just dealing with the roughness alone in the shader. A good tip for debugging scalar values is to also temporarily send it as output to the emission so you can visibly see the value as it is processed.

@MeshVoid said: Sorry, my bad it seems to be working, this time the problem where in the roughness image files I used, the code above is viable, sorry to bother. Thank you for your help!

Ah, that's great to hear, I guess I was writing the last post while you were posting this so I didn't notice it until now.

3 years later