Files
reliquary/plugins/bevy/skills/bevy-0.19/references/camera-rendering.md
T
g4borg c661027d19 🤖 Flesh out bevy-0.19 and bevy-upgrade skills from research
Replace scaffold placeholders with full skill content:
- bevy-0.19: ECS cheat sheet, critical traps table, architecture guide, and 7 reference files
- bevy-upgrade: version migration workflow, transition references for 0.15→0.19, and 3 per-bump reference files
2026-07-07 17:52:10 +02:00

72 lines
3.7 KiB
Markdown

# Camera, Rendering, Assets
## Camera setup
`Camera3d` is a marker with `#[require(...)]` pulling in `Camera`, `DebandDither`, `CameraRenderGraph`, `Projection`, `Tonemapping`, `ColorGrading`, `Exposure`. Spawning bare `Camera3d` yields a working 3D camera.
- **0.18**: `RenderTarget` is a separate required component, no longer a `Camera` field.
- **0.19**: `Hdr` moved from `bevy_render` to `bevy_camera`; screen-space specular transmission fields moved into a `ScreenSpaceTransmission` component.
### Multiple cameras / ordering
- `Camera.order: isize` — higher renders later (on top).
- Every camera with `is_active: true` renders independently.
- Overlay cameras need `ClearColorConfig::None` or they wipe the layer below.
### Camera gotchas
- Default far plane is **1000 units** — anything beyond is silently culled.
- Forward is **-Z**.
- Viewport coordinates are **physical** pixels; cursor position is **logical**.
## Coordinate system
Right-handed:
| Axis | Bevy | GLTF models |
|------|------|-------------|
| Forward | -Z (`Transform::forward()`) | +Z (`Transform::back()`) |
| Up | +Y | +Y |
| Right | +X | -X from camera perspective |
GLTF fix: orient with `look_to(-direction, Vec3::Y)` or treat `transform.back()` as the model's visual forward.
**0.18**: `GltfPlugin`'s `use_model_forward_direction` was replaced by `convert_coordinates` with `rotate_scene_entity` and `rotate_meshes` flags.
## Meshes & materials
- `StandardMaterial` needs **normals**; a mesh without them spawns fine and renders invisible. Programmatic meshes: `.with_computed_flat_normals()` (or insert `ATTRIBUTE_NORMAL`).
- Back-face culling is on by default — wrong winding = invisible faces.
- GLTF scenes spawn via **scene labels** (`"model.glb#Scene0"`), not the raw asset handle.
- Visibility inherits: parents without `Visibility`/`InheritedVisibility` make children invisible — common with hand-built hierarchies around loaded scenes.
- **0.18**: mesh accessors became `try_*` returning `Result<_, MeshAccessError>`; `MaterialPlugin` fields (`prepass_enabled`, `shadows_enabled`) became `Material` trait methods.
- **0.19**: GLTF material loading returns `GltfMaterial` — use the `#Material0/std` label for a `StandardMaterial`. `Assets::get_mut` returns mutation-tracked `AssetMut<A>`. `Scene`/`SceneRoot` renamed to `WorldAsset`/`WorldAssetRoot`.
## Custom material shaders — bind groups
Material bindings are `@group(3)` (0.18+), not `@group(2)`:
| Group | Contents |
|-------|----------|
| 0 | view |
| 1 | globals/lights |
| 2 | mesh (storage buffer) |
| 3 | material (`AsBindGroup`) |
`@group(2)` for material uniforms produces the confusing `Storage class Storage doesn't match the shader Uniform` error — group 2 is the mesh storage buffer.
Import: `use bevy::shader::ShaderRef;` (moved out of `bevy::render::render_resource` in 0.18).
## Lighting
`AmbientLight` split (0.18):
- `GlobalAmbientLight`**resource**, all cameras.
- `AmbientLight`**component** on a camera entity, per-camera.
## Assets
- Assets are not ready right after `asset_server.load()`. Gate on `AssetEvent::LoadedWithDependencies` or `AssetServer::is_loaded_with_dependencies()`.
- **Cache poisoning**: the server dedups by path. A `load_with_settings` that strips data (e.g. `load_meshes = RenderAssetUsages::empty()`) poisons the cache; a later `load()` of the same path returns the stripped asset — invisible models, zero errors. Never mix stripped and rendered loads of the same path in one process; stripped loads belong to headless tools only.
- **0.18**: `LoadContext::path()` returns `AssetPath`, not `Path`; image `reinterpret_*` return `Result`.
- **0.19**: `AssetPath::resolve()`/`resolve_embed()` take `&AssetPath`; the string-taking variants are `resolve_str()`/`resolve_embed_str()`.