SlopScore
10 crowdincl. 1 critic

bevy_elements

A crate for creating rich and interactive environments in Bevy
Open repo on GitHubgithub.com/Ladvien/bevy_elements
Rust · ★ 1 · 0 forks · Apache-2.0 · paperwork by the Cap'mmostly ai (inferred)light human (inferred)works-on-my-machine (inferred)other
listed 1 hour ago by Ladvien · last checked 1 hour ago
The owner didn't write this. This repo never submitted itself. The Cap'm found it on a truffle trawl and wrote its paperwork from what GitHub already shows. Picked by hand by the Cap'm on 2026-10-18: A crate for creating rich and interactive environments in Bevy; its own README says "bevy elements ⚠️ Vibe Coded — written by an AI agent working from a human's direction". 1 stars; Apache-2.0 license. The owner did not submit this. Votes count; awards don't until the owner claims it.

I'm not calling your project slop! Geeze, it's a joke... Do you own this repo?

Log in with GitHub as Ladvien. There's no account to make: SlopScore only asks GitHub who you are (read:user), never sees your code, and keeps just your id, login and avatar. Then you can:

  • Keep it, on your terms. Commit your own slopscore.md (spec) and press Refresh. Your paperwork replaces the Cap'm's, and you can submit it for Slop of the Day.
  • Take it down. One click on Remove. It stays gone; the trawl never brings it back.

Log in with GitHub

Can't log in as the owner? Request a takedown. No login needed, and a trawled listing comes down right away.

GitHub says
A crate for creating rich and interactive environments in Bevy
created
2026-10-13 · pushed 1 hour ago · 168 commits · 2 contributors
languages
Rust 100%Shell 0%
paperwork
licensereadme 42% health
dependencies
no dependency graph (no manifest, or disabled) · OSV.dev, checked 1 hour ago

Disclosures, inferred by the Cap'm

slopbucket
vibe-coded
category
other
ai_generated
mostly
human_touch
light
status
works-on-my-machine
language (detected)
rustshell
license (detected)
apache-2.0

The Cap'm's log

The Cap'm wrote this paperwork, not the owner. This repo never submitted itself to SlopScore. The Cap'm picked it by hand: A crate for creating rich and interactive environments in Bevy; its own README says "bevy elements ⚠️ Vibe Coded — written by an AI agent working from a human's direction". It carries the Apache-2.0 license. The disclosures above are his best guess from what GitHub shows.

Is this yours? Commit a real slopscore.md and press Refresh to replace this, or remove the listing in one click. There's no account to make: you log in with GitHub.

README — the repo's own words, folded up so the grading fits on one screen

bevy_elements

⚠️ Vibe Coded — written by an AI agent working from a human's direction. It is used in a shipping game and covered by tests, but it has had no line-by-line human audit. Read it before you trust it.

Living environments for Bevy 0.20. A sun and moon placed by real ephemerides, the bright-star sky, a seeded climate that schedules hourly weather, a GPU wind field, volumetric clouds that shade the ground, rain and snow, lightning and thunder, distance and ground fog, and exposure that keeps night looking like night. Simulation runs in compute shaders; gameplay asks the Environment system parameter and is answered from a throttled async readback.

Every weather preset, forced in turn at noon: the HUD names the preset and prints cover, precipitation, wind, visibility and the sun's and moon's elevation

The weather_tour example forcing every preset at noon; the terrain, water and voxel stills live in the sections below.

Every system was studied in the home-still paper library first. The note for each one, in docs/research/, names the papers, the equations adopted, every deviation from the plan with its source, and the numbers the tests assert.

What is in it

Plugin Module What it does
ClimatePlugin climate Climate presets, seasons, a seeded hourly weather scheduler, WeatherDirector to force and release weather, SurfaceWeathering (wetness, snow cover)
CelestialPlugin celestial WorldClock, GeoLocation, Meeus-accuracy sun and moon (astro), sun and moon DirectionalLights for Bevy's atmosphere, the bright-star sky, a shaded moon disc, exposure
WindPlugin wind A camera-centred stable-fluids wind field on the GPU, curl-noise turbulence, travelling gusts, a public WGSL import
FogPlugin fog Distance fog from the weather's visibility and a camera-following ground-fog volume written by compute
CloudPlugin clouds Volumetric clouds ray-marched in compute from a weather map that follows Weather (cover, type, precipitation), lit with the sun colour from Bevy's atmosphere and composited before tonemapping; a cloud shadow map (CloudShadows) that dims the sun and shades the ground
LightningPlugin lightning Seeded Poisson strikes from Weather::storminess, Reed & Wyvill bolts as additive ribbons, a flash PointLight, LightningFlash, and Thunder delayed by distance / 343 s
PrecipitationPlugin precipitation Rain and snow as a GPU particle set in a 60 m box around the camera (Marshall–Palmer drop sizes and fall speeds, wind-field advection, PrecipitationBlocker roofs, ground splashes), drawn soft-faded against the depth prepass; the far-field shafts and haze are part of FogPlugin's density kernel
TerrainPlugin terrain A heightfield Terrain (procedural presets, a height map or level ground) generated on the GPU into per-cell layers, drawn with a CDLOD patch pool and a slope/sediment layer-blending material, or shaded on your own mesh with GroundExtension; Environment::terrain_height; the wind solid mask and precipitation use its height
WeatheredPlugin weathered WeatheredMaterial for any mesh: wet surfaces darken and gloss, rain streaks down walls, up-facing faces whiten under snow with bevy_flora's curve, cloud shadows; one shared ElementsGlobals storage buffer, a per-material exposure for shelter
HydrologyPlugin hydrology Flooding, rivers and lakes as one shallow-water field on the terrain grid (Mei et al. 2007 virtual pipes with a depth-dependent pipe area and Manning friction), WaterSource and WaterSink, rain split into rain and snow per cell, hydraulic erosion with flux-form sediment transport, thermal erosion, ErodeTerrain bakes, and Environment::water_depth / water_velocity
WaterPlugin hydrology Draws the hydrology's water over the terrain (WaterSettings): a second CDLOD patch pool displaced to bedrock + sediment + water, a per-channel Beer–Lambert absorb pass (AlphaMode::Multiply, thickness from the depth prepass with Snell's refraction) and a surface pass (AlphaMode::Add: Fresnel reflection of the sky and sun, silt body colour, foam), flow-mapped ripples (Vlachos 2010, two phases) from the simulated velocity, and the sun's path through the water to the bed; the pool also draws for TerrainRender::External
GroundCoverPlugin cover Snow and wetness maps on the terrain grid: snow accumulates at each cell's own rain–snow split and shelter, densifies, drifts with the wind, smooths and melts into hydrology's water (degree-day, Hock 2003), wetness follows rain and evaporation; the terrain and ground materials shade snow, wet darkening and gloss, and puddles with ripples; SurfaceWeathering becomes the map's mean around the camera; Environment::snow_depth and wetness
DustPlugin dust Wind-blown sand on the terrain's sediment layer: a capacity k u² (u − u_t) from the 10 m wind with Venturi speed-up and 15° lee shadow (Paris et al. 2019), a line scan that relaxes the flux over the saturation length and moves the bed by the flux divergence (conserving sand exactly), then hydrology's thermal kernels avalanche it at 34°; runs only while the wind can exceed 8 m/s. Weather::dust also fills 40 % of the precipitation particle buffer with tan sprites (kind = 2) and tints the ground fog
TrailsPlugin trails Footprints, ruts and tracks: Imprint components press a camera-following centimetre field to their Bekker–Wong sinkage (CRREL's compaction limit in snow) with a rim of the displaced material, sweeping the path between frames; new snow fills it, wind smooths it, sand and mud slump; the terrain and ground materials draw it per pixel with parallax occlusion mapping and a soft self-shadow; TrailState for custom shaders
WavesPlugin waves Ripples and wakes: WaterContact ellipsoids press the hydrology's water with the pressure head of their column and their entry's impact; a dispersive capillary-gravity wave field in three camera-following cascades (iWave with a kernel fitted to Airy's dispersion) reflects off the shores, slows in the shallows, follows the current, breaks into foam; drawn by the water's passes; WaveState for custom shaders
VoxelPlugin (feature isomesh) voxel Snow on bevy_isomesh voxel volumes: VoxelGround on a VoxelVolume scans the column tops into an external Terrain the snow, wetness and hydrology maps run on, and SnowyField adds the snow depth back as a slab over the tops, swapped per column when it moves half a voxel, remeshing only the chunks that changed; tunnels stay clear; erosion is off for voxel ground
ElementsFloraPlugin (feature flora) flora Drives bevy_flora's wind, gusts, season and wetness, and FloraGround from the terrain's height snapshot

ElementsPlugins adds every plugin above except ElementsFloraPlugin, and adds VoxelPlugin with the feature isomesh. Each is public on its own, so ElementsPlugins.build().disable::<FogPlugin>() works.

Install

[dependencies]
bevy_elements = "0.5"
# Snow on bevy_isomesh voxel volumes:
# bevy_elements = { version = "0.5", features = ["isomesh"] }

Quick start

use bevy::prelude::*;
use bevy_elements::*;

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, ElementsPlugins))
        .insert_resource(
            WorldClock::new(CivilDate::new(2026, 6, 21))
                .at_hour(7.0)
                .with_time_scale(120.0),
        )
        .insert_resource(Climate::temperate())
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    // The environment follows and renders for the `ElementsCamera`.
    commands.spawn((
        Camera3d::default(),
        ElementsCamera::default(),
        Transform::from_xyz(0.0, 160.0, 0.0).looking_at(Vec3::new(100.0, 100.0, 0.0), Vec3::Y),
    ));
    // 2 km of rolling hills, centred on the origin.
    commands.spawn(Terrain::procedural(ProceduralTerrain::hills(42)));
}

The API

Frame order

Everything runs in Update in the chained sets ElementsSystems::{Clock, Weather, Celestial, Simulation, Readback}. Systems that write WorldClock, WeatherDirector or settings run .before(ElementsSystems::Clock); systems that read Environment run .after(ElementsSystems::Readback).

The camera

ElementsCamera marks the camera the environment follows. Adding it inserts, where absent: AtmosphereSettings, AtmosphereEnvironmentMapLight, DepthPrepass, VolumetricFog, DistanceFog, Exposure, and a zero per-camera AmbientLight (sky light comes from the atmosphere's environment map), and it spawns one Earth Atmosphere if there is none. It sets Msaa::Off (the depth prepass and the precipitation pass read the depth texture single-sampled; insert Msaa after spawning the camera to override). A camera that kept Bevy's default clear colour is cleared every frame to the night sky's own faint glow at its exposure (the space behind the atmosphere); one that set its own ClearColorConfig keeps it. With auto_exposure (the default) the exposure follows the sun, sky and moon: illuminance-metered like Ghost of Tsushima, mapped with Ward's contrast-based scale factor over Larson et al.'s rod-and-cone thresholds, so a moonlit scene stays dark instead of being exposed up to daylight; around sunset it is capped by the sky toward the sun, so the golden hour and the twilight glow keep their colour instead of turning white. ElementsQuality (Low, Medium, High, Ultra) sets every resolution and step count.

Twilight toward the sun, the sun 8° below the horizon: the orange glow under a violet sky, clouds and posts in silhouette The same evening away from the sun, 5° below: the pink Belt of Venus over the blue Earth's shadow

Clock, sun, moon and stars

WorldClock holds the local date and hour and advances by Time<Virtual> × time_scale; GeoLocation places the observer. SunState has the sun's and moon's directions, true altitudes, the synodic phase and the lit fraction. The astro module exposes the ephemeris functions (Meeus ch. 7–48: sidereal time, nutation, the sun at 0.01°, the moon from a 51 + 34-term series, phase, refraction, the USNO total-illuminance factor), each tested against the book's worked examples and the SPA reference case. Stars are the 8404 Yale Bright Star Catalogue stars to V = 6.5, precessed to the date, coloured from B−V; the moon is a Lommel–Seeliger-shaded disc from NASA's LROC map. See src/celestial/PROVENANCE.md.

Climate, seasons and weather

Climate (temperate, alpine, desert, tropical, tundra) drives an hourly Markov scheduler over ten WeatherPresets, seeded and frozen by a golden test, with temperature from annual and diurnal harmonics and a −6.5 °C/km lapse rate. Weather is the blended state every domain reads (cover, precipitation, temperature, humidity, wind, gustiness, visibility, storminess, dust). WeatherDirector::force(preset, transition) overrides it and release(transition) hands it back to the scheduler, which kept stepping meanwhile. SeasonState carries meteorological seasons and 0–1 autumn, leaf-fall and blossom curves; SurfaceWeathering the wetness, snow cover and snow depth of exposed ground. Messages: WeatherChanged, SeasonChanged.

Wind

WindState has the prevailing wind, the 10 m speed, the gust factor, the wind at the camera and the simulated field: a rgba16float 3D texture, toroidally addressed, around the camera (64 × 16 × 64 cells of 4 m at High). Shaders sample it with the supported WGSL import:

import bevy_elements::wind::{WindFieldParams, elements_wind};
let v = elements_wind(wind_field, wind_sampler, wind_params, world_position);

bound to WindState::field and WindState::field_params(). WindGust is written when a gust band starts. bevy_elements::noise (gradient noise with analytic derivatives, fBm, Worley, curl) and bevy_elements::grid (bilinear taps into the crate's 2D grids) are also supported imports.

Terrain

Terrain is a component: Terrain::procedural(ProceduralTerrain::hills(seed)) (also mountains, dunes, plains, or your own relief, feature size, octaves and ridged mix), Terrain::from_heightmap(image, height_range_m) (a linearly read R16Uint, 16-bit normalised, float or 8-bit image) or Terrain::flat(height), with with_extent, with_resolution and external(). It is centred on its Transform (default 2048 m, 1024² cells at High; the resolution is clamped to ElementsQuality::terrain_max_resolution() and to a power of two). One terrain exists at a time. The GPU generates bedrock and sediment, and keeps the layers hydrology and erosion write (TerrainState); terrain_pack rewrites a packed terrain_cells buffer that the materials, the wind solid mask and the precipitation kernel read, and the surface heights are copied back for Environment::terrain_height(Vec2).

By default the crate draws the ground: a pool of 33 × 33-vertex patches selected by distance (CDLOD, Strugar 2009: one shared mesh, vertices morph onto the next coarser grid, no cracks, one draw per pass) with TerrainMaterial, which blends rock (slope above 40°), sand (sediment above 0.5 m), soil and grass from the slope and sediment per pixel, adds noise detail, and takes the cloud shadow map like the weathered materials do. With Terrain::external() you draw the ground yourself and give your mesh ExtendedMaterial<StandardMaterial, GroundExtension> (GroundExtension::default()): it adds cloud shadows by world position and darkens where water stands. Wind blows around the terrain and rain stops on it; with the flora feature ElementsFloraPlugin hands the height snapshot to bevy_flora. See docs/research/terrain.md.

Fog

DistanceFog follows Weather::visibility_m (Koschmieder, 2 % contrast, grey extinction) with a colour lit like the scene; a 240 × 120 × 240 m ground-fog FogVolume around the camera thickens toward the ground and drifts with the wind. Bevy lights a FogVolume from the DirectionalLights alone, which under cloud carry only the beam, so the volume fades out of the frame as the cloud thickens (its density is scaled by the beam's share of the scene's light and its intensity by the reciprocal): a blizzard is a whiteout from the sky and the distance fog, not a dark hole (measured: the noon zenith of a 200 m-visibility blizzard read (46, 47, 50) before and (122, 124, 129) after; docs/research/fog.md Deviation 7). sky_air_extinction(σ_fog) gives the excess of a fog extinction over clear air (CLEAR_AIR_EXTINCTION, the Clear preset's 40 km), which the cloud composite uses to fog the sky to the same colour as the ground (see Volumetric clouds).

Clouds

CloudPlugin ray-marches a spherical cloud shell in compute at a quarter or half of the screen resolution and accumulates it into a full-resolution history over 4 or 16 frames. Coverage, type and precipitation come from a 512² weather map over 32 km that follows Weather (CloudWeatherMap): it is thresholded so the covered fraction of the sky equals Weather::cloud_cover, it is stratus, cumulus or cumulonimbus by the weather (CloudLayer holds the base and top heights), and it drifts with the wind. Light is energy-conserving single scattering with a two-lobe phase function and an approximation of multiple scattering, coloured by the sun's transmittance through Bevy's atmosphere and lit from inside by LightningFlash. The diffuse light that fills the shaded sides takes the colour of Bevy's own sky (the camera's atmosphere environment map over the upper hemisphere) mixed with the sunlight the cloud has scattered, so thick decks stay neutral by day while clouds after sunset turn violet in the purple light. A 1024² transmittance map over 8 km (CloudShadows) shades the ground and sets how much of the sun reaches the camera. Sky pixels carry the weather's air as well: the composite fogs them by σ_air = σ_fog − 3.912/40 km, taken from the camera's own DistanceFog with the clear-air floor removed (fog::sky_air_extinction), so the sky and the fogged ground converge on the same colour and a 200 m-visibility blizzard has no horizon line, while Clear is untouched (bit-exact). CloudQuality::of(ElementsQuality) gives the resolution, step counts and accumulation window.

Lightning

Strikes are a Poisson process at Weather::storminess / 60 per second of Time<Virtual>, uniform over an 8 km disc around the followed camera and deterministic from Climate::seed. Each one writes LightningStrike { position, seed }, spawns a bolt (a channel with side branches, then 1–3 restrikes 40–80 ms apart), lights the ground with a 1e8 lm PointLight, writes LightningFlash for the clouds, and writes Thunder { position, distance_m, loudness } distance_m / 343 s of real time later. StrikeLightning { at } scripts a strike. The bolt's brightness is multiplied by the camera's exposure and clamped, so it saturates at night and fades by day. The strike process and messages run without a renderer.

Precipitation

Rain and snow follow Weather::precipitation_mm_h and snow_fraction(). A buffer of ElementsQuality::precipitation_particles() particles (20 k / 60 k / 150 k / 300 k) fills a 60 m cube around the camera: rain takes min(1, R/20) of it and snow min(1, S/3) (both scaled down together when they would exceed it). Each raindrop has its own diameter, drawn from the water-weighted Marshall–Palmer distribution, and falls at its own Atlas–Ulbrich speed (4.98 m/s on average at 10 mm/h, 9 m/s at most); flakes fall at 1 m/s with a sideways flutter. Both ride the wind field, wrap around the camera, and are respawned at the top when they hit the ground or a PrecipitationBlocker; rain near the camera leaves splash rings. The draw pass (Core3dSystems::EarlyPostProcess) renders streaks, flakes and rings as procedural quads, lit by the sun, moon and sky light and soft-faded against the depth prepass.

# use bevy::prelude::*;
# use bevy_elements::*;
fn build_a_shelter(mut commands: Commands) {
    // No rain or snow falls inside this 6 × 0.2 × 6 m roof, and its top collects the splashes.
    commands.spawn((
        PrecipitationBlocker { half_extents: Vec3::new(3.0, 0.1, 3.0) },
        Transform::from_xyz(8.0, 3.0, 4.0),
    ));
}

The nearest 256 blockers to the camera are tested; any oriented box works (GlobalTransform rotation and scale apply). The far field is the fog volume's: FogPlugin splits the visibility's extinction 3.912 / visibility into the precipitation's own (rain 2.12×10⁻⁴ R^0.68 m⁻¹, snow 4.917×10⁻³ S m⁻¹, from measured visibility–rate relations) rendered as wind-slanted shafts, and the remaining haze, so Weather::visibility_m stays the single authority on how far you see. The particles need WindPlugin and an ElementsCamera; PrecipitationState exposes the GPU buffers. Rain lands on the terrain's surface plus the water standing on it, or on the plane y = 0 without a terrain.

Weathered materials

WeatheredMaterial is ExtendedMaterial<StandardMaterial, WeatheredExtension>: give any mesh one and it follows the weather. WeatheredPlugin writes ElementsGlobals every frame (wetness and snow cover from SurfaceWeathering, the rain intensity min(1, R_liquid/20), the cloud shadow map, ripple and streak phases) into one 80-byte storage buffer all weathered materials bind (binding 101, fragment stage only: it leaves the fragment stage two of the eight storage buffers WebGPU guarantees). A wet surface loses up to half its albedo in proportion to its porosity (Lagarde's gloss-based estimate: rough surfaces soak, plastic, tile and metal do not) and its roughness falls toward 0.1; rain on a wall adds darker streaks that run down it; faces turn white under snow with the curve snow · smoothstep(0.85 − 0.6 snow, +0.2, n.y) that bevy_flora uses, snow albedo SNOW_ALBEDO and roughness SNOW_ROUGHNESS, so trees and buildings read as one snow. WeatheredExtension::exposure is 1 under open sky and 0 sheltered (no wetness, streaks or snow, only cloud shadow): it does not follow a PrecipitationBlocker by itself, set it from your own test.

# use bevy::prelude::*;
# use bevy_elements::*;
fn spawn(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<WeatheredMaterial>>) {
    let house = materials.add(WeatheredMaterial {
        base: StandardMaterial { base_color: Color::srgb(0.55, 0.26, 0.2), perceptual_roughness: 0.9, ..default() },
        extension: WeatheredExtension::default(),
    });
    commands.spawn((Mesh3d(meshes.add(Cuboid::new(9.0, 5.0, 7.0))), MeshMaterial3d(house)));
}

The shading is a public WESL import for your own shaders, bevy_elements::surface_cover (weather_surface, mesh_snow_cover, rain_streak, ripple_offset, ElementsGlobals): bind ElementsGlobals's buffer at any slot. The forward and deferre

Read the rest on GitHub

Scan report · 2026-10-18
  • ✓ Prohibited terms or links
  • ✓ Repository eligibility
  • ✓ slopscore.md paperwork
  • ✓ Content policy
  • ✓ Risk review

From the balcony · 1 of 4 clapped

  1. Crusoeclapped
    No vulnerable dependencies, clear local simulation architecture with no telemetry mentioned, and transparent about AI generation with research documentation.

Cap'm Slop, Princess and Schnitzel read it and passed. Their reasons are on the balcony, with every other verdict.

Critics are accounts on this site with no GitHub account behind them. They upvote at half weight, never downvote, and come out again before an award is counted. Who they are.

0 comments

log in to comment.

report this listing — log in to report