Cheap parallax planes array
Parallax planes. Test on an array of 11 1mx1m planes with 1m height (Created with Blender, add modifier Array.), then we compact it to 0.025 with the Shader.
Using two textures, one colored for the diffuse and another packed for the normal and height. Texture packing with normal map in XY and height map in Z. Godot 4.3.
Shader code
//Parallax planes. Test on an array of 11 1mx1m planes with 1m height, then compact it to 0.025.
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx;
uniform float compact_arrays : hint_range(-1.0, 1.0, 0.005) = 0.025;
uniform float offset_arrays : hint_range(0.0, 1.0, 0.005) = 0.0;
uniform float scissor_arrays : hint_range(0.01, 0.2, 0.005) = 0.08;
uniform sampler2D tex_diffuse: source_color;
uniform sampler2D tex_normal_height: hint_default_white;// Texture packing with normal map in XY and height map in Z
uniform sampler2D ramp_control;// add gradient texture 1D, White to Black, change the value of Black from 0 to 10.Add a Gray of Value = 14 placed in between as a control to move and modify the height map
void vertex() {
// Vertex color Y
COLOR.y = VERTEX.y * 0.99;// "* 0.99" fix UV bug -> ramp control;
VERTEX.y = VERTEX.y * compact_arrays;//compact_arrays
VERTEX.y = VERTEX.y - offset_arrays;//By default it is Convex with the value 0:0, for Concave give the value compact_arrays. But an intermediate one works for grass.
}
void fragment() {
// Diffuse
lowp vec3 read_diffuse = texture(tex_diffuse, UV).rgb;
// Normal & Height
lowp vec3 read_normal_height = texture(tex_normal_height, UV).xyz;
// ramp control
lowp float read_ramp = texture(ramp_control, vec2(COLOR.y)).z;
lowp float top_alpha = (read_ramp * read_normal_height.z);
// Output
ALBEDO = read_diffuse;// replace with "vec3(read_ramp)" to display the highest grayscale height with the planes.
ALPHA = top_alpha;
NORMAL_MAP = vec3(read_normal_height.xy, 1.0);
ALPHA_SCISSOR_THRESHOLD = scissor_arrays;
}