Its complicated … heres what ive got …
func sample_image_bilnear_bump(image:Image,x:float, y:float, scale:float, divisor:float, size:float)->float:
var u_1 = scale * x / divisor
var v_1 = scale * y / divisor
var u__1 = (u_1 - int(u_1))
var v__1 = (v_1 - int(v_1))
var u1 = size * u__1
var v1 = size * v__1
var u12 = u1 + 1
if u12 > size-1: u12 = 0
var v12 = v1 + 1
if v12 > size-1: v12 = 0
# bilinear filter attempt
var m_uv1 := Vector2i( u1,v1)
var m_uv12 := Vector2i( u12,v1)
var m_uv13 := Vector2i( u1,v12)
var m_uv14 := Vector2i( u12,v12)
var disp11 = image.get_pixelv( m_uv1 ).a
var disp12 = image.get_pixelv( m_uv12 ).a
var disp13 = image.get_pixelv( m_uv13 ).a
var disp14 = image.get_pixelv( m_uv14 ).a
var disp1 = lerp ( lerp(disp11,disp12,u__1), lerp(disp13,disp14,u__1), v__1)
return disp1
@export var channel_for_splat:int
func get_map_values( x:float, z:float, X:int, Z:int):
var normal_pix:Color = nmap.get_pixel(X+int(x), Z+int(z))
var H1 = HEIGHT_SCALE*hmap.get_pixel(X + int(x-1), Z + int(z)).r
var H2 = HEIGHT_SCALE*hmap.get_pixel(X + int(x+1), Z + int(z)).r
var H3 = HEIGHT_SCALE*hmap.get_pixel(X + int(x), Z + int(z-1)).r
var H4 = HEIGHT_SCALE*hmap.get_pixel(X + int(x), Z + int(z+1)).r
var normal = -Vector3(2.0*(H2 - H1), -4.0, 2.0*(H4-H3) ).normalized();
var splat:Color = splat_map.get_pixel( X+int(x), Z+int(z) )
#x += X
#z += Z
# TEXTURE_DIVISOR is 127 here, 128-1, because x never reaches 128 for each tile, it goes 0-127
# BUT ... viewing with the collision mesh showed the results were bettwe when the shader
# had 128 as the divisor ... why ? I don't know, its still broken.
var disp1 =sample_image_bilnear_bump(alb1,x,z,UV_SCALE.x,128.0,512)
var u2 = int(512.0*(x * UV_SCALE.x/ TEXTURE_DIVISOR - floor(x * UV_SCALE.x/ TEXTURE_DIVISOR ) ))
var v2 = int(512.0*(z * UV_SCALE.x/ TEXTURE_DIVISOR - floor(z * UV_SCALE.x/ TEXTURE_DIVISOR ) ))
var m_uv2:= Vector2i( u2,v2 )
var disp2 = alb2.get_pixelv( m_uv2 ).a
var disp3 =sample_image_bilnear_bump(alb3,x,z,UV_SCALE.z,128.0,512)
var u4 = int( 512.0 * fposmod( (x * UV_SCALE.w)/ TEXTURE_DIVISOR, 1.0 ))
var v4 = int( 512.0 * fposmod( (z * UV_SCALE.w)/ TEXTURE_DIVISOR, 1.0 ))
var m_uv4:= Vector2i( u4,v4 )
var disp4 = alb4.get_pixelv( m_uv4 ).a
var splat_pixel = get_splat_color(splat)
var hval:float = (splat_pixel* disp1 +(1.0 -splat_pixel) * disp3)
return {
"normal":normal,
"height":hval
}
It is only using Textures 1 and 3, rock and grass in this case.
Then the displacement is calculated this way and also in the mesh instance shader (ordinary MeshInstance3D)
func generate_mesh_data(rect: Rect2) -> Array:
var mesh_faces_local :PackedVector3Array= PackedVector3Array()
for v in mesh_faces:
v.y = get_altitude(Vector3(rect.position.x+v.x, 0, rect.position.y+v.z))
var disp_dict = get_map_values(v.x, v.z, rect.position.x, rect.position.y)#x/2.0,z/2.0
var v1 =Vector3(v.x, v.y, v.z)
v1 += 5.0 * disp_dict["normal"] * disp_dict["height"]# - 2.5 * disp_dict["normal"]
mesh_faces_local.append(v1)
return mesh_faces_local