shader_type spatial; render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx; uniform vec2 wind_direction = vec2(0.94, 0.34); uniform float wind_strength : hint_range(0.0, 0.2) = 0.07; uniform float wind_speed : hint_range(0.0, 2.0) = 0.55; uniform float gust_speed : hint_range(0.0, 1.0) = 0.12; uniform float gust_strength : hint_range(0.0, 0.8) = 0.35; uniform float flutter_strength : hint_range(0.0, 0.05) = 0.012; uniform float wind_phase : hint_range(0.0, 6.2832) = 0.0; uniform vec3 albedo : source_color = vec3(0.19, 0.38, 0.17); uniform float roughness : hint_range(0.0, 1.0) = 0.9; varying vec3 paint_position; void vertex() { paint_position = VERTEX; float half_height = 1.2; float height_factor = clamp((VERTEX.y + half_height) / (half_height * 2.0), 0.0, 1.0); height_factor = height_factor * height_factor; vec2 direction = normalize(wind_direction); vec2 crosswind = vec2(-direction.y, direction.x); float world_phase = wind_phase + dot(MODEL_MATRIX[3].xz, vec2(0.07, 0.05)); float gust_wave = 0.5 + 0.5 * sin(TIME * gust_speed + world_phase * 0.7); float gust = mix(1.0 - gust_strength, 1.0, gust_wave); float bend = sin(TIME * wind_speed + world_phase) * wind_strength * gust; float flutter = sin(TIME * 1.7 + world_phase * 1.9 + VERTEX.y * 2.0) * flutter_strength; VERTEX.xz += direction * bend * height_factor; VERTEX.xz += crosswind * flutter * height_factor; } void fragment() { float patches = sin(paint_position.x * 6.0 + sin(paint_position.z * 7.0)) * sin(paint_position.y * 5.0); float top = smoothstep(-0.65, 0.8, paint_position.y); ALBEDO = albedo * mix(0.85, 1.17, top) * (1.0 + smoothstep(0.2, 0.4, patches) * 0.10); ROUGHNESS = roughness; SPECULAR = 0.0; } void light() { float band = smoothstep(0.08, 0.18, dot(NORMAL, LIGHT)); float highlight = smoothstep(0.62, 0.74, dot(NORMAL, LIGHT)); vec3 tone = mix(vec3(0.32, 0.48, 0.39), vec3(0.87, 0.92, 0.72), band); tone = mix(tone, vec3(1.12, 1.08, 0.82), highlight); DIFFUSE_LIGHT += tone * ATTENUATION * LIGHT_COLOR / PI; }