yeah blend_sharpness variable should always be just 1 i guess,
dont know why its exposed as a variable, this gives the same result
power_normal = abs(NORMAL);
i think, the fix lies in these lines of the shader>

power_normal = pow(abs(NORMAL),vec3(blend_sharpness));
power_normal /= dot(power_normal,vec3(1.0));

but im just guessing.

Ok, I removed all the detail blending and the issue remains so it's in that blend() function.

this was the only working method i found on an example on 'shadertoy'

n1 += vec3(0, 0, 1);
n2 *= vec3(-1, -1, 1);
	
return normalize(n1*dot(n1, n2)/n1.z - n2);

https://www.shadertoy.com/view/4t2SzR

    i also tried making a 'fake wind' shader, but its useless, as the editor becomes really, really slow.
    and the vertices dont get displaced correctly, it seems they get calculated from the pivot point of the mesh

    shader_type spatial;
    render_mode blend_mix, depth_prepass_alpha, cull_disabled, diffuse_burley, specular_schlick_ggx;
    uniform float alphatreshold;
    uniform float strenght : hint_range(0.0, 1.0, 0.05);
    uniform float speed : hint_range(0.0, 1.0, 0.1);
    
    uniform sampler2D colortex : source_color,filter_linear_mipmap,repeat_disable;
    uniform sampler2D normaltex :  hint_roughness_normal,filter_linear_mipmap,repeat_disable;
    uniform sampler2D roughnesstex : hint_roughness_gray,filter_linear_mipmap,repeat_disable;
    
    
    
    void vertex() {
    	
    	VERTEX.x += sin(TIME * speed + VERTEX.x + VERTEX.z ) * strenght * COLOR.g;
    	VERTEX.y += sin(TIME * speed + VERTEX.y + VERTEX.x ) * strenght * COLOR.g;
    	VERTEX.z += sin(TIME * speed + VERTEX.z + VERTEX.y ) * strenght * COLOR.g;
    
    }
    
    void fragment() {
    	
    	ALPHA = texture(colortex,UV).a;
    	ALPHA_SCISSOR_THRESHOLD = alphatreshold;
    	ALBEDO= texture(colortex,UV).rgb;
    	NORMAL_MAP = texture(normaltex,UV).rgb;
    	METALLIC = 0.0;
    	SPECULAR = 0.5;
    	ROUGHNESS = texture(roughnesstex,UV).r;
    	
    }

    DJM this was the only working method i found on an example on 'shadertoy'

     n1 += vec3(0, 0, 1);
     n2 *= vec3(-1, -1, 1);
     	
     return normalize(n1*dot(n1, n2)/n1.z - n2);

    It's not that, I already ruled that and now the blend() out. So it's just the triplanar mapping as far as i can tell. It's also entirely possible that the issue involves some bug in godot 4 rendering. I tried creating a standard material with triplanar mapping and converting into shader for comparison. The code seems pretty much the same as I suspected, so...

    • DJM replied to this.

      Not sure yet. I'll try and hammer out a custom shader from scratch to test further, in the meanwhile you can try setting up a test scene in godot 3 and copy and paste the shader into there, see how it does there.

      I think i got the normals fixed

      
      // Whiteout normal blending, example at https://blog.selfshadow.com/publications/blending-in-detail
      vec3 normalblend(vec3 n1, vec3 n2)
      {
      	n1 = n1 * 2.0 - 1.0;
      	n2 = n2 * 2.0 - 1.0;
      	return normalize(vec3(n1.xy + n2.xy, n1.z * n2.z)) + vec3(0.5, 0.5, 1.0);
      }

      This doubles the NORMAL_MAP_DEPTH, so that has to be 0.5 instead of 1.0 if you use this.

      • DJM replied to this.

        spacecloud tnx! that did it!
        heres' the working shader

        
        
        shader_type spatial;
        render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;
        uniform float blend_sharpness = 1.0;
        uniform float normal_scale = 1.0;
        
        uniform vec3 texture1_scale = vec3(1.0);
        
        uniform sampler2D texture1_albedo : source_color,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture1_normal : hint_normal,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture1_roughness : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        
        
        uniform vec3 texture2_scale = vec3(1.0);
        
        uniform sampler2D texture2_albedo : source_color,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture2_normal : hint_roughness_normal,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture2_roughness : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        
        
        uniform vec3 texture3_scale = vec3(1.0);
        
        uniform sampler2D texture3_albedo : source_color,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture3_normal : hint_roughness_normal,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture3_roughness : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        
        uniform sampler2D detailtexture : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        uniform sampler2D detailroughness : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        uniform sampler2D detailnormal : hint_roughness_normal,filter_linear_mipmap,repeat_enable;
        
        uniform vec3 detail_scale = vec3(1.0);
        varying vec3 power_normal;
        varying vec3 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);
        	power_normal = pow(abs(NORMAL),vec3(blend_sharpness));
        	triplanar_pos = VERTEX;
        	power_normal /= dot(power_normal,vec3(1.0));
        	triplanar_pos *= vec3(1.0,-1.0, 1.0);
        
        
        	
        }
        vec3 triplanar_texture(sampler2D p_sampler, vec3 p_triplanar_pos) {
        	vec3 samp = vec3(0.0);
        	samp += texture(p_sampler,p_triplanar_pos.xy).xyz * power_normal.z;
        	samp += texture(p_sampler,p_triplanar_pos.xz).xyz * power_normal.y;
        	samp += texture(p_sampler,p_triplanar_pos.zy).xyz * power_normal.x;
        	return samp;
        }
        
        vec3 blend(vec3 texture1, vec3 texture2, vec3 texture3, vec4 color){
        	return ((texture1 * color.r) + (texture2 * color.b) + (texture3 * color.g)).rgb;
        }
        
        vec3 normalblend(vec3 n1, vec3 n2)
        {
        	n1 = n1 * 2.0 - 1.0;
        	n2 = n2 * 2.0 - 1.0;
        	return normalize(vec3(n1.xy + n2.xy, n1.z * n2.z)) + vec3(0.5, 0.5, 1.0);
        }
        void fragment() {
        	vec3 albedo_texture = (blend(triplanar_texture(texture1_albedo, triplanar_pos * texture1_scale), triplanar_texture(texture2_albedo, triplanar_pos * texture2_scale) , triplanar_texture(texture3_albedo, triplanar_pos * texture3_scale), COLOR)) * triplanar_texture(detailtexture, triplanar_pos * detail_scale);
        	ALBEDO = albedo_texture.rgb;
        	vec3 orm_texture = (blend(triplanar_texture(texture1_roughness, triplanar_pos * texture1_scale), triplanar_texture(texture2_roughness, triplanar_pos * texture2_scale), triplanar_texture(texture3_roughness, triplanar_pos * texture3_scale), COLOR))* triplanar_texture(detailroughness, triplanar_pos * detail_scale);
        	AO = 1.0;
        	ROUGHNESS = orm_texture.r;
        	METALLIC = 0.0;
        	NORMAL_MAP = normalblend(blend(triplanar_texture(texture1_normal, triplanar_pos * texture1_scale), triplanar_texture(texture2_normal, triplanar_pos * texture2_scale), triplanar_texture(texture3_normal, triplanar_pos * texture3_scale), COLOR),triplanar_texture(detailnormal, triplanar_pos * detail_scale));
        	NORMAL_MAP_DEPTH = normal_scale;
        }

        any idea why my vertex offset shader is bad?

        I don't know other than that VERTEX is always relative to the pivot, so that might be messing up the displacement.
        If all transforms were applied in blender the pivot is at 0, 0, 0.

        i want the vertices painted vertex color green to be offsetted.

        but indeed the leafplanes are one mesh with the pivot at the center

        Anyways, far as I can tell, the blend sharpness factor is probably not even meant to be dialed below 1.0. My best guess, certainly the issue that becomes visible when going below 1 seems to be stemming from the triplanar_texture().

        For the wind shader, the culling being disabled probably has a negative impact, but it also doesn't seem such a high poly model. Still if you have many of them in the scene, that might be a factor.

        i can make m double sided, is there a better way to fake wind in godot?

        softbodies and physics? Not sure it's better performance, but maybe..? Also, what if your leaves are particles? I haven't tried any of this, but interesting questions in theory. Though I'd really expect a vertex shader to also work. I do find it odd, but it might just be 'alpha version' problems. So 🤷‍♂️

        Megalomaniak
        u were right, using world_vertex_coords fixed it, tnx!
        render_mode blend_mix, depth_prepass_alpha, cull_back, diffuse_burley, specular_schlick_ggx,world_vertex_coords;

        im trying to do the same technique to add triplanar detail to uvmapped meshes.
        however the tangents get messed up

        shader_type spatial;
        render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
        
        uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture_roughness : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        uniform sampler2D texture_normal : hint_roughness_normal,filter_linear_mipmap,repeat_enable;
        
        uniform sampler2D detailcolor : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        uniform sampler2D detailroughness : hint_roughness_gray,filter_linear_mipmap,repeat_enable;
        uniform sampler2D detailnormal : hint_roughness_normal,filter_linear_mipmap,repeat_enable;
        
        
        varying vec3 power_normal;
        
        uniform vec3 uv1_scale = vec3(1.0);
        uniform float normal_scale = 1.0;
        varying vec3 triplanar_pos;
        
        uniform vec3 detail_scale = vec3(1.0);
        
        
        
        
        void vertex() {
        	UV=UV*uv1_scale.xy;
        	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);
        	power_normal = pow(abs(NORMAL),vec3(1.0));
        	triplanar_pos = VERTEX;
        	power_normal /= dot(power_normal,vec3(1.0));
        	triplanar_pos *= vec3(1.0,-1.0, 1.0);
        }
        vec3 triplanar_texture(sampler2D p_sampler, vec3 p_triplanar_pos) {
        	vec3 samp = vec3(0.0);
        	samp += texture(p_sampler,p_triplanar_pos.xy).xyz * power_normal.z;
        	samp += texture(p_sampler,p_triplanar_pos.xz).xyz * power_normal.y;
        	samp += texture(p_sampler,p_triplanar_pos.zy * vec2(-1.0,1.0)).xyz * power_normal.x;
        	return samp;
        }
        vec3 normalblend(vec3 n1, vec3 n2)
        {
        	n1 = n1 * 2.0 - 1.0;
        	n2 = n2 * 2.0 - 1.0;
        	return normalize(vec3(n1.xy + n2.xy, n1.z * n2.z)) + vec3(0.5, 0.5, 1.0);
        }
        
        
        
        
        void fragment() {
        	vec2 base_uv = UV;
        	vec4 albedo_tex = texture(texture_albedo,base_uv);
        	
        	ALBEDO = albedo_tex.rgb;
        	AO = 1.0;
        	METALLIC = 0.0;
        	vec4 roughness_texture_channel = vec4(0.333333,0.333333,0.333333,0.0);
        	float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);
        	vec3 detail_roughness_tex = triplanar_texture(detailroughness,triplanar_pos * detail_scale);
        	ROUGHNESS = roughness_tex * detail_roughness_tex.r;
        	SPECULAR = 0.5;
        	vec3 detail_norm_tex = triplanar_texture(detailnormal,triplanar_pos * detail_scale);
        	NORMAL_MAP = normalblend(texture(texture_normal,base_uv).rgb,detail_norm_tex);
        	NORMAL_MAP_DEPTH = normal_scale;
        	vec3 detail_tex = triplanar_texture(detailcolor,triplanar_pos * detail_scale);
        	ALBEDO.rgb = ALBEDO.rgb * detail_tex;
        }

        You might want to look into using derivative maps instead of tangent space normal maps I suspect.

        it should be possible with tangent normal maps im sure.
        off topic
        physics collision detection on my large terrain mesh isnt very reliable with rigidbodies. sometimes objects just fall thru.
        edit//
        collision margin was too high, and switched to 'godot physics',its fixed
        edit again//
        collision detection is weird , rigidbodies fall thru terrain mesh. for example if i jump on a crate it just goes thru the collision mesh of the terrain