9 prepass_io::{Vertex, VertexOutput, FragmentOutput}, 10 mesh_view_bindings::view, 11 view_transformations::position_world_to_clip, 13#import bevy_aqua_core::deform::{deform_current} 14#import bevy_render::globals::Globals 15#import aqua::cascade::{DEBUG_MODE_BEAUTY, DEBUG_MODE_FAR_TIER, MIN_SAMPLE_WEIGHT, begin_invocation, CascadeLayout, cascade_layout, far_tier_weight, field_params, lod_alpha, lod_count, owning_body, sample_field_flow, sample_field_level, surface, world_to_uv} 16#import bevy_aqua_core::river::river_analytic_displacement 19struct AquaPreviousFrame { 20 previous_layout: CascadeLayout, 25@group(4) @binding(0) var aqua_previous_displacement: texture_2d_array<f32>; 26@group(4) @binding(1) var aqua_previous_sampler: sampler; 27@group(4) @binding(2) var<uniform> aqua_previous_frame: AquaPreviousFrame; 28@group(0) @binding(1) var<uniform> prepass_globals: Globals; 30fn previous_direct_displacement(world_xz: vec2<f32>, lod: u32) -> vec3<f32> { 33 let sampled_xz = world_xz 34 - aqua_previous_frame.flow.xy * aqua_previous_frame.time.x; 35 let previous_cascade = aqua_previous_frame.previous_layout.cascades[lod]; 36 return textureSampleLevel( 37 aqua_previous_displacement, 38 aqua_previous_sampler, 39 world_to_uv(sampled_xz, previous_cascade), 45fn previous_near_displacement( 52 let smaller = cascade_layout.cascades[lod]; 53 let bigger = cascade_layout.cascades[lod + 1u]; 54 let smaller_weight = (1.0 - alpha) * smaller.weight; 55 let bigger_weight = (1.0 - smaller_weight) * bigger.weight; 56 var displacement = vec3(0.0); 57 if smaller_weight > MIN_SAMPLE_WEIGHT { 58 displacement += smaller_weight 59 * previous_direct_displacement(world_xz, lod); 61 if bigger_weight > MIN_SAMPLE_WEIGHT { 62 displacement += bigger_weight 63 * previous_direct_displacement(world_xz, lod + 1u); 68fn previous_far_displacement(world_xz: vec2<f32>) -> vec3<f32> { 69 let outer_lod = lod_count() - 1u; 72 let weight = 1.0 - lod_alpha( 74 cascade_layout.cascades[outer_lod], 76 if weight <= MIN_SAMPLE_WEIGHT { 79 return weight * previous_direct_displacement(world_xz, outer_lod); 83fn vertex(vertex_in: Vertex) -> VertexOutput { 84 var out: VertexOutput; 88 var forward_vertex: forward_io::Vertex; 89 forward_vertex.instance_index = vertex_in.instance_index; 90 forward_vertex.position = vertex_in.position; 92 forward_vertex.uv = vertex_in.uv; 95 forward_vertex.uv_b = vertex_in.uv_b; 98 forward_vertex.color = vertex_in.color; 101 forward_vertex.joint_indices = vertex_in.joint_indices; 102 forward_vertex.joint_weights = vertex_in.joint_weights; 105 forward_vertex.index = vertex_in.index; 107 let deformation = deform_current(forward_vertex, prepass_globals.time); 108 out.world_position = deformation.world_position; 109 out.position = position_world_to_clip(out.world_position.xyz); 110#ifdef MOTION_VECTOR_PREPASS 111 var previous_world_position = out.world_position; 113 if aqua_previous_frame.valid.x >= 0.5 { 114 if deformation.river { 117 let previous_river = river_analytic_displacement( 118 deformation.sample_xz, 119 deformation.river_flow, 120 aqua_previous_frame.time.x, 122 previous_world_position = vec4( 123 deformation.sample_xz.x, 124 deformation.body_level + previous_river.x, 125 deformation.sample_xz.y, 128 } else if !deformation.bounded { 129 let mode = u32(round(surface.debug.x)); 130 let far_diagnostic = mode == DEBUG_MODE_FAR_TIER; 131 let far_tier = select( 133 far_tier_weight(deformation.base_world_position), 134 mode == DEBUG_MODE_BEAUTY || far_diagnostic, 136 var previous_displacement: vec3<f32>; 138 previous_displacement = previous_far_displacement( 139 deformation.sample_xz, 142 previous_displacement = previous_near_displacement( 143 deformation.sample_xz, 145 deformation.sample_alpha, 148 previous_displacement = mix( 149 previous_displacement, 150 previous_far_displacement(deformation.sample_xz), 155 previous_world_position = vec4( 156 deformation.base_world_position + previous_displacement, 162 out.previous_world_position = previous_world_position; 164#ifdef VERTEX_OUTPUT_INSTANCE_INDEX 165 out.instance_index = vertex_in.instance_index; 167#ifdef VISIBILITY_RANGE_DITHER 168 let world_from_local = mesh_functions::get_world_from_local(vertex_in.instance_index); 169 out.visibility_range_dither = mesh_functions::get_visibility_range_dither_level( 170 vertex_in.instance_index, 178fn fragment(in: VertexOutput) -> FragmentOutput { 182 if field_params.info.x > 0.5 { 183 slot = u32(sample_field_level(in.world_position.xz).y + 0.5); 185 let bounded = slot > 0u; 186 if !bounded && field_params.info.y < 0.5 { 189 let params = owning_body(slot); 190 begin_invocation(bounded, params); 192 let distance_to_extent = length( 193 params.extent.xy - view.world_position.xz, 195 if distance_to_extent > surface.far_tier.y { 198 let river_flow = sample_field_flow(in.world_position.xz); 199 if params.flags.y > 0.5 && river_flow.z < 0.0 { 204 var out: FragmentOutput; 205#ifdef MOTION_VECTOR_PREPASS 206 let clip_t = view.unjittered_clip_from_world * in.world_position; 207 let clip = clip_t.xy / clip_t.w; 208 let previous_clip_t = prepass_bindings::previous_view_uniforms.clip_from_world 209 * in.previous_world_position; 210 let saved_previous_clip = previous_clip_t.xy / previous_clip_t.w; 212 let previous_clip = select( 215 aqua_previous_frame.valid.x >= 0.5, 218 let motion = (clip - previous_clip) * vec2(0.5, -0.5); 220 out.motion_vector = select(motion, vec2(0.0), motion == vec2(0.0));