4#define_import_path bevy_aqua_core::deform 6#import bevy_pbr::{forward_io::Vertex, mesh_functions} 7#import aqua::cascade::{BodyParams, DEBUG_MODE_BEAUTY, DEBUG_MODE_FAR_TIER, MIN_NORMAL_Y, SAFE_LENGTH_SQUARED, begin_invocation, cascade_layout, effective_flow, far_tier_weight, field_params, lod_count, owning_body, sample_displacement, sample_field_flow, sample_field_level, set_effective_flow, set_effective_time, snap_and_transition, surface} 8#import aqua::waves::displace::{far_displacement, far_normal_cross, sample_fft_normal_cross} 9#import bevy_aqua_core::river::river_analytic_displacement 14struct DeformationResult { 15 world_position: vec4<f32>, 16 base_world_position: vec3<f32>, 17 world_normal: vec3<f32>, 19 undisplaced_xz: vec2<f32>, 22 displacement: vec3<f32>, 25 body_params: BodyParams, 29 river_flow: vec4<f32>, 32fn deformation_safe_normalize(value: vec3<f32>, fallback: vec3<f32>) -> vec3<f32> { 33 let length_squared = dot(value, value); 34 let normalized = value * inverseSqrt(max(length_squared, SAFE_LENGTH_SQUARED)); 35 return select(fallback, normalized, length_squared > SAFE_LENGTH_SQUARED); 38fn deform_current(vertex: Vertex, time: f32) -> DeformationResult { 39 var result: DeformationResult; 40 let world_from_local = mesh_functions::get_world_from_local(vertex.instance_index); 41 var world_position = mesh_functions::mesh_position_local_to_world( 43 vec4(vertex.position, 1.0), 45 let tile_lod = min(mesh_functions::get_tag(vertex.instance_index), lod_count() - 1u); 47 var params = field_params.bodies[0]; 48 var vertex_level = 0.0; 49 if field_params.info.x > 0.5 { 50 let field = sample_field_level(world_position.xz); 51 slot = u32(field.y + 0.5); 52 params = owning_body(slot); 53 vertex_level = field.x; 55 let bounded = slot > 0u; 56 begin_invocation(bounded, params); 57 set_effective_time(time); 60 var vertex_river_flow = vec4(0.0, 0.0, 1024.0, 0.0); 62 vertex_river_flow = sample_field_flow(world_position.xz); 64 set_effective_flow(select( 67 bounded && params.flags.y > 0.5, 70 result.body_slot = slot; 71 result.body_params = params; 72 result.body_level = vertex_level; 73 result.bounded = bounded; 74 result.river = bounded && params.flags.y > 0.5; 75 result.river_flow = vertex_river_flow; 80 let transitioned = snap_and_transition( 82 world_from_local[3].xz, 83 cascade_layout.cascades[tile_lod], 85 let river_xz = transitioned.xy; 86 vertex_river_flow = sample_field_flow(river_xz); 87 effective_flow = vertex_river_flow.xy; 88 let analytic = river_analytic_displacement( 94 let height_x = river_analytic_displacement( 95 river_xz + vec2(epsilon, 0.0), 99 let height_z = river_analytic_displacement( 100 river_xz + vec2(0.0, epsilon), 104 let displaced = vec4( 106 vertex_level + analytic.x, 110 result.world_position = displaced; 111 result.base_world_position = world_position.xyz; 112 result.world_normal = deformation_safe_normalize( 114 -(height_x - analytic.x) / epsilon, 116 -(height_z - analytic.x) / epsilon, 120 result.sample_xz = river_xz; 121 result.undisplaced_xz = world_position.xz; 123 result.sample_alpha = 1.0; 124 result.displacement = displaced.xyz - world_position.xyz; 125 result.wave_height = analytic.x; 126 result.river_flow = vertex_river_flow; 131 let transitioned = snap_and_transition( 133 world_from_local[3].xz, 134 cascade_layout.cascades[tile_lod], 136 let displaced = vec4(transitioned.x, vertex_level, transitioned.y, 1.0); 137 result.world_position = displaced; 138 result.base_world_position = displaced.xyz; 139 result.world_normal = vec3(0.0, 1.0, 0.0); 140 result.sample_xz = transitioned.xy; 141 result.undisplaced_xz = world_position.xz; 143 result.sample_alpha = 1.0; 144 result.displacement = vec3(0.0); 145 result.wave_height = 0.0; 149 let transitioned = select( 152 world_from_local[3].xz, 153 cascade_layout.cascades[tile_lod], 155 vec3(world_position.x, world_position.z, 1.0), 158 world_position = vec4( 166 let detail_lod = clamp(cascade_layout.center.z, 0.0, f32(lod_count() - 1u)); 167 let minimum_lod = u32(floor(detail_lod)); 168 let lod = max(tile_lod, minimum_lod); 169 let detail_alpha = fract(detail_lod); 170 var sample_alpha = select(transitioned.z, 1.0, bounded); 171 if tile_lod < minimum_lod { 172 sample_alpha = select(detail_alpha, 1.0, bounded); 173 } else if tile_lod == minimum_lod { 174 sample_alpha = select(max(sample_alpha, detail_alpha), 1.0, bounded); 176 let mode = u32(round(surface.debug.x)); 177 let far_diagnostic = mode == DEBUG_MODE_FAR_TIER; 178 let base_world_position = world_position.xyz; 179 let far_tier = select( 181 far_tier_weight(base_world_position), 182 mode == DEBUG_MODE_BEAUTY || far_diagnostic, 184 var displacement: vec3<f32>; 185 var normal_cross: vec3<f32>; 187 displacement = far_displacement(transitioned.xy); 188 normal_cross = far_normal_cross(transitioned.xy); 190 let near_displacement = sample_displacement(transitioned.xy, lod, sample_alpha); 191 displacement = near_displacement; 192 if surface.reflection.x > 0.5 { 193 normal_cross = sample_fft_normal_cross(transitioned.xy, lod, sample_alpha); 195 let texel_width = cascade_layout.cascades[lod].texel_width; 196 let displacement_x = sample_displacement( 197 transitioned.xy + vec2(texel_width, 0.0), 201 let displacement_z = sample_displacement( 202 transitioned.xy + vec2(0.0, texel_width), 206 let tangent_x = vec3(texel_width, 0.0, 0.0) 207 + displacement_x - near_displacement; 208 let tangent_z = vec3(0.0, 0.0, texel_width) 209 + displacement_z - near_displacement; 210 normal_cross = cross(tangent_z, tangent_x); 212 normal_cross.y = max(normal_cross.y, MIN_NORMAL_Y); 216 far_displacement(transitioned.xy), 219 normal_cross = deformation_safe_normalize( 221 deformation_safe_normalize(normal_cross, vec3(0.0, 1.0, 0.0)), 222 far_normal_cross(transitioned.xy), 229 normal_cross.y = max(normal_cross.y, MIN_NORMAL_Y); 230 world_position = vec4(base_world_position + displacement, world_position.w); 232 result.world_position = world_position; 233 result.base_world_position = base_world_position; 234 result.world_normal = deformation_safe_normalize(normal_cross, vec3(0.0, 1.0, 0.0)); 235 result.sample_xz = transitioned.xy; 236 result.undisplaced_xz = transitioned.xy; 238 result.sample_alpha = sample_alpha; 239 result.displacement = displacement; 240 result.wave_height = displacement.y;