Blending textures based percent of normal in a shader
Asked Answered
T

8

0

I currently have a shader that takes two textures and when the normal is less than 0.5 uses the second texture (I'm using it for snow effects). The normal I'm using I calculate via

vec3 global_normal = (INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz;
float interp_by = dot(global_normal, slant);

slant being a uniform vec3 (set to 0,1,0), basically the objects normal restricted to up or down.

It looks good enough for now here, but I want to use a similar technique on a dome like so

This obviously looks terrible.
I currently switch texture when interp_by == 0.5, but to blend the two textures I take the space 0.55-0.45. I figured two ways I could blend the texture, neither of which I can work properly.
Method 1 is to have a noise texture then take the X value and get it's percent of 255:

float val = texture(noise, UV).x;
float a = (val/255.0);
ALBEDO=mix(vec3(albedo_tex_1), vec3(albedo_tex_2), a);

this should mix with what looks like randomly varying strengths in the 0.55-0.45 area.

alas just this.

Method 2 was to calculate the percentage between the start and end of 0.55-0.45 and use that as the mix strength.

float mid_top = 0.5 + 0.1;
float mid_bot = 0.5 - 0.1;

float whole = mid_top-mid_bot;
float part = interp_by-mid_bot;
float percent = (part/whole)*100.0;
ALBEDO=mix(vec3(albedo_tex_1), vec3(albedo_tex_2), percent);

The full shader. The above methods are commented out. It also includes triplanar mapping:

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

group_uniforms Texture1;
uniform sampler2D texture1 : source_color;
uniform vec3 albedo1 : source_color = vec3(255.0);
uniform float albedo1_strength : hint_range(0.0, 1.0) = 0.0;

group_uniforms Texture2;
uniform sampler2D texture2 : source_color;
uniform vec3 albedo2 : source_color = vec3(255.0);
uniform float albedo2_strength : hint_range(0.0, 1.0) = 0.0;

group_uniforms Placement;
uniform float split_at : hint_range(0.0, 1.0) = 0.5;
uniform vec3 slant = vec3(0.0, 1.0, 0.0);
uniform float uv_blend_sharpness : hint_range(0.0, 150.0) = 150.0;
uniform sampler2D noise : source_color;

varying vec3 uv1_power_normal;
varying vec3 uv1_triplanar_pos;

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);
	uv1_power_normal=pow(abs(NORMAL),vec3(uv_blend_sharpness));
	uv1_triplanar_pos = VERTEX;
	uv1_power_normal/=dot(uv1_power_normal,vec3(1.0));
	uv1_triplanar_pos *= vec3(1.0,-1.0, 1.0);
}

vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_triplanar_pos) {
	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;
}

void fragment() {
	vec3 albedo_tex_1 = triplanar_texture(texture1,uv1_power_normal,uv1_triplanar_pos).rgb; 
	vec3 albedo_tex_2 = triplanar_texture(texture2,uv1_power_normal,uv1_triplanar_pos).rgb; 	

	vec3 global_normal = (INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz;
	float interp_by = dot(global_normal, slant);
	
    // would be +/- 0.1 for the middle space
	float mid_top = split_at + 0.0; //0.1;
	float mid_bot = split_at - 0.0; //0.1;
	
	if (interp_by < 1.0 && interp_by > mid_top) {
		ALBEDO=mix(vec3(albedo_tex_2.xyz), vec3(albedo2), albedo2_strength);
	}
	
	if (interp_by <= mid_top && interp_by >= mid_bot) {
        // Method 1 (Noise)
        // float val = texture(noise, UV).x;
        // float percent = (val/255.0);
        // ALBEDO=mix(vec3(albedo_tex_1), vec3(albedo_tex_2), percent);

        // Method 2 (Percent)
        //float whole = mid_top-mid_bot; // 0.6-0.4=0.2
		//float part = interp_by-mid_bot; // 0.41-0.4=0.01
		//float percent = (part/whole)*100.0; //0.01/0.2

		//ALBEDO=mix(vec3(albedo_tex_1), vec3(albedo_tex_2), percent);

	}
	
	if (interp_by < mid_bot && interp_by > -0.1) {
		ALBEDO=mix(vec3(albedo_tex_1.xyz), vec3(albedo1), albedo1_strength);
	}
}

If this doesnt make any please tell me this is a lot

Trinary answered 21/11, 2023 at 5:51 Comment(0)
Q
0

Trinary

shader_type spatial;

uniform sampler2D noise;
uniform float threshold: hint_range(0.0, 1.0) = .5;
uniform float smoothZone: hint_range(0.0, 1.0) = .1;
uniform float noiseZone: hint_range(0.0, 2.0) = .2;

void fragment() {
	vec3 n = mat3(INV_VIEW_MATRIX) * NORMAL;
	float t = dot(n, vec3(0.0, 1.0, 0.0)) + (texture(noise, UV).x - .5) * noiseZone;
	ALBEDO = mix(vec3(0.0), vec3(1.0), smoothstep(threshold-smoothZone, threshold+smoothZone, t));
}

Quinary answered 21/11, 2023 at 6:39 Comment(0)
D
0

Quinary shader_type spatial;

Great job! πŸ‘οΈ Probably, for a perfect snow simulation, it would be very good to make a vertex shift. πŸ§‘β€πŸ”¬

Donofrio answered 21/11, 2023 at 15:54 Comment(0)
Q
1

Donofrio Thanks. Easy enough to add some displacement πŸ˜‰

shader_type spatial;

uniform sampler2D noise;
uniform float threshold: hint_range(0.0, 1.0) = .5;
uniform float smoothZone: hint_range(0.0, 1.0) = .1;
uniform float noiseZone: hint_range(0.0, 2.0) = .2;
uniform float displace: hint_range(0.0, 1.0) = .1;

float snow(vec3 normal, vec2 uv){
	float t = dot(normal, vec3(0.0, 1.0, 0.0)) + (texture(noise, uv).x- .5) * noiseZone;
	return smoothstep(threshold-smoothZone, threshold+smoothZone, t);
}

void vertex(){ VERTEX += NORMAL * snow(NORMAL, UV) * displace; }
void fragment(){ ALBEDO = mix(vec3(0.0), vec3(1.0), snow(mat3(INV_VIEW_MATRIX) * NORMAL, UV )); }

Quinary answered 21/11, 2023 at 16:25 Comment(0)
D
0

Quinary Easy enough to add some displacemen

Absolutely perfect!! β˜ƒοΈ

Donofrio answered 21/11, 2023 at 17:52 Comment(0)
T
0

Thanks thats really nice looking!

Trinary answered 21/11, 2023 at 18:21 Comment(0)
D
0

Quinary asy enough to add some displacement

Are you going to publish this wonderful shader somewhere?

Donofrio answered 21/11, 2023 at 19:57 Comment(0)
Q
0

Donofrio Are you going to publish this wonderful shader somewhere?

I'm not sure it's worth publishing. It's pretty basic, just a mix mask driven by inclination, although it looks nice when mapped on a sphere. I guess I could put it on godotshaders.

Quinary answered 21/11, 2023 at 21:48 Comment(0)
D
0

Quinary I'm not sure it's worth publishing.

Well, I find it very useful. For understanding how shaders work, it's marvelous. There are very few tutorials on shaders.

I guess I could put it on godotshaders.

It's a beautiful place.

Donofrio answered 21/11, 2023 at 21:57 Comment(0)

© 2022 - 2025 β€” McMap. All rights reserved.