bevy_elements 0.5.3

Living environments for Bevy: sun, moon and stars, climate-driven weather, GPU wind, volumetric clouds, rain, snow and fog, lightning, terrain with hydraulic and thermal erosion, flooding, snow cover, wetness and dust — simulated in compute shaders.
Documentation
// bevy_elements::wind — sample the GPU wind field from any shader.
//
// A supported import for consumers:
//
//     import bevy_elements::wind::{WindFieldParams, elements_wind};
//     @group(3) @binding(110) var wind_field: texture_3d<f32>;
//     @group(3) @binding(111) var wind_sampler: sampler;
//     @group(3) @binding(112) var<uniform> wind_params: WindFieldParams;
//     let v = elements_wind(wind_field, wind_sampler, wind_params, world_position);
//
// Bind `WindState::field` as a filterable 3D float texture with its own (repeating, linear)
// sampler and `WindState::field_params()` as the uniform.

/// Where the wind field sits in the world. Mirrors the Rust `WindFieldParams`.
struct WindFieldParams {
    /// xyz: world position of the field's minimum corner, m. w: unused.
    origin: vec4<f32>,
    /// xyz: field size, m. w: 1 when the field holds simulated data, else 0.
    extent: vec4<f32>,
    /// xyz: prevailing wind at 10 m above ground, m/s, used outside the field. w: unused.
    prevailing: vec4<f32>,
}

/// Wind velocity at `world`, m/s. The field is stored toroidally (a cell's texel is its world
/// cell index modulo the grid), so the texture coordinate is the world position divided by the
/// extent, wrapped; outside the current window the prevailing wind is returned.
fn elements_wind(
    field: texture_3d<f32>,
    s: sampler,
    params: WindFieldParams,
    world: vec3<f32>,
) -> vec3<f32> {
    let local = world - params.origin.xyz;
    let inside = all(local >= vec3<f32>(0.0)) && all(local <= params.extent.xyz);
    if !inside || params.extent.w < 0.5 {
        return params.prevailing.xyz;
    }
    let uvw = fract(world / params.extent.xyz);
    return textureSampleLevel(field, s, uvw, 0.0).xyz;
}