Migrate meshes and materials to required components (#15524)

# Objective

A big step in the migration to required components: meshes and
materials!

## Solution

As per the [selected
proposal](https://hackmd.io/@bevy/required_components/%2Fj9-PnF-2QKK0on1KQ29UWQ):

- Deprecate `MaterialMesh2dBundle`, `MaterialMeshBundle`, and
`PbrBundle`.
- Add `Mesh2d` and `Mesh3d` components, which wrap a `Handle<Mesh>`.
- Add `MeshMaterial2d<M: Material2d>` and `MeshMaterial3d<M: Material>`,
which wrap a `Handle<M>`.
- Meshes *without* a mesh material should be rendered with a default
material. The existence of a material is determined by
`HasMaterial2d`/`HasMaterial3d`, which is required by
`MeshMaterial2d`/`MeshMaterial3d`. This gets around problems with the
generics.

Previously:

```rust
commands.spawn(MaterialMesh2dBundle {
    mesh: meshes.add(Circle::new(100.0)).into(),
    material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
    transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
    ..default()
});
```

Now:

```rust
commands.spawn((
    Mesh2d(meshes.add(Circle::new(100.0))),
    MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
    Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
```

If the mesh material is missing, previously nothing was rendered. Now,
it renders a white default `ColorMaterial` in 2D and a
`StandardMaterial` in 3D (this can be overridden). Below, only every
other entity has a material:

![Näyttökuva 2024-09-29
181746](https://github.com/user-attachments/assets/5c8be029-d2fe-4b8c-ae89-17a72ff82c9a)

![Näyttökuva 2024-09-29
181918](https://github.com/user-attachments/assets/58adbc55-5a1e-4c7d-a2c7-ed456227b909)

Why white? This is still open for discussion, but I think white makes
sense for a *default* material, while *invalid* asset handles pointing
to nothing should have something like a pink material to indicate that
something is broken (I don't handle that in this PR yet). This is kind
of a mix of Godot and Unity: Godot just renders a white material for
non-existent materials, while Unity renders nothing when no materials
exist, but renders pink for invalid materials. I can also change the
default material to pink if that is preferable though.

## Testing

I ran some 2D and 3D examples to test if anything changed visually. I
have not tested all examples or features yet however. If anyone wants to
test more extensively, it would be appreciated!

## Implementation Notes

- The relationship between `bevy_render` and `bevy_pbr` is weird here.
`bevy_render` needs `Mesh3d` for its own systems, but `bevy_pbr` has all
of the material logic, and `bevy_render` doesn't depend on it. I feel
like the two crates should be refactored in some way, but I think that's
out of scope for this PR.
- I didn't migrate meshlets to required components yet. That can
probably be done in a follow-up, as this is already a huge PR.
- It is becoming increasingly clear to me that we really, *really* want
to disallow raw asset handles as components. They caused me a *ton* of
headache here already, and it took me a long time to find every place
that queried for them or inserted them directly on entities, since there
were no compiler errors for it. If we don't remove the `Component`
derive, I expect raw asset handles to be a *huge* footgun for users as
we transition to wrapper components, especially as handles as components
have been the norm so far. I personally consider this to be a blocker
for 0.15: we need to migrate to wrapper components for asset handles
everywhere, and remove the `Component` derive. Also see
https://github.com/bevyengine/bevy/issues/14124.

---

## Migration Guide

Asset handles for meshes and mesh materials must now be wrapped in the
`Mesh2d` and `MeshMaterial2d` or `Mesh3d` and `MeshMaterial3d`
components for 2D and 3D respectively. Raw handles as components no
longer render meshes.

Additionally, `MaterialMesh2dBundle`, `MaterialMeshBundle`, and
`PbrBundle` have been deprecated. Instead, use the mesh and material
components directly.

Previously:

```rust
commands.spawn(MaterialMesh2dBundle {
    mesh: meshes.add(Circle::new(100.0)).into(),
    material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
    transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
    ..default()
});
```

Now:

```rust
commands.spawn((
    Mesh2d(meshes.add(Circle::new(100.0))),
    MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
    Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
```

If the mesh material is missing, a white default material is now used.
Previously, nothing was rendered if the material was missing.

The `WithMesh2d` and `WithMesh3d` query filter type aliases have also
been removed. Simply use `With<Mesh2d>` or `With<Mesh3d>`.

---------

Co-authored-by: Tim Blackbird <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
Joona Aalto 2024-10-02 00:33:17 +03:00 committed by GitHub
parent 0fe17b8b30
commit 54006b107b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
144 changed files with 2044 additions and 2088 deletions

View file

@ -432,6 +432,6 @@ jobs:
echo -e "$errors"
echo " Avoid importing internal Bevy crates, they should not be used directly"
echo " Fix the issue by replacing 'bevy_*' with 'bevy'"
echo " Example: 'use bevy::sprite::MaterialMesh2dBundle;' instead of 'bevy_internal::sprite::MaterialMesh2dBundle;'"
echo " Example: 'use bevy::sprite::Mesh2d;' instead of 'bevy_internal::sprite::Mesh2d;'"
exit 1
fi

View file

@ -17,7 +17,8 @@ use bevy_ecs::{
use bevy_hierarchy::{BuildChildren, ChildBuild, WorldChildBuilder};
use bevy_math::{Affine2, Mat4, Vec3};
use bevy_pbr::{
DirectionalLight, PbrBundle, PointLight, SpotLight, StandardMaterial, UvChannel, MAX_JOINTS,
DirectionalLight, MeshMaterial3d, PointLight, SpotLight, StandardMaterial, UvChannel,
MAX_JOINTS,
};
use bevy_render::{
alpha::AlphaMode,
@ -25,7 +26,7 @@ use bevy_render::{
mesh::{
morph::{MeshMorphWeights, MorphAttributes, MorphTargetImage, MorphWeights},
skinning::{SkinnedMesh, SkinnedMeshInverseBindposes},
Indices, Mesh, MeshVertexAttribute, VertexAttributeValues,
Indices, Mesh, Mesh3d, MeshVertexAttribute, VertexAttributeValues,
},
prelude::SpatialBundle,
primitives::Aabb,
@ -1456,12 +1457,13 @@ fn load_node(
};
let bounds = primitive.bounding_box();
let mut mesh_entity = parent.spawn(PbrBundle {
let mut mesh_entity = parent.spawn((
// TODO: handle missing label handle errors here?
mesh: load_context.get_label_handle(primitive_label.to_string()),
material: load_context.get_label_handle(&material_label),
..Default::default()
});
Mesh3d(load_context.get_label_handle(primitive_label.to_string())),
MeshMaterial3d::<StandardMaterial>(
load_context.get_label_handle(&material_label),
),
));
let target_count = primitive.morph_targets().len();
if target_count != 0 {

View file

@ -1,10 +1,9 @@
#![expect(deprecated)]
use crate::{
CascadeShadowConfig, Cascades, DirectionalLight, Material, PointLight, SpotLight,
StandardMaterial,
CascadeShadowConfig, Cascades, DirectionalLight, Material, MeshMaterial3d, PointLight,
SpotLight, StandardMaterial,
};
use bevy_asset::Handle;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
bundle::Bundle,
@ -14,21 +13,29 @@ use bevy_ecs::{
};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{
mesh::Mesh,
mesh::Mesh3d,
primitives::{CascadesFrusta, CubemapFrusta, Frustum},
view::{InheritedVisibility, ViewVisibility, Visibility},
world_sync::SyncToRenderWorld,
};
use bevy_transform::components::{GlobalTransform, Transform};
/// A component bundle for PBR entities with a [`Mesh`] and a [`StandardMaterial`].
/// A component bundle for PBR entities with a [`Mesh3d`] and a [`MeshMaterial3d<StandardMaterial>`].
#[deprecated(
since = "0.15.0",
note = "Use the `Mesh3d` and `MeshMaterial3d` components instead. Inserting them will now also insert the other components required by them automatically."
)]
pub type PbrBundle = MaterialMeshBundle<StandardMaterial>;
/// A component bundle for entities with a [`Mesh`] and a [`Material`].
/// A component bundle for entities with a [`Mesh3d`] and a [`MeshMaterial3d`].
#[derive(Bundle, Clone)]
#[deprecated(
since = "0.15.0",
note = "Use the `Mesh3d` and `MeshMaterial3d` components instead. Inserting them will now also insert the other components required by them automatically."
)]
pub struct MaterialMeshBundle<M: Material> {
pub mesh: Handle<Mesh>,
pub material: Handle<M>,
pub mesh: Mesh3d,
pub material: MeshMaterial3d<M>,
pub transform: Transform,
pub global_transform: GlobalTransform,
/// User indication of whether an entity is visible

View file

@ -34,6 +34,7 @@ mod light;
mod light_probe;
mod lightmap;
mod material;
mod mesh_material;
mod parallax;
mod pbr_material;
mod prepass;
@ -53,6 +54,7 @@ pub use light::*;
pub use light_probe::*;
pub use lightmap::*;
pub use material::*;
pub use mesh_material::*;
pub use parallax::*;
pub use pbr_material::*;
pub use prepass::*;
@ -83,6 +85,7 @@ pub mod prelude {
LightProbe,
},
material::{Material, MaterialPlugin},
mesh_material::MeshMaterial3d,
parallax::ParallaxMappingMethod,
pbr_material::StandardMaterial,
ssao::ScreenSpaceAmbientOcclusionPlugin,
@ -411,13 +414,13 @@ impl Plugin for PbrPlugin {
app.add_plugins(DeferredPbrLightingPlugin);
}
// Initialize the default material.
app.world_mut()
.resource_mut::<Assets<StandardMaterial>>()
.insert(
&Handle::<StandardMaterial>::default(),
StandardMaterial {
base_color: Color::srgb(1.0, 0.0, 0.5),
unlit: true,
base_color: Color::WHITE,
..Default::default()
},
);
@ -428,7 +431,14 @@ impl Plugin for PbrPlugin {
// Extract the required data from the main world
render_app
.add_systems(ExtractSchedule, (extract_clusters, extract_lights))
.add_systems(
ExtractSchedule,
(
extract_clusters,
extract_lights,
extract_default_materials.after(clear_material_instances::<StandardMaterial>),
),
)
.add_systems(
Render,
(

View file

@ -7,7 +7,7 @@ use bevy_render::{
camera::{Camera, CameraProjection},
extract_component::ExtractComponent,
extract_resource::ExtractResource,
mesh::Mesh,
mesh::Mesh3d,
primitives::{Aabb, CascadesFrusta, CubemapFrusta, Frustum, Sphere},
view::{
InheritedVisibility, NoFrustumCulling, RenderLayers, ViewVisibility, VisibilityRange,
@ -440,11 +440,11 @@ fn calculate_cascade(
texel_size: cascade_texel_size,
}
}
/// Add this component to make a [`Mesh`] not cast shadows.
/// Add this component to make a [`Mesh3d`] not cast shadows.
#[derive(Debug, Component, Reflect, Default)]
#[reflect(Component, Default, Debug)]
pub struct NotShadowCaster;
/// Add this component to make a [`Mesh`] not receive shadows.
/// Add this component to make a [`Mesh3d`] not receive shadows.
///
/// **Note:** If you're using diffuse transmission, setting [`NotShadowReceiver`] will
/// cause both “regular” shadows as well as diffusely transmitted shadows to be disabled,
@ -452,7 +452,7 @@ pub struct NotShadowCaster;
#[derive(Debug, Component, Reflect, Default)]
#[reflect(Component, Default, Debug)]
pub struct NotShadowReceiver;
/// Add this component to make a [`Mesh`] using a PBR material with [`diffuse_transmission`](crate::pbr_material::StandardMaterial::diffuse_transmission)`> 0.0`
/// Add this component to make a [`Mesh3d`] using a PBR material with [`diffuse_transmission`](crate::pbr_material::StandardMaterial::diffuse_transmission)`> 0.0`
/// receive shadows on its diffuse transmission lobe. (i.e. its “backside”)
///
/// Not enabled by default, as it requires carefully setting up [`thickness`](crate::pbr_material::StandardMaterial::thickness)
@ -697,7 +697,7 @@ pub fn check_dir_light_mesh_visibility(
(
Without<NotShadowCaster>,
Without<DirectionalLight>,
With<Handle<Mesh>>,
With<Mesh3d>,
),
>,
visible_entity_ranges: Option<Res<VisibleEntityRanges>>,
@ -866,7 +866,7 @@ pub fn check_point_light_mesh_visibility(
(
Without<NotShadowCaster>,
Without<DirectionalLight>,
With<Handle<Mesh>>,
With<Mesh3d>,
),
>,
visible_entity_ranges: Option<Res<VisibleEntityRanges>>,

View file

@ -6,10 +6,10 @@
//! with an addon like [The Lightmapper]. The tools in the [`bevy-baked-gi`]
//! project support other lightmap baking methods.
//!
//! When a [`Lightmap`] component is added to an entity with a [`Mesh`] and a
//! [`StandardMaterial`](crate::StandardMaterial), Bevy applies the lightmap when rendering. The brightness
//! When a [`Lightmap`] component is added to an entity with a [`Mesh3d`] and a
//! [`MeshMaterial3d<StandardMaterial>`], Bevy applies the lightmap when rendering. The brightness
//! of the lightmap may be controlled with the `lightmap_exposure` field on
//! `StandardMaterial`.
//! [`StandardMaterial`].
//!
//! During the rendering extraction phase, we extract all lightmaps into the
//! [`RenderLightmaps`] table, which lives in the render world. Mesh bindgroup
@ -25,7 +25,9 @@
//! appropriately.
//!
//! [The Lightmapper]: https://github.com/Naxela/The_Lightmapper
//!
//! [`Mesh3d`]: bevy_render::mesh::Mesh3d
//! [`MeshMaterial3d<StandardMaterial>`]: crate::StandardMaterial
//! [`StandardMaterial`]: crate::StandardMaterial
//! [`bevy-baked-gi`]: https://github.com/pcwalton/bevy-baked-gi
use bevy_app::{App, Plugin};
@ -61,10 +63,10 @@ pub struct LightmapPlugin;
/// A component that applies baked indirect diffuse global illumination from a
/// lightmap.
///
/// When assigned to an entity that contains a [`Mesh`] and a
/// [`StandardMaterial`](crate::StandardMaterial), if the mesh has a second UV
/// layer ([`ATTRIBUTE_UV_1`](bevy_render::mesh::Mesh::ATTRIBUTE_UV_1)), then
/// the lightmap will render using those UVs.
/// When assigned to an entity that contains a [`Mesh3d`](bevy_render::mesh::Mesh3d) and a
/// [`MeshMaterial3d<StandardMaterial>`](crate::StandardMaterial), if the mesh
/// has a second UV layer ([`ATTRIBUTE_UV_1`](bevy_render::mesh::Mesh::ATTRIBUTE_UV_1)),
/// then the lightmap will render using those UVs.
#[derive(Component, Clone, Reflect)]
#[reflect(Component, Default)]
pub struct Lightmap {

View file

@ -24,14 +24,15 @@ use bevy_reflect::std_traits::ReflectDefault;
use bevy_reflect::Reflect;
use bevy_render::{
camera::TemporalJitter,
extract_instances::{ExtractInstancesPlugin, ExtractedInstances},
extract_instances::ExtractedInstances,
extract_resource::ExtractResource,
mesh::{MeshVertexBufferLayoutRef, RenderMesh},
mesh::{Mesh3d, MeshVertexBufferLayoutRef, RenderMesh},
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
render_phase::*,
render_resource::*,
renderer::RenderDevice,
view::{ExtractedView, Msaa, RenderVisibilityRanges, VisibleEntities, WithMesh},
view::{ExtractedView, Msaa, RenderVisibilityRanges, ViewVisibility, VisibleEntities},
Extract,
};
use bevy_utils::tracing::error;
use core::{
@ -43,26 +44,28 @@ use core::{
use self::{irradiance_volume::IrradianceVolume, prelude::EnvironmentMapLight};
/// Materials are used alongside [`MaterialPlugin`] and [`MaterialMeshBundle`]
/// Materials are used alongside [`MaterialPlugin`], [`Mesh3d`], and [`MeshMaterial3d`]
/// to spawn entities that are rendered with a specific [`Material`] type. They serve as an easy to use high level
/// way to render [`Mesh`](bevy_render::mesh::Mesh) entities with custom shader logic.
/// way to render [`Mesh3d`] entities with custom shader logic.
///
/// Materials must implement [`AsBindGroup`] to define how data will be transferred to the GPU and bound in shaders.
/// [`AsBindGroup`] can be derived, which makes generating bindings straightforward. See the [`AsBindGroup`] docs for details.
///
/// # Example
///
/// Here is a simple Material implementation. The [`AsBindGroup`] derive has many features. To see what else is available,
/// Here is a simple [`Material`] implementation. The [`AsBindGroup`] derive has many features. To see what else is available,
/// check out the [`AsBindGroup`] documentation.
///
/// ```
/// # use bevy_pbr::{Material, MaterialMeshBundle};
/// # use bevy_pbr::{Material, MeshMaterial3d};
/// # use bevy_ecs::prelude::*;
/// # use bevy_reflect::TypePath;
/// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image};
/// # use bevy_render::{mesh::{Mesh, Mesh3d}, render_resource::{AsBindGroup, ShaderRef}, texture::Image};
/// # use bevy_color::LinearRgba;
/// # use bevy_color::palettes::basic::RED;
/// # use bevy_asset::{Handle, AssetServer, Assets, Asset};
///
/// # use bevy_math::primitives::Capsule3d;
/// #
/// #[derive(AsBindGroup, Debug, Clone, Asset, TypePath)]
/// pub struct CustomMaterial {
/// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to
@ -84,17 +87,23 @@ use self::{irradiance_volume::IrradianceVolume, prelude::EnvironmentMapLight};
/// }
/// }
///
/// // Spawn an entity using `CustomMaterial`.
/// fn setup(mut commands: Commands, mut materials: ResMut<Assets<CustomMaterial>>, asset_server: Res<AssetServer>) {
/// commands.spawn(MaterialMeshBundle {
/// material: materials.add(CustomMaterial {
/// // Spawn an entity with a mesh using `CustomMaterial`.
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<CustomMaterial>>,
/// asset_server: Res<AssetServer>
/// ) {
/// commands.spawn((
/// Mesh3d(meshes.add(Capsule3d::default())),
/// MeshMaterial3d(materials.add(CustomMaterial {
/// color: RED.into(),
/// color_texture: asset_server.load("some_image.png"),
/// }),
/// ..Default::default()
/// });
/// })),
/// ));
/// }
/// ```
///
/// In WGSL shaders, the material's binding would look like this:
///
/// ```wgsl
@ -258,20 +267,25 @@ where
M::Data: PartialEq + Eq + Hash + Clone,
{
fn build(&self, app: &mut App) {
app.init_asset::<M>().add_plugins((
ExtractInstancesPlugin::<AssetId<M>>::extract_visible(),
RenderAssetPlugin::<PreparedMaterial<M>>::default(),
));
app.init_asset::<M>()
.register_type::<MeshMaterial3d<M>>()
.register_type::<HasMaterial3d>()
.add_plugins(RenderAssetPlugin::<PreparedMaterial<M>>::default());
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
.init_resource::<DrawFunctions<Shadow>>()
.init_resource::<ExtractedInstances<AssetId<M>>>()
.add_render_command::<Shadow, DrawPrepass<M>>()
.add_render_command::<Transmissive3d, DrawMaterial<M>>()
.add_render_command::<Transparent3d, DrawMaterial<M>>()
.add_render_command::<Opaque3d, DrawMaterial<M>>()
.add_render_command::<AlphaMask3d, DrawMaterial<M>>()
.init_resource::<SpecializedMeshPipelines<MaterialPipeline<M>>>()
.add_systems(
ExtractSchedule,
(clear_material_instances::<M>, extract_mesh_materials::<M>).chain(),
)
.add_systems(
Render,
queue_material_meshes::<M>
@ -527,6 +541,35 @@ pub const fn screen_space_specular_transmission_pipeline_key(
}
}
pub(super) fn clear_material_instances<M: Material>(
mut material_instances: ResMut<RenderMaterialInstances<M>>,
) {
material_instances.clear();
}
fn extract_mesh_materials<M: Material>(
mut material_instances: ResMut<RenderMaterialInstances<M>>,
query: Extract<Query<(Entity, &ViewVisibility, &MeshMaterial3d<M>), With<Mesh3d>>>,
) {
for (entity, view_visibility, material) in &query {
if view_visibility.get() {
material_instances.insert(entity, material.id());
}
}
}
/// Extracts default materials for 3D meshes with no [`MeshMaterial3d`].
pub(super) fn extract_default_materials(
mut material_instances: ResMut<RenderMaterialInstances<StandardMaterial>>,
query: Extract<Query<(Entity, &ViewVisibility), (With<Mesh3d>, Without<HasMaterial3d>)>>,
) {
for (entity, view_visibility) in &query {
if view_visibility.get() {
material_instances.insert(entity, AssetId::default());
}
}
}
/// For each view, iterates over all the meshes visible from that view and adds
/// them to [`BinnedRenderPhase`]s or [`SortedRenderPhase`]s as appropriate.
#[allow(clippy::too_many_arguments)]
@ -686,7 +729,7 @@ pub fn queue_material_meshes<M: Material>(
}
let rangefinder = view.rangefinder3d();
for visible_entity in visible_entities.iter::<WithMesh>() {
for visible_entity in visible_entities.iter::<With<Mesh3d>>() {
let Some(material_asset_id) = render_material_instances.get(visible_entity) else {
continue;
};

View file

@ -0,0 +1,106 @@
use crate::Material;
use bevy_asset::{AssetId, Handle};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{component::Component, reflect::ReflectComponent};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
/// A [material](Material) for a [`Mesh3d`].
///
/// See [`Material`] for general information about 3D materials and how to implement your own materials.
///
/// [`Mesh3d`]: bevy_render::mesh::Mesh3d
///
/// # Example
///
/// ```
/// # use bevy_pbr::{Material, MeshMaterial3d, StandardMaterial};
/// # use bevy_ecs::prelude::*;
/// # use bevy_render::mesh::{Mesh, Mesh3d};
/// # use bevy_color::palettes::basic::RED;
/// # use bevy_asset::Assets;
/// # use bevy_math::primitives::Capsule3d;
/// #
/// // Spawn an entity with a mesh using `StandardMaterial`.
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<StandardMaterial>>,
/// ) {
/// commands.spawn((
/// Mesh3d(meshes.add(Capsule3d::default())),
/// MeshMaterial3d(materials.add(StandardMaterial {
/// base_color: RED.into(),
/// ..Default::default()
/// })),
/// ));
/// }
/// ```
///
/// ## Default Material
///
/// Meshes without a [`MeshMaterial3d`] are rendered with a default [`StandardMaterial`].
/// This material can be overridden by inserting a custom material for the default asset handle.
///
/// ```
/// # use bevy_pbr::{Material, MeshMaterial3d, StandardMaterial};
/// # use bevy_ecs::prelude::*;
/// # use bevy_render::mesh::{Mesh, Mesh3d};
/// # use bevy_color::Color;
/// # use bevy_asset::{Assets, Handle};
/// # use bevy_math::primitives::Capsule3d;
/// #
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<StandardMaterial>>,
/// ) {
/// // Optional: Insert a custom default material.
/// materials.insert(
/// &Handle::<StandardMaterial>::default(),
/// StandardMaterial::from(Color::srgb(1.0, 0.0, 1.0)),
/// );
///
/// // Spawn a capsule with no material.
/// // The mesh will be rendered with the default material.
/// commands.spawn(Mesh3d(meshes.add(Capsule3d::default())));
/// }
/// ```
///
/// [`StandardMaterial`]: crate::StandardMaterial
#[derive(Component, Clone, Debug, Deref, DerefMut, Reflect, PartialEq, Eq)]
#[reflect(Component, Default)]
#[require(HasMaterial3d)]
pub struct MeshMaterial3d<M: Material>(pub Handle<M>);
impl<M: Material> Default for MeshMaterial3d<M> {
fn default() -> Self {
Self(Handle::default())
}
}
impl<M: Material> From<Handle<M>> for MeshMaterial3d<M> {
fn from(handle: Handle<M>) -> Self {
Self(handle)
}
}
impl<M: Material> From<MeshMaterial3d<M>> for AssetId<M> {
fn from(material: MeshMaterial3d<M>) -> Self {
material.id()
}
}
impl<M: Material> From<&MeshMaterial3d<M>> for AssetId<M> {
fn from(material: &MeshMaterial3d<M>) -> Self {
material.id()
}
}
/// A component that marks an entity as having a [`MeshMaterial3d`].
/// [`Mesh3d`] entities without this component are rendered with a [default material].
///
/// [`Mesh3d`]: bevy_render::mesh::Mesh3d
/// [default material]: crate::MeshMaterial3d#default-material
#[derive(Component, Clone, Debug, Default, Reflect)]
#[reflect(Component, Default)]
pub struct HasMaterial3d;

View file

@ -1,9 +1,8 @@
mod prepass_bindings;
use bevy_render::{
mesh::{MeshVertexBufferLayoutRef, RenderMesh},
mesh::{Mesh3d, MeshVertexBufferLayoutRef, RenderMesh},
render_resource::binding_types::uniform_buffer,
view::WithMesh,
world_sync::RenderEntity,
};
pub use prepass_bindings::*;
@ -220,9 +219,9 @@ pub fn update_previous_view_data(
pub struct PreviousGlobalTransform(pub Affine3A);
#[cfg(not(feature = "meshlet"))]
type PreviousMeshFilter = With<Handle<Mesh>>;
type PreviousMeshFilter = With<Mesh3d>;
#[cfg(feature = "meshlet")]
type PreviousMeshFilter = Or<(With<Handle<Mesh>>, With<Handle<MeshletMesh>>)>;
type PreviousMeshFilter = Or<(With<Mesh3d>, With<Handle<MeshletMesh>>)>;
pub fn update_mesh_previous_global_transforms(
mut commands: Commands,
@ -766,7 +765,7 @@ pub fn queue_prepass_material_meshes<M: Material>(
view_key |= MeshPipelineKey::MOTION_VECTOR_PREPASS;
}
for visible_entity in visible_entities.iter::<WithMesh>() {
for visible_entity in visible_entities.iter::<With<Mesh3d>>() {
let Some(material_asset_id) = render_material_instances.get(visible_entity) else {
continue;
};

View file

@ -567,7 +567,7 @@ pub struct RenderMeshInstanceGpuQueues(Parallel<RenderMeshInstanceGpuQueue>);
impl RenderMeshInstanceShared {
fn from_components(
previous_transform: Option<&PreviousGlobalTransform>,
handle: &Handle<Mesh>,
mesh: &Mesh3d,
not_shadow_caster: bool,
no_automatic_batching: bool,
) -> Self {
@ -583,8 +583,7 @@ impl RenderMeshInstanceShared {
);
RenderMeshInstanceShared {
mesh_asset_id: handle.id(),
mesh_asset_id: mesh.id(),
flags: mesh_instance_flags,
material_bind_group_id: AtomicMaterialBindGroupId::default(),
}
@ -870,7 +869,7 @@ pub fn extract_meshes_for_cpu_building(
&ViewVisibility,
&GlobalTransform,
Option<&PreviousGlobalTransform>,
&Handle<Mesh>,
&Mesh3d,
Has<NotShadowReceiver>,
Has<TransmittedShadowReceiver>,
Has<NotShadowCaster>,
@ -887,7 +886,7 @@ pub fn extract_meshes_for_cpu_building(
view_visibility,
transform,
previous_transform,
handle,
mesh,
not_shadow_receiver,
transmitted_receiver,
not_shadow_caster,
@ -912,7 +911,7 @@ pub fn extract_meshes_for_cpu_building(
let shared = RenderMeshInstanceShared::from_components(
previous_transform,
handle,
mesh,
not_shadow_caster,
no_automatic_batching,
);
@ -969,7 +968,7 @@ pub fn extract_meshes_for_gpu_building(
Option<&PreviousGlobalTransform>,
Option<&Lightmap>,
Option<&Aabb>,
&Handle<Mesh>,
&Mesh3d,
Has<NotShadowReceiver>,
Has<TransmittedShadowReceiver>,
Has<NotShadowCaster>,
@ -1003,7 +1002,7 @@ pub fn extract_meshes_for_gpu_building(
previous_transform,
lightmap,
aabb,
handle,
mesh,
not_shadow_receiver,
transmitted_receiver,
not_shadow_caster,
@ -1028,7 +1027,7 @@ pub fn extract_meshes_for_gpu_building(
let shared = RenderMeshInstanceShared::from_components(
previous_transform,
handle,
mesh,
not_shadow_caster,
no_automatic_batching,
);

View file

@ -1,11 +1,13 @@
use crate::{Material, MaterialPipeline, MaterialPipelineKey, MaterialPlugin};
use crate::{Material, MaterialPipeline, MaterialPipelineKey, MaterialPlugin, MeshMaterial3d};
use bevy_app::{Plugin, Startup, Update};
use bevy_asset::{load_internal_asset, Asset, Assets, Handle};
use bevy_color::{Color, LinearRgba};
use bevy_ecs::prelude::*;
use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
use bevy_render::{
extract_resource::ExtractResource, mesh::MeshVertexBufferLayoutRef, prelude::*,
extract_resource::ExtractResource,
mesh::{Mesh3d, MeshVertexBufferLayoutRef},
prelude::*,
render_resource::*,
};
@ -129,12 +131,12 @@ fn global_color_changed(
fn wireframe_color_changed(
mut materials: ResMut<Assets<WireframeMaterial>>,
mut colors_changed: Query<
(&mut Handle<WireframeMaterial>, &WireframeColor),
(&mut MeshMaterial3d<WireframeMaterial>, &WireframeColor),
(With<Wireframe>, Changed<WireframeColor>),
>,
) {
for (mut handle, wireframe_color) in &mut colors_changed {
*handle = materials.add(WireframeMaterial {
handle.0 = materials.add(WireframeMaterial {
color: wireframe_color.color.into(),
});
}
@ -147,27 +149,27 @@ fn apply_wireframe_material(
mut materials: ResMut<Assets<WireframeMaterial>>,
wireframes: Query<
(Entity, Option<&WireframeColor>),
(With<Wireframe>, Without<Handle<WireframeMaterial>>),
(With<Wireframe>, Without<MeshMaterial3d<WireframeMaterial>>),
>,
no_wireframes: Query<Entity, (With<NoWireframe>, With<Handle<WireframeMaterial>>)>,
no_wireframes: Query<Entity, (With<NoWireframe>, With<MeshMaterial3d<WireframeMaterial>>)>,
mut removed_wireframes: RemovedComponents<Wireframe>,
global_material: Res<GlobalWireframeMaterial>,
) {
for e in removed_wireframes.read().chain(no_wireframes.iter()) {
if let Some(commands) = commands.get_entity(e) {
commands.remove::<Handle<WireframeMaterial>>();
commands.remove::<MeshMaterial3d<WireframeMaterial>>();
}
}
let mut material_to_spawn = vec![];
for (e, maybe_color) in &wireframes {
let material = get_wireframe_material(maybe_color, &mut materials, &global_material);
material_to_spawn.push((e, material));
material_to_spawn.push((e, MeshMaterial3d(material)));
}
commands.insert_or_spawn_batch(material_to_spawn);
}
type WireframeFilter = (With<Handle<Mesh>>, Without<Wireframe>, Without<NoWireframe>);
type WireframeFilter = (With<Mesh3d>, Without<Wireframe>, Without<NoWireframe>);
/// Applies or removes a wireframe material on any mesh without a [`Wireframe`] or [`NoWireframe`] component.
fn apply_global_wireframe_material(
@ -175,9 +177,12 @@ fn apply_global_wireframe_material(
config: Res<WireframeConfig>,
meshes_without_material: Query<
(Entity, Option<&WireframeColor>),
(WireframeFilter, Without<Handle<WireframeMaterial>>),
(WireframeFilter, Without<MeshMaterial3d<WireframeMaterial>>),
>,
meshes_with_global_material: Query<
Entity,
(WireframeFilter, With<MeshMaterial3d<WireframeMaterial>>),
>,
meshes_with_global_material: Query<Entity, (WireframeFilter, With<Handle<WireframeMaterial>>)>,
global_material: Res<GlobalWireframeMaterial>,
mut materials: ResMut<Assets<WireframeMaterial>>,
) {
@ -187,12 +192,14 @@ fn apply_global_wireframe_material(
let material = get_wireframe_material(maybe_color, &mut materials, &global_material);
// We only add the material handle but not the Wireframe component
// This makes it easy to detect which mesh is using the global material and which ones are user specified
material_to_spawn.push((e, material));
material_to_spawn.push((e, MeshMaterial3d(material)));
}
commands.insert_or_spawn_batch(material_to_spawn);
} else {
for e in &meshes_with_global_material {
commands.entity(e).remove::<Handle<WireframeMaterial>>();
commands
.entity(e)
.remove::<MeshMaterial3d<WireframeMaterial>>();
}
}
}

View file

@ -54,7 +54,10 @@ pub mod prelude {
Camera, ClearColor, ClearColorConfig, OrthographicProjection, PerspectiveProjection,
Projection,
},
mesh::{morph::MorphWeights, primitives::MeshBuilder, primitives::Meshable, Mesh},
mesh::{
morph::MorphWeights, primitives::MeshBuilder, primitives::Meshable, Mesh, Mesh2d,
Mesh3d,
},
render_resource::Shader,
spatial_bundle::SpatialBundle,
texture::{image_texture_conversion::IntoDynamicImageError, Image, ImagePlugin},

View file

@ -0,0 +1,115 @@
use crate::{mesh::Mesh, view::Visibility};
use bevy_asset::{AssetId, Handle};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{component::Component, reflect::ReflectComponent};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_transform::components::Transform;
/// A component for rendering 2D meshes, typically with a [`MeshMaterial2d`] using a [`ColorMaterial`].
///
/// Meshes without a [`MeshMaterial2d`] will be rendered with a [default material].
///
/// [`MeshMaterial2d`]: <https://docs.rs/bevy/latest/bevy/sprite/struct.MeshMaterial2d.html>
/// [`ColorMaterial`]: <https://docs.rs/bevy/latest/bevy/sprite/struct.ColorMaterial.html>
/// [default material]: <https://docs.rs/bevy/latest/bevy/sprite/struct.MeshMaterial2d.html#default-material>
///
/// # Example
///
/// ```ignore
/// # use bevy_sprite::{ColorMaterial, Mesh2d, MeshMaterial2d};
/// # use bevy_ecs::prelude::*;
/// # use bevy_render::mesh::Mesh;
/// # use bevy_color::palettes::basic::RED;
/// # use bevy_asset::Assets;
/// # use bevy_math::primitives::Circle;
/// #
/// // Spawn an entity with a mesh using `ColorMaterial`.
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<ColorMaterial>>,
/// ) {
/// commands.spawn((
/// Mesh2d(meshes.add(Circle::new(50.0))),
/// MeshMaterial2d(materials.add(ColorMaterial::from_color(RED))),
/// ));
/// }
/// ```
#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq)]
#[reflect(Component, Default)]
#[require(Transform, Visibility)]
pub struct Mesh2d(pub Handle<Mesh>);
impl From<Handle<Mesh>> for Mesh2d {
fn from(handle: Handle<Mesh>) -> Self {
Self(handle)
}
}
impl From<Mesh2d> for AssetId<Mesh> {
fn from(mesh: Mesh2d) -> Self {
mesh.id()
}
}
impl From<&Mesh2d> for AssetId<Mesh> {
fn from(mesh: &Mesh2d) -> Self {
mesh.id()
}
}
/// A component for rendering 3D meshes, typically with a [`MeshMaterial3d`] using a [`StandardMaterial`].
///
/// Meshes without a [`MeshMaterial3d`] will be rendered with a [default material].
///
/// [`MeshMaterial3d`]: <https://docs.rs/bevy/latest/bevy/pbr/struct.MeshMaterial3d.html>
/// [`StandardMaterial`]: <https://docs.rs/bevy/latest/bevy/pbr/struct.StandardMaterial.html>
/// [default material]: <https://docs.rs/bevy/latest/bevy/pbr/struct.MeshMaterial3d.html#default-material>
///
/// # Example
///
/// ```ignore
/// # use bevy_pbr::{Material, MeshMaterial3d, StandardMaterial};
/// # use bevy_ecs::prelude::*;
/// # use bevy_render::mesh::{Mesh, Mesh3d};
/// # use bevy_color::palettes::basic::RED;
/// # use bevy_asset::Assets;
/// # use bevy_math::primitives::Capsule3d;
/// #
/// // Spawn an entity with a mesh using `StandardMaterial`.
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<StandardMaterial>>,
/// ) {
/// commands.spawn((
/// Mesh3d(meshes.add(Capsule3d::default())),
/// MeshMaterial3d(materials.add(StandardMaterial {
/// base_color: RED.into(),
/// ..Default::default()
/// })),
/// ));
/// }
/// ```
#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq)]
#[reflect(Component, Default)]
#[require(Transform, Visibility)]
pub struct Mesh3d(pub Handle<Mesh>);
impl From<Handle<Mesh>> for Mesh3d {
fn from(handle: Handle<Mesh>) -> Self {
Self(handle)
}
}
impl From<Mesh3d> for AssetId<Mesh> {
fn from(mesh: Mesh3d) -> Self {
mesh.id()
}
}
impl From<&Mesh3d> for AssetId<Mesh> {
fn from(mesh: &Mesh3d) -> Self {
mesh.id()
}
}

View file

@ -36,11 +36,10 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
///
/// Meshes can be automatically generated by a bevy `AssetLoader` (generally by loading a `Gltf` file),
/// or by converting a [primitive](bevy_math::primitives) using [`into`](Into).
/// It is also possible to create one manually.
/// They can be edited after creation.
/// It is also possible to create one manually. They can be edited after creation.
///
/// Meshes can be rendered with a `Material`, like `StandardMaterial` in `PbrBundle`
/// or `ColorMaterial` in `ColorMesh2dBundle`.
/// Meshes can be rendered with a [`Mesh2d`](super::Mesh2d) and `MeshMaterial2d`
/// or [`Mesh3d`](super::Mesh3d) and `MeshMaterial3d` for 2D and 3D respectively.
///
/// A [`Mesh`] in Bevy is equivalent to a "primitive" in the glTF format, for a
/// glTF Mesh representation, see `GltfMesh`.
@ -49,6 +48,7 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
///
/// The following function will construct a flat mesh, to be rendered with a
/// `StandardMaterial` or `ColorMaterial`:
///
/// ```
/// # use bevy_render::mesh::{Mesh, Indices};
/// # use bevy_render::render_resource::PrimitiveTopology;
@ -84,7 +84,7 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
/// ```
///
/// You can see how it looks like [here](https://github.com/bevyengine/bevy/blob/main/assets/docs/Mesh.png),
/// used in a `PbrBundle` with a square bevy logo texture, with added axis, points,
/// used in a `Mesh3d` with a square bevy logo texture, with added axis, points,
/// lines and text for clarity.
///
/// ## Other examples
@ -92,7 +92,7 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
/// For further visualization, explanation, and examples, see the built-in Bevy examples,
/// and the [implementation of the built-in shapes](https://github.com/bevyengine/bevy/tree/main/crates/bevy_render/src/mesh/primitives).
/// In particular, [generate_custom_mesh](https://github.com/bevyengine/bevy/blob/main/examples/3d/generate_custom_mesh.rs)
/// teaches you to access modify a Mesh's attributes after creating it.
/// teaches you to access and modify the attributes of a [`Mesh`] after creating it.
///
/// ## Common points of confusion
///

View file

@ -2,12 +2,14 @@
mod mesh;
pub mod allocator;
mod components;
pub mod morph;
pub mod primitives;
use alloc::sync::Arc;
use allocator::MeshAllocatorPlugin;
use bevy_utils::HashSet;
pub use components::{Mesh2d, Mesh3d};
use core::hash::{Hash, Hasher};
pub use mesh::*;
pub use primitives::*;
@ -25,6 +27,7 @@ impl Plugin for MeshPlugin {
app.init_asset::<Mesh>()
.init_asset::<skinning::SkinnedMeshInverseBindposes>()
.register_asset_reflect::<Mesh>()
.register_type::<Mesh3d>()
.register_type::<skinning::SkinnedMesh>()
.register_type::<Vec<Entity>>()
// 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready

View file

@ -14,6 +14,8 @@ use bytemuck::{Pod, Zeroable};
use core::iter;
use thiserror::Error;
use super::Mesh3d;
const MAX_TEXTURE_WIDTH: u32 = 2048;
// NOTE: "component" refers to the element count of math objects,
// Vec3 has 3 components, Mat2 has 4 components.
@ -114,7 +116,7 @@ impl MorphTargetImage {
}
}
/// Controls the [morph targets] for all child [`Handle<Mesh>`] entities. In most cases, [`MorphWeights`] should be considered
/// Controls the [morph targets] for all child [`Mesh3d`] entities. In most cases, [`MorphWeights`] should be considered
/// the "source of truth" when writing morph targets for meshes. However you can choose to write child [`MeshMorphWeights`]
/// if your situation requires more granularity. Just note that if you set [`MorphWeights`], it will overwrite child
/// [`MeshMorphWeights`] values.
@ -122,9 +124,9 @@ impl MorphTargetImage {
/// This exists because Bevy's [`Mesh`] corresponds to a _single_ surface / material, whereas morph targets
/// as defined in the GLTF spec exist on "multi-primitive meshes" (where each primitive is its own surface with its own material).
/// Therefore in Bevy [`MorphWeights`] an a parent entity are the "canonical weights" from a GLTF perspective, which then
/// synchronized to child [`Handle<Mesh>`] / [`MeshMorphWeights`] (which correspond to "primitives" / "surfaces" from a GLTF perspective).
/// synchronized to child [`Mesh3d`] / [`MeshMorphWeights`] (which correspond to "primitives" / "surfaces" from a GLTF perspective).
///
/// Add this to the parent of one or more [`Entities`](`Entity`) with a [`Handle<Mesh>`] with a [`MeshMorphWeights`].
/// Add this to the parent of one or more [`Entities`](`Entity`) with a [`Mesh3d`] with a [`MeshMorphWeights`].
///
/// [morph targets]: https://en.wikipedia.org/wiki/Morph_target_animation
#[derive(Reflect, Default, Debug, Clone, Component)]
@ -148,7 +150,7 @@ impl MorphWeights {
first_mesh,
})
}
/// The first child [`Handle<Mesh>`] primitive controlled by these weights.
/// The first child [`Mesh3d`] primitive controlled by these weights.
/// This can be used to look up metadata information such as [`Mesh::morph_target_names`].
pub fn first_mesh(&self) -> Option<&Handle<Mesh>> {
self.first_mesh.as_ref()
@ -168,7 +170,7 @@ impl MorphWeights {
///
/// See [`MorphWeights`] for more details on Bevy's morph target implementation.
///
/// Add this to an [`Entity`] with a [`Handle<Mesh>`] with a [`MorphAttributes`] set
/// Add this to an [`Entity`] with a [`Mesh3d`] with a [`MorphAttributes`] set
/// to control individual weights of each morph target.
///
/// [morph targets]: https://en.wikipedia.org/wiki/Morph_target_animation
@ -198,8 +200,8 @@ impl MeshMorphWeights {
///
/// Only direct children are updated, to fulfill the expectations of glTF spec.
pub fn inherit_weights(
morph_nodes: Query<(&Children, &MorphWeights), (Without<Handle<Mesh>>, Changed<MorphWeights>)>,
mut morph_primitives: Query<&mut MeshMorphWeights, With<Handle<Mesh>>>,
morph_nodes: Query<(&Children, &MorphWeights), (Without<Mesh3d>, Changed<MorphWeights>)>,
mut morph_primitives: Query<&mut MeshMorphWeights, With<Mesh3d>>,
) {
for (children, parent_weights) in &morph_nodes {
let mut iter = morph_primitives.iter_many_mut(children);

View file

@ -17,19 +17,17 @@ use bevy_reflect::prelude::*;
/// with the camera's [`Frustum`].
///
/// It will be added automatically by the systems in [`CalculateBounds`] to entities that:
/// - could be subject to frustum culling, for example with a [`Handle<Mesh>`]
/// - could be subject to frustum culling, for example with a [`Mesh3d`]
/// or `Sprite` component,
/// - don't have the [`NoFrustumCulling`] component.
///
/// It won't be updated automatically if the space occupied by the entity changes,
/// for example if the vertex positions of a [`Mesh`] inside a `Handle<Mesh>` are
/// updated.
/// for example if the vertex positions of a [`Mesh3d`] are updated.
///
/// [`Camera`]: crate::camera::Camera
/// [`NoFrustumCulling`]: crate::view::visibility::NoFrustumCulling
/// [`CalculateBounds`]: crate::view::visibility::VisibilitySystems::CalculateBounds
/// [`Mesh`]: crate::mesh::Mesh
/// [`Handle<Mesh>`]: crate::mesh::Mesh
/// [`Mesh3d`]: crate::mesh::Mesh
#[derive(Component, Clone, Copy, Debug, Default, Reflect, PartialEq)]
#[reflect(Component, Default, Debug, PartialEq)]
pub struct Aabb {

View file

@ -9,7 +9,7 @@ pub use range::*;
pub use render_layers::*;
use bevy_app::{Plugin, PostUpdate};
use bevy_asset::{Assets, Handle};
use bevy_asset::Assets;
use bevy_derive::Deref;
use bevy_ecs::{prelude::*, query::QueryFilter};
use bevy_hierarchy::{Children, Parent};
@ -19,7 +19,7 @@ use bevy_utils::{Parallel, TypeIdMap};
use crate::{
camera::{Camera, CameraProjection},
mesh::Mesh,
mesh::{Mesh, Mesh3d},
primitives::{Aabb, Frustum, Sphere},
};
@ -271,10 +271,6 @@ impl VisibleEntities {
}
}
/// A convenient alias for `With<Handle<Mesh>>`, for use with
/// [`VisibleEntities`].
pub type WithMesh = With<Handle<Mesh>>;
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
pub enum VisibilitySystems {
/// Label for the [`calculate_bounds`], `calculate_bounds_2d` and `calculate_bounds_text2d` systems,
@ -312,20 +308,20 @@ impl Plugin for VisibilityPlugin {
(
calculate_bounds.in_set(CalculateBounds),
(visibility_propagate_system, reset_view_visibility).in_set(VisibilityPropagate),
check_visibility::<WithMesh>.in_set(CheckVisibility),
check_visibility::<With<Mesh3d>>.in_set(CheckVisibility),
),
);
}
}
/// Computes and adds an [`Aabb`] component to entities with a
/// [`Handle<Mesh>`](Mesh) component and without a [`NoFrustumCulling`] component.
/// [`Mesh3d`] component and without a [`NoFrustumCulling`] component.
///
/// This system is used in system set [`VisibilitySystems::CalculateBounds`].
pub fn calculate_bounds(
mut commands: Commands,
meshes: Res<Assets<Mesh>>,
without_aabb: Query<(Entity, &Handle<Mesh>), (Without<Aabb>, Without<NoFrustumCulling>)>,
without_aabb: Query<(Entity, &Mesh3d), (Without<Aabb>, Without<NoFrustumCulling>)>,
) {
for (entity, mesh_handle) in &without_aabb {
if let Some(mesh) = meshes.get(mesh_handle) {

View file

@ -24,13 +24,14 @@ use wgpu::{BufferBindingType, BufferUsages};
use crate::{
camera::Camera,
mesh::Mesh3d,
primitives::Aabb,
render_resource::BufferVec,
renderer::{RenderDevice, RenderQueue},
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
};
use super::{check_visibility, VisibilitySystems, WithMesh};
use super::{check_visibility, VisibilitySystems};
/// We need at least 4 storage buffer bindings available to enable the
/// visibility range buffer.
@ -57,7 +58,7 @@ impl Plugin for VisibilityRangePlugin {
PostUpdate,
check_visibility_ranges
.in_set(VisibilitySystems::CheckVisibility)
.before(check_visibility::<WithMesh>),
.before(check_visibility::<With<Mesh3d>>),
);
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {

View file

@ -25,6 +25,7 @@ mod texture_slice;
/// The sprite prelude.
///
/// This includes the most common types in this crate, re-exported for your convenience.
#[expect(deprecated)]
pub mod prelude {
#[doc(hidden)]
pub use crate::{
@ -32,7 +33,7 @@ pub mod prelude {
sprite::{ImageScaleMode, Sprite},
texture_atlas::{TextureAtlas, TextureAtlasLayout, TextureAtlasSources},
texture_slice::{BorderRect, SliceScaleMode, TextureSlice, TextureSlicer},
ColorMaterial, ColorMesh2dBundle, TextureAtlasBuilder,
ColorMaterial, ColorMesh2dBundle, MeshMaterial2d, TextureAtlasBuilder,
};
}
@ -52,7 +53,7 @@ use bevy_core_pipeline::core_2d::Transparent2d;
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_render::{
extract_component::{ExtractComponent, ExtractComponentPlugin},
mesh::Mesh,
mesh::{Mesh, Mesh2d},
primitives::Aabb,
render_phase::AddRenderCommand,
render_resource::{Shader, SpecializedRenderPipelines},
@ -84,10 +85,6 @@ pub enum SpriteSystem {
#[reflect(Component, Default, Debug)]
pub struct SpriteSource;
/// A convenient alias for `With<Mesh2dHandle>>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithMesh2d = With<Mesh2dHandle>;
/// A convenient alias for `Or<With<Sprite>, With<SpriteSource>>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithSprite = Or<(With<Sprite>, With<SpriteSource>)>;
@ -113,7 +110,7 @@ impl Plugin for SpritePlugin {
.register_type::<TextureSlicer>()
.register_type::<Anchor>()
.register_type::<TextureAtlas>()
.register_type::<Mesh2dHandle>()
.register_type::<Mesh2d>()
.register_type::<SpriteSource>()
.add_plugins((
Mesh2dRenderPlugin,
@ -130,7 +127,7 @@ impl Plugin for SpritePlugin {
)
.in_set(SpriteSystem::ComputeSlices),
(
check_visibility::<WithMesh2d>,
check_visibility::<With<Mesh2d>>,
check_visibility::<WithSprite>,
)
.in_set(VisibilitySystems::CheckVisibility),
@ -176,7 +173,7 @@ impl Plugin for SpritePlugin {
}
/// System calculating and inserting an [`Aabb`] component to entities with either:
/// - a `Mesh2dHandle` component,
/// - a `Mesh2d` component,
/// - a `Sprite` and `Handle<Image>` components,
/// and without a [`NoFrustumCulling`] component.
///
@ -186,7 +183,7 @@ pub fn calculate_bounds_2d(
meshes: Res<Assets<Mesh>>,
images: Res<Assets<Image>>,
atlases: Res<Assets<TextureAtlasLayout>>,
meshes_without_aabb: Query<(Entity, &Mesh2dHandle), (Without<Aabb>, Without<NoFrustumCulling>)>,
meshes_without_aabb: Query<(Entity, &Mesh2d), (Without<Aabb>, Without<NoFrustumCulling>)>,
sprites_to_recalculate_aabb: Query<
(Entity, &Sprite, &Handle<Image>, Option<&TextureAtlas>),
(

View file

@ -1,13 +1,20 @@
use crate::{AlphaMode2d, Material2d, Material2dPlugin, MaterialMesh2dBundle};
#![expect(deprecated)]
use crate::{
clear_material_2d_instances, extract_default_materials_2d, AlphaMode2d, Material2d,
Material2dPlugin, MaterialMesh2dBundle,
};
use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, Asset, AssetApp, Assets, Handle};
use bevy_color::{Alpha, Color, ColorToComponents, LinearRgba};
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_math::Vec4;
use bevy_reflect::prelude::*;
use bevy_render::{
render_asset::RenderAssets,
render_resource::*,
texture::{GpuImage, Image},
ExtractSchedule, RenderApp,
};
pub const COLOR_MATERIAL_SHADER_HANDLE: Handle<Shader> =
@ -28,19 +35,30 @@ impl Plugin for ColorMaterialPlugin {
app.add_plugins(Material2dPlugin::<ColorMaterial>::default())
.register_asset_reflect::<ColorMaterial>();
// Initialize the default material.
app.world_mut()
.resource_mut::<Assets<ColorMaterial>>()
.insert(
&Handle::<ColorMaterial>::default(),
ColorMaterial {
color: Color::srgb(1.0, 0.0, 1.0),
color: Color::WHITE,
..Default::default()
},
);
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
// Extract default materials for entities with no material.
render_app.add_systems(
ExtractSchedule,
extract_default_materials_2d.after(clear_material_2d_instances::<ColorMaterial>),
);
}
}
/// A [2d material](Material2d) that renders [2d meshes](crate::Mesh2dHandle) with a texture tinted by a uniform color
/// A [2d material](Material2d) that renders [2d meshes](crate::Mesh2d) with a texture tinted by a uniform color
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
#[reflect(Default, Debug)]
#[uniform(0, ColorMaterialUniform)]
@ -158,5 +176,9 @@ impl Material2d for ColorMaterial {
}
}
/// A component bundle for entities with a [`Mesh2dHandle`](crate::Mesh2dHandle) and a [`ColorMaterial`].
/// A component bundle for entities with a [`Mesh2d`](crate::Mesh2d) and a [`ColorMaterial`].
#[deprecated(
since = "0.15.0",
note = "Use the `Mesh3d` and `MeshMaterial3d` components instead. Inserting them will now also insert the other components required by them automatically."
)]
pub type ColorMesh2dBundle = MaterialMesh2dBundle<ColorMaterial>;

View file

@ -1,3 +1,5 @@
#![expect(deprecated)]
use bevy_app::{App, Plugin};
use bevy_asset::{Asset, AssetApp, AssetId, AssetServer, Handle};
use bevy_core_pipeline::{
@ -36,29 +38,34 @@ use bevy_utils::tracing::error;
use core::{hash::Hash, marker::PhantomData};
use crate::{
DrawMesh2d, Mesh2dHandle, Mesh2dPipeline, Mesh2dPipelineKey, RenderMesh2dInstances,
SetMesh2dBindGroup, SetMesh2dViewBindGroup, WithMesh2d,
DrawMesh2d, Mesh2d, Mesh2dPipeline, Mesh2dPipelineKey, RenderMesh2dInstances,
SetMesh2dBindGroup, SetMesh2dViewBindGroup,
};
/// Materials are used alongside [`Material2dPlugin`] and [`MaterialMesh2dBundle`]
use super::ColorMaterial;
/// Materials are used alongside [`Material2dPlugin`], [`Mesh2d`], and [`MeshMaterial2d`]
/// to spawn entities that are rendered with a specific [`Material2d`] type. They serve as an easy to use high level
/// way to render [`Mesh2dHandle`] entities with custom shader logic.
/// way to render [`Mesh2d`] entities with custom shader logic.
///
/// Material2ds must implement [`AsBindGroup`] to define how data will be transferred to the GPU and bound in shaders.
/// Materials must implement [`AsBindGroup`] to define how data will be transferred to the GPU and bound in shaders.
/// [`AsBindGroup`] can be derived, which makes generating bindings straightforward. See the [`AsBindGroup`] docs for details.
///
/// # Example
///
/// Here is a simple Material2d implementation. The [`AsBindGroup`] derive has many features. To see what else is available,
/// Here is a simple [`Material2d`] implementation. The [`AsBindGroup`] derive has many features. To see what else is available,
/// check out the [`AsBindGroup`] documentation.
///
/// ```
/// # use bevy_sprite::{Material2d, MaterialMesh2dBundle};
/// # use bevy_sprite::{Material2d, MeshMaterial2d};
/// # use bevy_ecs::prelude::*;
/// # use bevy_reflect::TypePath;
/// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image};
/// # use bevy_render::{mesh::{Mesh, Mesh2d}, render_resource::{AsBindGroup, ShaderRef}, texture::Image};
/// # use bevy_color::LinearRgba;
/// # use bevy_color::palettes::basic::RED;
/// # use bevy_asset::{Handle, AssetServer, Assets, Asset};
///
/// # use bevy_math::primitives::Circle;
/// #
/// #[derive(AsBindGroup, Debug, Clone, Asset, TypePath)]
/// pub struct CustomMaterial {
/// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to
@ -80,17 +87,23 @@ use crate::{
/// }
/// }
///
/// // Spawn an entity using `CustomMaterial`.
/// fn setup(mut commands: Commands, mut materials: ResMut<Assets<CustomMaterial>>, asset_server: Res<AssetServer>) {
/// commands.spawn(MaterialMesh2dBundle {
/// material: materials.add(CustomMaterial {
/// color: LinearRgba::RED,
/// // Spawn an entity with a mesh using `CustomMaterial`.
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<CustomMaterial>>,
/// asset_server: Res<AssetServer>,
/// ) {
/// commands.spawn((
/// Mesh2d(meshes.add(Circle::new(50.0))),
/// MeshMaterial2d(materials.add(CustomMaterial {
/// color: RED.into(),
/// color_texture: asset_server.load("some_image.png"),
/// }),
/// ..Default::default()
/// });
/// })),
/// ));
/// }
/// ```
///
/// In WGSL shaders, the material's binding would look like this:
///
/// ```wgsl
@ -137,8 +150,104 @@ pub trait Material2d: AsBindGroup + Asset + Clone + Sized {
}
}
/// A [material](Material2d) for a [`Mesh2d`].
///
/// See [`Material2d`] for general information about 2D materials and how to implement your own materials.
///
/// # Example
///
/// ```
/// # use bevy_sprite::{ColorMaterial, MeshMaterial2d};
/// # use bevy_ecs::prelude::*;
/// # use bevy_render::mesh::{Mesh, Mesh2d};
/// # use bevy_color::palettes::basic::RED;
/// # use bevy_asset::Assets;
/// # use bevy_math::primitives::Circle;
/// #
/// // Spawn an entity with a mesh using `ColorMaterial`.
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<ColorMaterial>>,
/// ) {
/// commands.spawn((
/// Mesh2d(meshes.add(Circle::new(50.0))),
/// MeshMaterial2d(materials.add(ColorMaterial::from_color(RED))),
/// ));
/// }
/// ```
///
/// [`MeshMaterial2d`]: crate::MeshMaterial2d
/// [`ColorMaterial`]: crate::ColorMaterial
///
/// ## Default Material
///
/// Meshes without a [`MeshMaterial2d`] are rendered with a default [`ColorMaterial`].
/// This material can be overridden by inserting a custom material for the default asset handle.
///
/// ```
/// # use bevy_sprite::ColorMaterial;
/// # use bevy_ecs::prelude::*;
/// # use bevy_render::mesh::{Mesh, Mesh2d};
/// # use bevy_color::Color;
/// # use bevy_asset::{Assets, Handle};
/// # use bevy_math::primitives::Circle;
/// #
/// fn setup(
/// mut commands: Commands,
/// mut meshes: ResMut<Assets<Mesh>>,
/// mut materials: ResMut<Assets<ColorMaterial>>,
/// ) {
/// // Optional: Insert a custom default material.
/// materials.insert(
/// &Handle::<ColorMaterial>::default(),
/// ColorMaterial::from(Color::srgb(1.0, 0.0, 1.0)),
/// );
///
/// // Spawn a circle with no material.
/// // The mesh will be rendered with the default material.
/// commands.spawn(Mesh2d(meshes.add(Circle::new(50.0))));
/// }
/// ```
#[derive(Component, Clone, Debug, Deref, DerefMut, Reflect, PartialEq, Eq)]
#[reflect(Component, Default)]
#[require(HasMaterial2d)]
pub struct MeshMaterial2d<M: Material2d>(pub Handle<M>);
impl<M: Material2d> Default for MeshMaterial2d<M> {
fn default() -> Self {
Self(Handle::default())
}
}
impl<M: Material2d> From<Handle<M>> for MeshMaterial2d<M> {
fn from(handle: Handle<M>) -> Self {
Self(handle)
}
}
impl<M: Material2d> From<MeshMaterial2d<M>> for AssetId<M> {
fn from(material: MeshMaterial2d<M>) -> Self {
material.id()
}
}
impl<M: Material2d> From<&MeshMaterial2d<M>> for AssetId<M> {
fn from(material: &MeshMaterial2d<M>) -> Self {
material.id()
}
}
/// A component that marks an entity as having a [`MeshMaterial2d`].
/// [`Mesh2d`] entities without this component are rendered with a [default material].
///
/// [default material]: crate::MeshMaterial2d#default-material
#[derive(Component, Clone, Debug, Default, Reflect)]
#[reflect(Component, Default)]
pub struct HasMaterial2d;
/// Sets how a 2d material's base color alpha channel is used for transparency.
/// Currently, this only works with [`Mesh2d`](crate::mesh2d::Mesh2d). Sprites are always transparent.
/// Currently, this only works with [`Mesh2d`]. Sprites are always transparent.
///
/// This is very similar to [`AlphaMode`](bevy_render::alpha::AlphaMode) but this only applies to 2d meshes.
/// We use a separate type because 2d doesn't support all the transparency modes that 3d does.
@ -179,6 +288,8 @@ where
{
fn build(&self, app: &mut App) {
app.init_asset::<M>()
.register_type::<MeshMaterial2d<M>>()
.register_type::<HasMaterial2d>()
.add_plugins(RenderAssetPlugin::<PreparedMaterial2d<M>>::default());
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
@ -188,7 +299,14 @@ where
.add_render_command::<Transparent2d, DrawMaterial2d<M>>()
.init_resource::<RenderMaterial2dInstances<M>>()
.init_resource::<SpecializedMeshPipelines<Material2dPipeline<M>>>()
.add_systems(ExtractSchedule, extract_material_meshes_2d::<M>)
.add_systems(
ExtractSchedule,
(
clear_material_2d_instances::<M>,
extract_mesh_materials_2d::<M>,
)
.chain(),
)
.add_systems(
Render,
queue_material2d_meshes::<M>
@ -214,14 +332,33 @@ impl<M: Material2d> Default for RenderMaterial2dInstances<M> {
}
}
fn extract_material_meshes_2d<M: Material2d>(
pub(crate) fn clear_material_2d_instances<M: Material2d>(
mut material_instances: ResMut<RenderMaterial2dInstances<M>>,
query: Extract<Query<(Entity, &ViewVisibility, &Handle<M>)>>,
) {
material_instances.clear();
for (entity, view_visibility, handle) in &query {
}
fn extract_mesh_materials_2d<M: Material2d>(
mut material_instances: ResMut<RenderMaterial2dInstances<M>>,
query: Extract<Query<(Entity, &ViewVisibility, &MeshMaterial2d<M>), With<Mesh2d>>>,
) {
for (entity, view_visibility, material) in &query {
if view_visibility.get() {
material_instances.insert(entity, handle.id());
material_instances.insert(entity, material.id());
}
}
}
/// Extracts default materials for 2D meshes with no [`MeshMaterial2d`].
pub(crate) fn extract_default_materials_2d(
mut material_instances: ResMut<RenderMaterial2dInstances<ColorMaterial>>,
query: Extract<Query<(Entity, &ViewVisibility), (With<Mesh2d>, Without<HasMaterial2d>)>>,
) {
let default_material: AssetId<ColorMaterial> = Handle::<ColorMaterial>::default().id();
for (entity, view_visibility) in &query {
if view_visibility.get() {
material_instances.insert(entity, default_material);
}
}
}
@ -340,7 +477,7 @@ impl<M: Material2d> FromWorld for Material2dPipeline<M> {
}
}
type DrawMaterial2d<M> = (
pub(super) type DrawMaterial2d<M> = (
SetItemPipeline,
SetMesh2dViewBindGroup<0>,
SetMesh2dBindGroup<1>,
@ -460,7 +597,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
view_key |= Mesh2dPipelineKey::DEBAND_DITHER;
}
}
for visible_entity in visible_entities.iter::<WithMesh2d>() {
for visible_entity in visible_entities.iter::<With<Mesh2d>>() {
let Some(material_asset_id) = render_material_instances.get(visible_entity) else {
continue;
};
@ -609,11 +746,15 @@ impl<M: Material2d> RenderAsset for PreparedMaterial2d<M> {
}
}
/// A component bundle for entities with a [`Mesh2dHandle`] and a [`Material2d`].
/// A component bundle for entities with a [`Mesh2d`] and a [`MeshMaterial2d`].
#[derive(Bundle, Clone)]
#[deprecated(
since = "0.15.0",
note = "Use the `Mesh2d` and `MeshMaterial2d` components instead. Inserting them will now also insert the other components required by them automatically."
)]
pub struct MaterialMesh2dBundle<M: Material2d> {
pub mesh: Mesh2dHandle,
pub material: Handle<M>,
pub mesh: Mesh2d,
pub material: MeshMaterial2d<M>,
pub transform: Transform,
pub global_transform: GlobalTransform,
/// User indication of whether an entity is visible

View file

@ -15,7 +15,6 @@ use bevy_ecs::{
system::{lifetimeless::*, SystemParamItem, SystemState},
};
use bevy_math::{Affine3, Vec4};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{
batching::{
gpu_preprocessing::IndirectParameters,
@ -27,7 +26,8 @@ use bevy_render::{
},
globals::{GlobalsBuffer, GlobalsUniform},
mesh::{
allocator::MeshAllocator, Mesh, MeshVertexBufferLayoutRef, RenderMesh, RenderMeshBufferInfo,
allocator::MeshAllocator, Mesh, Mesh2d, MeshVertexBufferLayoutRef, RenderMesh,
RenderMeshBufferInfo,
},
render_asset::RenderAssets,
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
@ -48,19 +48,6 @@ use nonmax::NonMaxU32;
use crate::Material2dBindGroupId;
/// Component for rendering with meshes in the 2d pipeline, usually with a [2d material](crate::Material2d) such as [`ColorMaterial`](crate::ColorMaterial).
///
/// It wraps a [`Handle<Mesh>`] to differentiate from the 3d pipelines which use the handles directly as components
#[derive(Default, Clone, Component, Debug, Reflect, PartialEq, Eq, Deref, DerefMut)]
#[reflect(Default, Component, Debug, PartialEq)]
pub struct Mesh2dHandle(pub Handle<Mesh>);
impl From<Handle<Mesh>> for Mesh2dHandle {
fn from(handle: Handle<Mesh>) -> Self {
Self(handle)
}
}
#[derive(Default)]
pub struct Mesh2dRenderPlugin;
@ -218,7 +205,7 @@ pub struct RenderMesh2dInstance {
pub struct RenderMesh2dInstances(EntityHashMap<RenderMesh2dInstance>);
#[derive(Component)]
pub struct Mesh2d;
pub struct Mesh2dMarker;
pub fn extract_mesh2d(
mut render_mesh_instances: ResMut<RenderMesh2dInstances>,
@ -227,7 +214,7 @@ pub fn extract_mesh2d(
Entity,
&ViewVisibility,
&GlobalTransform,
&Mesh2dHandle,
&Mesh2d,
Has<NoAutomaticBatching>,
)>,
>,

View file

@ -1,4 +1,4 @@
use crate::{Material2d, Material2dKey, Material2dPlugin, Mesh2dHandle};
use crate::{Material2d, Material2dKey, Material2dPlugin, Mesh2d};
use bevy_app::{Plugin, Startup, Update};
use bevy_asset::{load_internal_asset, Asset, Assets, Handle};
use bevy_color::{Color, LinearRgba};
@ -9,6 +9,8 @@ use bevy_render::{
render_resource::*,
};
use super::MeshMaterial2d;
pub const WIREFRAME_2D_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(6920362697190520314);
/// A [`Plugin`] that draws wireframes for 2D meshes.
@ -126,12 +128,12 @@ fn global_color_changed(
fn wireframe_color_changed(
mut materials: ResMut<Assets<Wireframe2dMaterial>>,
mut colors_changed: Query<
(&mut Handle<Wireframe2dMaterial>, &Wireframe2dColor),
(&mut MeshMaterial2d<Wireframe2dMaterial>, &Wireframe2dColor),
(With<Wireframe2d>, Changed<Wireframe2dColor>),
>,
) {
for (mut handle, wireframe_color) in &mut colors_changed {
*handle = materials.add(Wireframe2dMaterial {
handle.0 = materials.add(Wireframe2dMaterial {
color: wireframe_color.color.into(),
});
}
@ -144,15 +146,24 @@ fn apply_wireframe_material(
mut materials: ResMut<Assets<Wireframe2dMaterial>>,
wireframes: Query<
(Entity, Option<&Wireframe2dColor>),
(With<Wireframe2d>, Without<Handle<Wireframe2dMaterial>>),
(
With<Wireframe2d>,
Without<MeshMaterial2d<Wireframe2dMaterial>>,
),
>,
no_wireframes: Query<
Entity,
(
With<NoWireframe2d>,
With<MeshMaterial2d<Wireframe2dMaterial>>,
),
>,
no_wireframes: Query<Entity, (With<NoWireframe2d>, With<Handle<Wireframe2dMaterial>>)>,
mut removed_wireframes: RemovedComponents<Wireframe2d>,
global_material: Res<GlobalWireframe2dMaterial>,
) {
for e in removed_wireframes.read().chain(no_wireframes.iter()) {
if let Some(commands) = commands.get_entity(e) {
commands.remove::<Handle<Wireframe2dMaterial>>();
commands.remove::<MeshMaterial2d<Wireframe2dMaterial>>();
}
}
@ -166,16 +177,12 @@ fn apply_wireframe_material(
// If there's no color specified we can use the global material since it's already set to use the default_color
global_material.handle.clone()
};
wireframes_to_spawn.push((e, material));
wireframes_to_spawn.push((e, MeshMaterial2d(material)));
}
commands.insert_or_spawn_batch(wireframes_to_spawn);
}
type Wireframe2dFilter = (
With<Mesh2dHandle>,
Without<Wireframe2d>,
Without<NoWireframe2d>,
);
type Wireframe2dFilter = (With<Mesh2d>, Without<Wireframe2d>, Without<NoWireframe2d>);
/// Applies or removes a wireframe material on any mesh without a [`Wireframe2d`] or [`NoWireframe2d`] component.
fn apply_global_wireframe_material(
@ -183,11 +190,14 @@ fn apply_global_wireframe_material(
config: Res<Wireframe2dConfig>,
meshes_without_material: Query<
Entity,
(Wireframe2dFilter, Without<Handle<Wireframe2dMaterial>>),
(
Wireframe2dFilter,
Without<MeshMaterial2d<Wireframe2dMaterial>>,
),
>,
meshes_with_global_material: Query<
Entity,
(Wireframe2dFilter, With<Handle<Wireframe2dMaterial>>),
(Wireframe2dFilter, With<MeshMaterial2d<Wireframe2dMaterial>>),
>,
global_material: Res<GlobalWireframe2dMaterial>,
) {
@ -196,12 +206,14 @@ fn apply_global_wireframe_material(
for e in &meshes_without_material {
// We only add the material handle but not the Wireframe component
// This makes it easy to detect which mesh is using the global material and which ones are user specified
material_to_spawn.push((e, global_material.handle.clone()));
material_to_spawn.push((e, MeshMaterial2d(global_material.handle.clone())));
}
commands.insert_or_spawn_batch(material_to_spawn);
} else {
for e in &meshes_with_global_material {
commands.entity(e).remove::<Handle<Wireframe2dMaterial>>();
commands
.entity(e)
.remove::<MeshMaterial2d<Wireframe2dMaterial>>();
}
}
}

View file

@ -32,12 +32,11 @@ fn setup_cube(
.spawn(Transform::default())
.with_children(|parent| {
// cube
parent.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::rgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
parent.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::rgb(0.8, 0.7, 0.6))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
});
// camera
@ -61,7 +60,8 @@ doesn't have a [`ViewVisibility`] or [`InheritedVisibility`] component.
Since the cube is spawned as a child of an entity without the
visibility components, it will not be visible at all.
To fix this, you must use [`SpatialBundle`], as follows:
To fix this, you must also add a [`Visibility`] component.
It automatically adds the other relevant visibility components for you:
```rust,no_run
use bevy::prelude::*;
@ -72,18 +72,14 @@ fn setup_cube(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands
// We use SpatialBundle instead of Transform, it contains the
// visibility components needed to display the cube,
// In addition to the Transform and GlobalTransform components.
.spawn(SpatialBundle::default())
.spawn((Transform::default(), Visibility::default()))
.with_children(|parent| {
// cube
parent.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::rgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
parent.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::rgb(0.8, 0.7, 0.6))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
});
// camera
@ -103,14 +99,14 @@ fn main() {
A similar problem occurs when the [`GlobalTransform`] component is missing.
However, it will be automatically inserted whenever `Transform` is
inserted, as it's a required component.
inserted, as it is a required component.
You will most likely encounter this warning when loading a scene
as a child of a pre-existing [`Entity`] that does not have the proper components.
[`InheritedVisibility`]: https://docs.rs/bevy/*/bevy/render/view/struct.InheritedVisibility.html
[`ViewVisibility`]: https://docs.rs/bevy/*/bevy/render/view/struct.ViewVisibility.html
[`Visibility`]: https://docs.rs/bevy/*/bevy/render/view/struct.Visibility.html
[`GlobalTransform`]: https://docs.rs/bevy/*/bevy/transform/components/struct.GlobalTransform.html
[`Parent`]: https://docs.rs/bevy/*/bevy/hierarchy/struct.Parent.html
[`Entity`]: https://docs.rs/bevy/*/bevy/ecs/entity/struct.Entity.html
[`SpatialBundle`]: https://docs.rs/bevy/*/bevy/render/prelude/struct.SpatialBundle.html

View file

@ -3,12 +3,9 @@
//! You can toggle wireframes with the space bar except on wasm. Wasm does not support
//! `POLYGON_MODE_LINE` on the gpu.
use bevy::prelude::*;
#[cfg(not(target_arch = "wasm32"))]
use bevy::sprite::{Wireframe2dConfig, Wireframe2dPlugin};
use bevy::{
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
fn main() {
let mut app = App::new();
@ -33,20 +30,20 @@ fn setup(
commands.spawn(Camera2dBundle::default());
let shapes = [
Mesh2dHandle(meshes.add(Circle::new(50.0))),
Mesh2dHandle(meshes.add(CircularSector::new(50.0, 1.0))),
Mesh2dHandle(meshes.add(CircularSegment::new(50.0, 1.25))),
Mesh2dHandle(meshes.add(Ellipse::new(25.0, 50.0))),
Mesh2dHandle(meshes.add(Annulus::new(25.0, 50.0))),
Mesh2dHandle(meshes.add(Capsule2d::new(25.0, 50.0))),
Mesh2dHandle(meshes.add(Rhombus::new(75.0, 100.0))),
Mesh2dHandle(meshes.add(Rectangle::new(50.0, 100.0))),
Mesh2dHandle(meshes.add(RegularPolygon::new(50.0, 6))),
Mesh2dHandle(meshes.add(Triangle2d::new(
meshes.add(Circle::new(50.0)),
meshes.add(CircularSector::new(50.0, 1.0)),
meshes.add(CircularSegment::new(50.0, 1.25)),
meshes.add(Ellipse::new(25.0, 50.0)),
meshes.add(Annulus::new(25.0, 50.0)),
meshes.add(Capsule2d::new(25.0, 50.0)),
meshes.add(Rhombus::new(75.0, 100.0)),
meshes.add(Rectangle::new(50.0, 100.0)),
meshes.add(RegularPolygon::new(50.0, 6)),
meshes.add(Triangle2d::new(
Vec2::Y * 50.0,
Vec2::new(-50.0, -50.0),
Vec2::new(50.0, -50.0),
))),
)),
];
let num_shapes = shapes.len();
@ -54,17 +51,16 @@ fn setup(
// Distribute colors evenly across the rainbow.
let color = Color::hsl(360. * i as f32 / num_shapes as f32, 0.95, 0.7);
commands.spawn(MaterialMesh2dBundle {
mesh: shape,
material: materials.add(color),
transform: Transform::from_xyz(
commands.spawn((
Mesh2d(shape),
MeshMaterial2d(materials.add(color)),
Transform::from_xyz(
// Distribute shapes from -X_EXTENT/2 to +X_EXTENT/2.
-X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * X_EXTENT,
0.0,
0.0,
),
..default()
});
));
}
#[cfg(not(target_arch = "wasm32"))]

View file

@ -6,7 +6,6 @@ use bevy::{
tonemapping::Tonemapping,
},
prelude::*,
sprite::MaterialMesh2dBundle,
};
fn main() {
@ -47,22 +46,20 @@ fn setup(
});
// Circle mesh
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Circle::new(100.)).into(),
commands.spawn((
Mesh2d(meshes.add(Circle::new(100.))),
// 4. Put something bright in a dark environment to see the effect
material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
..default()
});
MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
// Hexagon mesh
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(RegularPolygon::new(100., 6)).into(),
commands.spawn((
Mesh2d(meshes.add(RegularPolygon::new(100., 6))),
// 4. Put something bright in a dark environment to see the effect
material: materials.add(Color::srgb(6.25, 9.4, 9.1)),
transform: Transform::from_translation(Vec3::new(200., 0., 0.)),
..default()
});
MeshMaterial2d(materials.add(Color::srgb(6.25, 9.4, 9.1))),
Transform::from_translation(Vec3::new(200., 0., 0.)),
));
// UI
commands.spawn(

View file

@ -8,7 +8,7 @@ use bevy::{
mesh::{MeshVertexAttribute, MeshVertexBufferLayoutRef},
render_resource::*,
},
sprite::{Material2d, Material2dKey, Material2dPlugin, MaterialMesh2dBundle, Mesh2dHandle},
sprite::{Material2d, Material2dKey, Material2dPlugin},
};
/// This example uses a shader source file from the assets subdirectory
@ -53,12 +53,11 @@ fn setup(
}
.from_asset("models/barycentric/barycentric.gltf"),
);
commands.spawn(MaterialMesh2dBundle {
mesh: Mesh2dHandle(mesh),
material: materials.add(CustomMaterial {}),
transform: Transform::from_scale(150.0 * Vec3::ONE),
..default()
});
commands.spawn((
Mesh2d(mesh),
MeshMaterial2d(materials.add(CustomMaterial {})),
Transform::from_scale(150.0 * Vec3::ONE),
));
// Add a camera
commands.spawn(Camera2dBundle { ..default() });

View file

@ -1,6 +1,6 @@
//! Shows how to render a polygonal [`Mesh`], generated from a [`Rectangle`] primitive, in a 2D scene.
use bevy::{color::palettes::basic::PURPLE, prelude::*, sprite::MaterialMesh2dBundle};
use bevy::{color::palettes::basic::PURPLE, prelude::*};
fn main() {
App::new()
@ -15,10 +15,9 @@ fn setup(
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn(Camera2dBundle::default());
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Rectangle::default()).into(),
transform: Transform::default().with_scale(Vec3::splat(128.)),
material: materials.add(Color::from(PURPLE)),
..default()
});
commands.spawn((
Mesh2d(meshes.add(Rectangle::default())),
MeshMaterial2d(materials.add(Color::from(PURPLE))),
Transform::default().with_scale(Vec3::splat(128.)),
));
}

View file

@ -1,10 +1,10 @@
//! This example is used to test how transforms interact with alpha modes for [`MaterialMesh2dBundle`] entities.
//! This example is used to test how transforms interact with alpha modes for [`Mesh2d`] entities with a [`MeshMaterial2d`].
//! This makes sure the depth buffer is correctly being used for opaque and transparent 2d meshes
use bevy::{
color::palettes::css::{BLUE, GREEN, WHITE},
prelude::*,
sprite::{AlphaMode2d, MaterialMesh2dBundle},
sprite::AlphaMode2d,
};
fn main() {
@ -28,70 +28,64 @@ fn setup(
// opaque
// Each sprite should be square with the transparent parts being completely black
// The blue sprite should be on top with the white and green one behind it
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle.clone().into(),
material: materials.add(ColorMaterial {
commands.spawn((
Mesh2d(mesh_handle.clone()),
MeshMaterial2d(materials.add(ColorMaterial {
color: WHITE.into(),
alpha_mode: AlphaMode2d::Opaque,
texture: Some(texture_handle.clone()),
}),
transform: Transform::from_xyz(-400.0, 0.0, 0.0),
..default()
});
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle.clone().into(),
material: materials.add(ColorMaterial {
})),
Transform::from_xyz(-400.0, 0.0, 0.0),
));
commands.spawn((
Mesh2d(mesh_handle.clone()),
MeshMaterial2d(materials.add(ColorMaterial {
color: BLUE.into(),
alpha_mode: AlphaMode2d::Opaque,
texture: Some(texture_handle.clone()),
}),
transform: Transform::from_xyz(-300.0, 0.0, 1.0),
..default()
});
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle.clone().into(),
material: materials.add(ColorMaterial {
})),
Transform::from_xyz(-300.0, 0.0, 1.0),
));
commands.spawn((
Mesh2d(mesh_handle.clone()),
MeshMaterial2d(materials.add(ColorMaterial {
color: GREEN.into(),
alpha_mode: AlphaMode2d::Opaque,
texture: Some(texture_handle.clone()),
}),
transform: Transform::from_xyz(-200.0, 0.0, -1.0),
..default()
});
})),
Transform::from_xyz(-200.0, 0.0, -1.0),
));
// Test the interaction between opaque/mask and transparent meshes
// The white sprite should be:
// - only the icon is opaque but background is transparent
// - on top of the green sprite
// - behind the blue sprite
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle.clone().into(),
material: materials.add(ColorMaterial {
commands.spawn((
Mesh2d(mesh_handle.clone()),
MeshMaterial2d(materials.add(ColorMaterial {
color: WHITE.into(),
alpha_mode: AlphaMode2d::Mask(0.5),
texture: Some(texture_handle.clone()),
}),
transform: Transform::from_xyz(200.0, 0.0, 0.0),
..default()
});
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle.clone().into(),
material: materials.add(ColorMaterial {
})),
Transform::from_xyz(200.0, 0.0, 0.0),
));
commands.spawn((
Mesh2d(mesh_handle.clone()),
MeshMaterial2d(materials.add(ColorMaterial {
color: BLUE.with_alpha(0.7).into(),
alpha_mode: AlphaMode2d::Blend,
texture: Some(texture_handle.clone()),
}),
transform: Transform::from_xyz(300.0, 0.0, 1.0),
..default()
});
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle.clone().into(),
material: materials.add(ColorMaterial {
})),
Transform::from_xyz(300.0, 0.0, 1.0),
));
commands.spawn((
Mesh2d(mesh_handle.clone()),
MeshMaterial2d(materials.add(ColorMaterial {
color: GREEN.with_alpha(0.7).into(),
alpha_mode: AlphaMode2d::Blend,
texture: Some(texture_handle),
}),
transform: Transform::from_xyz(400.0, 0.0, -1.0),
..default()
});
})),
Transform::from_xyz(400.0, 0.0, -1.0),
));
}

View file

@ -12,7 +12,6 @@ use bevy::{
},
prelude::*,
render::mesh::{CircularMeshUvMode, CircularSectorMeshBuilder, CircularSegmentMeshBuilder},
sprite::MaterialMesh2dBundle,
};
fn main() {
@ -68,14 +67,11 @@ fn setup(
angle: sector_angle,
});
commands.spawn((
MaterialMesh2dBundle {
mesh: meshes.add(sector_mesh).into(),
material: material.clone(),
transform: Transform {
translation: Vec3::new(FIRST_X + OFFSET * i as f32, 2.0 * UPPER_Y, 0.0),
rotation: Quat::from_rotation_z(sector_angle),
..default()
},
Mesh2d(meshes.add(sector_mesh)),
MeshMaterial2d(material.clone()),
Transform {
translation: Vec3::new(FIRST_X + OFFSET * i as f32, 2.0 * UPPER_Y, 0.0),
rotation: Quat::from_rotation_z(sector_angle),
..default()
},
DrawBounds(sector),
@ -95,14 +91,11 @@ fn setup(
angle: -segment_angle,
});
commands.spawn((
MaterialMesh2dBundle {
mesh: meshes.add(segment_mesh).into(),
material: material.clone(),
transform: Transform {
translation: Vec3::new(FIRST_X + OFFSET * i as f32, LOWER_Y, 0.0),
rotation: Quat::from_rotation_z(segment_angle),
..default()
},
Mesh2d(meshes.add(segment_mesh)),
MeshMaterial2d(material.clone()),
Transform {
translation: Vec3::new(FIRST_X + OFFSET * i as f32, LOWER_Y, 0.0),
rotation: Quat::from_rotation_z(segment_angle),
..default()
},
DrawBounds(segment),

View file

@ -12,7 +12,7 @@ use bevy::{
math::{ops, FloatOrd},
prelude::*,
render::{
mesh::{Indices, MeshVertexAttribute, RenderMesh},
mesh::{Indices, RenderMesh},
render_asset::{RenderAssetUsages, RenderAssets},
render_phase::{
AddRenderCommand, DrawFunctions, PhaseItemExtraIndex, SetItemPipeline,
@ -30,9 +30,9 @@ use bevy::{
Extract, Render, RenderApp, RenderSet,
},
sprite::{
extract_mesh2d, DrawMesh2d, Material2dBindGroupId, Mesh2dHandle, Mesh2dPipeline,
extract_mesh2d, DrawMesh2d, HasMaterial2d, Material2dBindGroupId, Mesh2dPipeline,
Mesh2dPipelineKey, Mesh2dTransforms, MeshFlags, RenderMesh2dInstance, SetMesh2dBindGroup,
SetMesh2dViewBindGroup, WithMesh2d,
SetMesh2dViewBindGroup,
},
};
use std::f32::consts::PI;
@ -85,12 +85,9 @@ fn star(
// Set the position attribute
star.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
// And a RGB color attribute as well
let mut v_color: Vec<u32> = vec![LinearRgba::BLACK.as_u32()];
v_color.extend_from_slice(&[LinearRgba::from(YELLOW).as_u32(); 10]);
star.insert_attribute(
MeshVertexAttribute::new("Vertex_Color", 1, VertexFormat::Uint32),
v_color,
);
let mut v_color: Vec<[f32; 4]> = vec![LinearRgba::BLACK.to_f32_array()];
v_color.extend_from_slice(&[LinearRgba::from(YELLOW).to_f32_array(); 10]);
star.insert_attribute(Mesh::ATTRIBUTE_COLOR, v_color);
// Now, we specify the indices of the vertex that are going to compose the
// triangles in our star. Vertices in triangles have to be specified in CCW
@ -111,8 +108,8 @@ fn star(
commands.spawn((
// We use a marker component to identify the custom colored meshes
ColoredMesh2d,
// The `Handle<Mesh>` needs to be wrapped in a `Mesh2dHandle` to use 2d rendering instead of 3d
Mesh2dHandle(meshes.add(star)),
// The `Handle<Mesh>` needs to be wrapped in a `Mesh2d` for 2D rendering
Mesh2d(meshes.add(star)),
// This bundle's components are needed for something to be rendered
SpatialBundle::INHERITED_IDENTITY,
));
@ -121,8 +118,10 @@ fn star(
commands.spawn(Camera2dBundle::default());
}
// Require `HasMaterial2d` to indicate that no placeholder material should be rendeed.
/// A marker component for colored 2d meshes
#[derive(Component, Default)]
#[require(HasMaterial2d)]
pub struct ColoredMesh2d;
/// Custom pipeline for 2d meshes with vertex colors
@ -330,7 +329,7 @@ pub fn extract_colored_mesh2d(
// When extracting, you must use `Extract` to mark the `SystemParam`s
// which should be taken from the main world.
query: Extract<
Query<(Entity, &ViewVisibility, &GlobalTransform, &Mesh2dHandle), With<ColoredMesh2d>>,
Query<(Entity, &ViewVisibility, &GlobalTransform, &Mesh2d), With<ColoredMesh2d>>,
>,
mut render_mesh_instances: ResMut<RenderColoredMesh2dInstances>,
) {
@ -387,7 +386,7 @@ pub fn queue_colored_mesh2d(
| Mesh2dPipelineKey::from_hdr(view.hdr);
// Queue all entities visible to that view
for visible_entity in visible_entities.iter::<WithMesh2d>() {
for visible_entity in visible_entities.iter::<With<Mesh2d>>() {
if let Some(mesh_instance) = render_mesh_instances.get(visible_entity) {
let mesh2d_handle = mesh_instance.mesh_asset_id;
let mesh2d_transforms = &mesh_instance.transforms;

View file

@ -1,10 +1,7 @@
//! Shows how to render a polygonal [`Mesh`], generated from a [`Rectangle`] primitive, in a 2D scene.
//! Adds a texture and colored vertices, giving per-vertex tinting.
use bevy::{
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
use bevy::prelude::*;
fn main() {
App::new()
@ -33,26 +30,22 @@ fn setup(
// Insert the vertex colors as an attribute
mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, vertex_colors);
let mesh_handle: Mesh2dHandle = meshes.add(mesh).into();
let mesh_handle = meshes.add(mesh);
// Spawn camera
commands.spawn(Camera2dBundle::default());
// Spawn the quad with vertex colors
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle.clone(),
transform: Transform::from_translation(Vec3::new(-96., 0., 0.))
.with_scale(Vec3::splat(128.)),
material: materials.add(ColorMaterial::default()),
..default()
});
commands.spawn((
Mesh2d(mesh_handle.clone()),
MeshMaterial2d(materials.add(ColorMaterial::default())),
Transform::from_translation(Vec3::new(-96., 0., 0.)).with_scale(Vec3::splat(128.)),
));
// Spawning the quad with vertex colors and a texture results in tinting
commands.spawn(MaterialMesh2dBundle {
mesh: mesh_handle,
transform: Transform::from_translation(Vec3::new(96., 0., 0.))
.with_scale(Vec3::splat(128.)),
material: materials.add(texture_handle),
..default()
});
commands.spawn((
Mesh2d(mesh_handle),
MeshMaterial2d(materials.add(texture_handle)),
Transform::from_translation(Vec3::new(96., 0., 0.)).with_scale(Vec3::splat(128.)),
));
}

View file

@ -9,7 +9,6 @@ use bevy::{
},
view::RenderLayers,
},
sprite::MaterialMesh2dBundle,
window::WindowResized,
};
@ -81,12 +80,9 @@ fn setup_mesh(
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn((
MaterialMesh2dBundle {
mesh: meshes.add(Capsule2d::default()).into(),
transform: Transform::from_xyz(40., 0., 2.).with_scale(Vec3::splat(32.)),
material: materials.add(Color::BLACK),
..default()
},
Mesh2d(meshes.add(Capsule2d::default())),
MeshMaterial2d(materials.add(Color::BLACK)),
Transform::from_xyz(40., 0., 2.).with_scale(Vec3::splat(32.)),
Rotate,
PIXEL_PERFECT_LAYERS,
));

View file

@ -16,10 +16,7 @@ use bevy::{
settings::{RenderCreation, WgpuSettings},
RenderPlugin,
},
sprite::{
MaterialMesh2dBundle, NoWireframe2d, Wireframe2d, Wireframe2dColor, Wireframe2dConfig,
Wireframe2dPlugin,
},
sprite::{NoWireframe2d, Wireframe2d, Wireframe2dColor, Wireframe2dConfig, Wireframe2dPlugin},
};
fn main() {
@ -59,35 +56,26 @@ fn setup(
) {
// Triangle: Never renders a wireframe
commands.spawn((
MaterialMesh2dBundle {
mesh: meshes
.add(Triangle2d::new(
Vec2::new(0.0, 50.0),
Vec2::new(-50.0, -50.0),
Vec2::new(50.0, -50.0),
))
.into(),
material: materials.add(Color::BLACK),
transform: Transform::from_xyz(-150.0, 0.0, 0.0),
..default()
},
Mesh2d(meshes.add(Triangle2d::new(
Vec2::new(0.0, 50.0),
Vec2::new(-50.0, -50.0),
Vec2::new(50.0, -50.0),
))),
MeshMaterial2d(materials.add(Color::BLACK)),
Transform::from_xyz(-150.0, 0.0, 0.0),
NoWireframe2d,
));
// Rectangle: Follows global wireframe setting
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Rectangle::new(100.0, 100.0)).into(),
material: materials.add(Color::BLACK),
transform: Transform::from_xyz(0.0, 0.0, 0.0),
..default()
});
commands.spawn((
Mesh2d(meshes.add(Rectangle::new(100.0, 100.0))),
MeshMaterial2d(materials.add(Color::BLACK)),
Transform::from_xyz(0.0, 0.0, 0.0),
));
// Circle: Always renders a wireframe
commands.spawn((
MaterialMesh2dBundle {
mesh: meshes.add(Circle::new(50.0)).into(),
material: materials.add(Color::BLACK),
transform: Transform::from_xyz(150.0, 0.0, 0.0),
..default()
},
Mesh2d(meshes.add(Circle::new(50.0))),
MeshMaterial2d(materials.add(Color::BLACK)),
Transform::from_xyz(150.0, 0.0, 0.0),
Wireframe2d,
// This lets you configure the wireframe color of this entity.
// If not set, this will use the color in `WireframeConfig`

View file

@ -16,19 +16,17 @@ fn setup(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// circular base
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(4.0)),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Circle::new(4.0))),
MeshMaterial3d(materials.add(Color::WHITE)),
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
));
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::srgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// light
commands.spawn((
PointLight {

View file

@ -81,17 +81,14 @@ fn setup(
for (i, shape) in shapes.into_iter().enumerate() {
commands.spawn((
PbrBundle {
mesh: shape,
material: debug_material.clone(),
transform: Transform::from_xyz(
-SHAPES_X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * SHAPES_X_EXTENT,
2.0,
Z_EXTENT / 2.,
)
.with_rotation(Quat::from_rotation_x(-PI / 4.)),
..default()
},
Mesh3d(shape),
MeshMaterial3d(debug_material.clone()),
Transform::from_xyz(
-SHAPES_X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * SHAPES_X_EXTENT,
2.0,
Z_EXTENT / 2.,
)
.with_rotation(Quat::from_rotation_x(-PI / 4.)),
Shape,
));
}
@ -100,18 +97,15 @@ fn setup(
for (i, shape) in extrusions.into_iter().enumerate() {
commands.spawn((
PbrBundle {
mesh: shape,
material: debug_material.clone(),
transform: Transform::from_xyz(
-EXTRUSION_X_EXTENT / 2.
+ i as f32 / (num_extrusions - 1) as f32 * EXTRUSION_X_EXTENT,
2.0,
-Z_EXTENT / 2.,
)
.with_rotation(Quat::from_rotation_x(-PI / 4.)),
..default()
},
Mesh3d(shape),
MeshMaterial3d(debug_material.clone()),
Transform::from_xyz(
-EXTRUSION_X_EXTENT / 2.
+ i as f32 / (num_extrusions - 1) as f32 * EXTRUSION_X_EXTENT,
2.0,
-Z_EXTENT / 2.,
)
.with_rotation(Quat::from_rotation_x(-PI / 4.)),
Shape,
));
}
@ -128,11 +122,10 @@ fn setup(
));
// ground plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0).subdivisions(10)),
material: materials.add(Color::from(SILVER)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(50.0, 50.0).subdivisions(10))),
MeshMaterial3d(materials.add(Color::from(SILVER))),
));
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 7., 14.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y),

View file

@ -57,11 +57,8 @@ fn setup(
) {
// plane
commands.spawn((
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(20., 20.)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
},
Mesh3d(meshes.add(Plane3d::default().mesh().size(20., 20.))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
Ground,
));

View file

@ -37,19 +37,18 @@ fn setup(
let mut hsla = Hsla::hsl(0.0, 1.0, 0.5);
for x in -1..2 {
for z in -1..2 {
commands.spawn(PbrBundle {
mesh: cube.clone(),
material: materials.add(Color::from(hsla)),
transform: Transform::from_translation(Vec3::new(x as f32, 0.0, z as f32)),
..default()
});
commands.spawn((
Mesh3d(cube.clone()),
MeshMaterial3d(materials.add(Color::from(hsla))),
Transform::from_translation(Vec3::new(x as f32, 0.0, z as f32)),
));
hsla = hsla.rotate_hue(GOLDEN_ANGLE);
}
}
}
fn animate_materials(
material_handles: Query<&Handle<StandardMaterial>>,
material_handles: Query<&MeshMaterial3d<StandardMaterial>>,
time: Res<Time>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {

View file

@ -104,8 +104,11 @@ fn create_material_variants(
mut commands: Commands,
mut materials: ResMut<Assets<StandardMaterial>>,
new_meshes: Query<
(Entity, &Handle<StandardMaterial>),
(Added<Handle<StandardMaterial>>, Without<MaterialVariants>),
(Entity, &MeshMaterial3d<StandardMaterial>),
(
Added<MeshMaterial3d<StandardMaterial>>,
Without<MaterialVariants>,
),
>,
) {
for (entity, anisotropic_material_handle) in new_meshes.iter() {
@ -114,7 +117,7 @@ fn create_material_variants(
};
commands.entity(entity).insert(MaterialVariants {
anisotropic: anisotropic_material_handle.clone(),
anisotropic: anisotropic_material_handle.0.clone(),
isotropic: materials.add(StandardMaterial {
anisotropy_texture: None,
anisotropy_strength: 0.0,
@ -163,7 +166,7 @@ fn handle_input(
asset_server: Res<AssetServer>,
cameras: Query<Entity, With<Camera>>,
lights: Query<Entity, Or<(With<DirectionalLight>, With<PointLight>)>>,
mut meshes: Query<(&mut Handle<StandardMaterial>, &MaterialVariants)>,
mut meshes: Query<(&mut MeshMaterial3d<StandardMaterial>, &MaterialVariants)>,
keyboard: Res<ButtonInput<KeyCode>>,
mut app_status: ResMut<AppStatus>,
) {
@ -213,7 +216,7 @@ fn handle_input(
// Go through each mesh and alter its material.
for (mut material_handle, material_variants) in meshes.iter_mut() {
*material_handle = if app_status.anisotropy_enabled {
material_handle.0 = if app_status.anisotropy_enabled {
material_variants.anisotropic.clone()
} else {
material_variants.isotropic.clone()

View file

@ -252,11 +252,10 @@ fn setup(
asset_server: Res<AssetServer>,
) {
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)),
material: materials.add(Color::srgb(0.1, 0.2, 0.1)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(50.0, 50.0))),
MeshMaterial3d(materials.add(Color::srgb(0.1, 0.2, 0.1))),
));
let cube_material = materials.add(StandardMaterial {
base_color_texture: Some(images.add(uv_debug_texture())),
@ -265,12 +264,11 @@ fn setup(
// Cubes
for i in 0..5 {
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(0.25, 0.25, 0.25)),
material: cube_material.clone(),
transform: Transform::from_xyz(i as f32 * 0.25 - 1.0, 0.125, -i as f32 * 0.5),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(0.25, 0.25, 0.25))),
MeshMaterial3d(cube_material.clone()),
Transform::from_xyz(i as f32 * 0.25 - 1.0, 0.125, -i as f32 * 0.5),
));
}
// Flight Helmet

View file

@ -77,17 +77,14 @@ fn setup_terrain_scene(
// Sky
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::new(2.0, 1.0, 1.0)),
material: materials.add(StandardMaterial {
base_color: Srgba::hex("888888").unwrap().into(),
unlit: true,
cull_mode: None,
..default()
}),
transform: Transform::from_scale(Vec3::splat(20.0)),
Mesh3d(meshes.add(Cuboid::new(2.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Srgba::hex("888888").unwrap().into(),
unlit: true,
cull_mode: None,
..default()
},
})),
Transform::from_scale(Vec3::splat(20.0)),
NotShadowCaster,
));
}

View file

@ -88,20 +88,18 @@ fn setup(
let height = Vec3::Y * level as f32;
commands.spawn(PbrBundle {
mesh: plane.clone(),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(plane.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(
0.5 + side.x * 0.5,
0.75 - level as f32 * 0.25,
0.5 + side.z * 0.5,
),
..default()
}),
transform: Transform::from_translation(side * 2.0 + height)
.looking_at(height, Vec3::Y),
..default()
});
})),
Transform::from_translation(side * 2.0 + height),
));
}
}

View file

@ -42,16 +42,13 @@ fn setup(
// Opaque
let opaque = commands
.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Opaque,
..default()
}),
transform: Transform::from_xyz(-4.0, 0.0, 0.0),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Opaque,
..default()
},
})),
Transform::from_xyz(-4.0, 0.0, 0.0),
ExampleControls {
unlit: true,
color: true,
@ -62,16 +59,13 @@ fn setup(
// Blend
let blend = commands
.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Blend,
..default()
}),
transform: Transform::from_xyz(-2.0, 0.0, 0.0),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Blend,
..default()
},
})),
Transform::from_xyz(-2.0, 0.0, 0.0),
ExampleControls {
unlit: true,
color: true,
@ -82,16 +76,13 @@ fn setup(
// Premultiplied
let premultiplied = commands
.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Premultiplied,
..default()
}),
transform: Transform::from_xyz(0.0, 0.0, 0.0),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Premultiplied,
..default()
},
})),
Transform::from_xyz(0.0, 0.0, 0.0),
ExampleControls {
unlit: true,
color: true,
@ -102,16 +93,13 @@ fn setup(
// Add
let add = commands
.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Add,
..default()
}),
transform: Transform::from_xyz(2.0, 0.0, 0.0),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Add,
..default()
},
})),
Transform::from_xyz(2.0, 0.0, 0.0),
ExampleControls {
unlit: true,
color: true,
@ -122,16 +110,13 @@ fn setup(
// Multiply
let multiply = commands
.spawn((
PbrBundle {
mesh: icosphere_mesh,
material: materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Multiply,
..default()
}),
transform: Transform::from_xyz(4.0, 0.0, 0.0),
Mesh3d(icosphere_mesh),
MeshMaterial3d(materials.add(StandardMaterial {
base_color,
alpha_mode: AlphaMode::Multiply,
..default()
},
})),
Transform::from_xyz(4.0, 0.0, 0.0),
ExampleControls {
unlit: true,
color: true,
@ -148,16 +133,13 @@ fn setup(
for x in -3..4 {
for z in -3..4 {
commands.spawn((
PbrBundle {
mesh: plane_mesh.clone(),
material: if (x + z) % 2 == 0 {
black_material.clone()
} else {
white_material.clone()
},
transform: Transform::from_xyz(x as f32 * 2.0, -1.0, z as f32 * 2.0),
..default()
},
Mesh3d(plane_mesh.clone()),
MeshMaterial3d(if (x + z) % 2 == 0 {
black_material.clone()
} else {
white_material.clone()
}),
Transform::from_xyz(x as f32 * 2.0, -1.0, z as f32 * 2.0),
ExampleControls {
unlit: false,
color: true,
@ -277,7 +259,7 @@ impl Default for ExampleState {
#[allow(clippy::too_many_arguments)]
fn example_control_system(
mut materials: ResMut<Assets<StandardMaterial>>,
controllable: Query<(&Handle<StandardMaterial>, &ExampleControls)>,
controllable: Query<(&MeshMaterial3d<StandardMaterial>, &ExampleControls)>,
mut camera: Query<(&mut Camera, &mut Transform, &GlobalTransform), With<Camera3d>>,
mut labels: Query<(&mut Style, &ExampleLabel)>,
mut display: Query<&mut Text, With<ExampleDisplay>>,

View file

@ -77,12 +77,9 @@ fn setup_scene(
};
commands.spawn((
PbrBundle {
mesh: mesh.clone(),
material,
transform: Transform::from_xyz(x as f32 * 2.0, 0.0, z as f32 * 2.0),
..default()
},
Mesh3d(mesh.clone()),
MeshMaterial3d(material),
Transform::from_xyz(x as f32 * 2.0, 0.0, z as f32 * 2.0),
Bouncing,
));
}

View file

@ -50,19 +50,17 @@ fn setup(
let transform = Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y);
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// Cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// Light
commands.spawn((

View file

@ -97,9 +97,9 @@ fn spawn_car_paint_sphere(
sphere: &Handle<Mesh>,
) {
commands
.spawn(PbrBundle {
mesh: sphere.clone(),
material: materials.add(StandardMaterial {
.spawn((
Mesh3d(sphere.clone()),
materials.add(StandardMaterial {
clearcoat: 1.0,
clearcoat_perceptual_roughness: 0.1,
normal_map_texture: Some(asset_server.load_with_settings(
@ -111,9 +111,8 @@ fn spawn_car_paint_sphere(
base_color: BLUE.into(),
..default()
}),
transform: Transform::from_xyz(-1.0, 1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
..default()
})
Transform::from_xyz(-1.0, 1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
))
.insert(ExampleSphere);
}
@ -124,9 +123,9 @@ fn spawn_coated_glass_bubble_sphere(
sphere: &Handle<Mesh>,
) {
commands
.spawn(PbrBundle {
mesh: sphere.clone(),
material: materials.add(StandardMaterial {
.spawn((
Mesh3d(sphere.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
clearcoat: 1.0,
clearcoat_perceptual_roughness: 0.1,
metallic: 0.5,
@ -134,10 +133,9 @@ fn spawn_coated_glass_bubble_sphere(
base_color: Color::srgba(0.9, 0.9, 0.9, 0.3),
alpha_mode: AlphaMode::Blend,
..default()
}),
transform: Transform::from_xyz(-1.0, -1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
..default()
})
})),
Transform::from_xyz(-1.0, -1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
))
.insert(ExampleSphere);
}
@ -166,9 +164,9 @@ fn spawn_scratched_gold_ball(
sphere: &Handle<Mesh>,
) {
commands
.spawn(PbrBundle {
mesh: sphere.clone(),
material: materials.add(StandardMaterial {
.spawn((
Mesh3d(sphere.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
clearcoat: 1.0,
clearcoat_perceptual_roughness: 0.3,
clearcoat_normal_texture: Some(asset_server.load_with_settings(
@ -179,10 +177,9 @@ fn spawn_scratched_gold_ball(
perceptual_roughness: 0.1,
base_color: GOLD.into(),
..default()
}),
transform: Transform::from_xyz(1.0, -1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
..default()
})
})),
Transform::from_xyz(1.0, -1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
))
.insert(ExampleSphere);
}

View file

@ -100,28 +100,25 @@ fn setup(
let forward_mat_h = materials.add(forward_mat);
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)),
material: forward_mat_h.clone(),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(50.0, 50.0))),
MeshMaterial3d(forward_mat_h.clone()),
));
let cube_h = meshes.add(Cuboid::new(0.1, 0.1, 0.1));
let sphere_h = meshes.add(Sphere::new(0.125).mesh().uv(32, 18));
// Cubes
commands.spawn(PbrBundle {
mesh: cube_h.clone(),
material: forward_mat_h.clone(),
transform: Transform::from_xyz(-0.3, 0.5, -0.2),
..default()
});
commands.spawn(PbrBundle {
mesh: cube_h,
material: forward_mat_h,
transform: Transform::from_xyz(0.2, 0.5, 0.2),
..default()
});
commands.spawn((
Mesh3d(cube_h.clone()),
MeshMaterial3d(forward_mat_h.clone()),
Transform::from_xyz(-0.3, 0.5, -0.2),
));
commands.spawn((
Mesh3d(cube_h),
MeshMaterial3d(forward_mat_h),
Transform::from_xyz(0.2, 0.5, 0.2),
));
let sphere_color = Color::srgb(10.0, 4.0, 1.0);
let sphere_pos = Transform::from_xyz(0.4, 0.5, -0.8);
@ -129,12 +126,9 @@ fn setup(
let mut unlit_mat: StandardMaterial = sphere_color.into();
unlit_mat.unlit = true;
commands.spawn((
PbrBundle {
mesh: sphere_h.clone(),
material: materials.add(unlit_mat),
transform: sphere_pos,
..default()
},
Mesh3d(sphere_h.clone()),
MeshMaterial3d(materials.add(unlit_mat)),
sphere_pos,
NotShadowCaster,
));
// Light
@ -175,31 +169,27 @@ fn setup(
..default()
})
};
commands.spawn(PbrBundle {
mesh: sphere_h.clone(),
material,
transform: Transform::from_xyz(
commands.spawn((
Mesh3d(sphere_h.clone()),
MeshMaterial3d(material),
Transform::from_xyz(
j as f32 * 0.25 + if i < 3 { -0.15 } else { 0.15 } - 0.4,
0.125,
-j as f32 * 0.25 + if i < 3 { -0.15 } else { 0.15 } + 0.4,
),
..default()
});
));
}
// sky
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::new(2.0, 1.0, 1.0)),
material: materials.add(StandardMaterial {
base_color: Srgba::hex("888888").unwrap().into(),
unlit: true,
cull_mode: None,
..default()
}),
transform: Transform::from_scale(Vec3::splat(1_000_000.0)),
Mesh3d(meshes.add(Cuboid::new(2.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Srgba::hex("888888").unwrap().into(),
unlit: true,
cull_mode: None,
..default()
},
})),
Transform::from_scale(Vec3::splat(1_000_000.0)),
NotShadowCaster,
NotShadowReceiver,
));
@ -266,12 +256,9 @@ fn setup_parallax(
..default()
});
commands.spawn((
PbrBundle {
mesh: meshes.add(cube),
material: parallax_material,
transform: Transform::from_xyz(0.4, 0.2, -0.8),
..default()
},
Mesh3d(meshes.add(cube)),
MeshMaterial3d(parallax_material),
Transform::from_xyz(0.4, 0.2, -0.8),
Spin { speed: 0.3 },
));
}

View file

@ -194,8 +194,8 @@ fn tweak_scene(
mut materials: ResMut<Assets<StandardMaterial>>,
mut lights: Query<&mut DirectionalLight, Changed<DirectionalLight>>,
mut named_entities: Query<
(Entity, &Name, &Handle<StandardMaterial>),
(With<Handle<Mesh>>, Without<Lightmap>),
(Entity, &Name, &MeshMaterial3d<StandardMaterial>),
(With<Mesh3d>, Without<Lightmap>),
>,
) {
// Turn on shadows.

View file

@ -59,30 +59,25 @@ fn setup_pyramid_scene(
// pillars
for (x, z) in &[(-1.5, -1.5), (1.5, -1.5), (1.5, 1.5), (-1.5, 1.5)] {
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 3.0, 1.0)),
material: stone.clone(),
transform: Transform::from_xyz(*x, 1.5, *z),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 3.0, 1.0))),
MeshMaterial3d(stone.clone()),
Transform::from_xyz(*x, 1.5, *z),
));
}
// orb
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::default()),
material: materials.add(StandardMaterial {
base_color: Srgba::hex("126212CC").unwrap().into(),
reflectance: 1.0,
perceptual_roughness: 0.0,
metallic: 0.5,
alpha_mode: AlphaMode::Blend,
..default()
}),
transform: Transform::from_scale(Vec3::splat(1.75))
.with_translation(Vec3::new(0.0, 4.0, 0.0)),
Mesh3d(meshes.add(Sphere::default())),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Srgba::hex("126212CC").unwrap().into(),
reflectance: 1.0,
perceptual_roughness: 0.0,
metallic: 0.5,
alpha_mode: AlphaMode::Blend,
..default()
},
})),
Transform::from_scale(Vec3::splat(1.75)).with_translation(Vec3::new(0.0, 4.0, 0.0)),
NotShadowCaster,
NotShadowReceiver,
));
@ -91,26 +86,24 @@ fn setup_pyramid_scene(
for i in 0..50 {
let half_size = i as f32 / 2.0 + 3.0;
let y = -i as f32 / 2.0;
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(2.0 * half_size, 0.5, 2.0 * half_size)),
material: stone.clone(),
transform: Transform::from_xyz(0.0, y + 0.25, 0.0),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(2.0 * half_size, 0.5, 2.0 * half_size))),
MeshMaterial3d(stone.clone()),
Transform::from_xyz(0.0, y + 0.25, 0.0),
));
}
// sky
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(2.0, 1.0, 1.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(2.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Srgba::hex("888888").unwrap().into(),
unlit: true,
cull_mode: None,
..default()
}),
transform: Transform::from_scale(Vec3::splat(1_000_000.0)),
..default()
});
})),
Transform::from_scale(Vec3::splat(1_000_000.0)),
));
// light
commands.spawn((

View file

@ -36,16 +36,13 @@ fn setup(
// Create and save a handle to the mesh.
let cube_mesh_handle: Handle<Mesh> = meshes.add(create_cube_mesh());
// Render the mesh with the custom texture using a PbrBundle, add the marker.
// Render the mesh with the custom texture, and add the marker.
commands.spawn((
PbrBundle {
mesh: cube_mesh_handle,
material: materials.add(StandardMaterial {
base_color_texture: Some(custom_texture_handle),
..default()
}),
Mesh3d(cube_mesh_handle),
MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: Some(custom_texture_handle),
..default()
},
})),
CustomUV,
));
@ -81,7 +78,7 @@ fn setup(
// check out examples/input/ for more examples about user input.
fn input_handler(
keyboard_input: Res<ButtonInput<KeyCode>>,
mesh_query: Query<&Handle<Mesh>, With<CustomUV>>,
mesh_query: Query<&Mesh3d, With<CustomUV>>,
mut meshes: ResMut<Assets<Mesh>>,
mut query: Query<&mut Transform, With<CustomUV>>,
time: Res<Time>,

View file

@ -272,13 +272,11 @@ fn spawn_light(commands: &mut Commands) {
fn spawn_sphere(commands: &mut Commands, assets: &ExampleAssets) {
commands
.spawn(PbrBundle {
mesh: assets.main_sphere.clone(),
material: assets.main_sphere_material.clone(),
transform: Transform::from_xyz(0.0, SPHERE_SCALE, 0.0)
.with_scale(Vec3::splat(SPHERE_SCALE)),
..default()
})
.spawn((
Mesh3d(assets.main_sphere.clone()),
MeshMaterial3d(assets.main_sphere_material.clone()),
Transform::from_xyz(0.0, SPHERE_SCALE, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
))
.insert(MainObject);
}
@ -390,7 +388,7 @@ fn change_main_object(
mut app_status: ResMut<AppStatus>,
mut sphere_query: Query<
&mut Visibility,
(With<MainObject>, With<Handle<Mesh>>, Without<Handle<Scene>>),
(With<MainObject>, With<Mesh3d>, Without<Handle<Scene>>),
>,
mut fox_query: Query<&mut Visibility, (With<MainObject>, With<Handle<Scene>>)>,
) {
@ -597,13 +595,12 @@ fn create_cubes(
let uvw = (uvec3(x, y, z).as_vec3() + 0.5) * scale - 0.5;
let pos = global_transform.transform_point(uvw);
let voxel_cube = commands
.spawn(MaterialMeshBundle {
mesh: example_assets.voxel_cube.clone(),
material: voxel_cube_material.clone(),
transform: Transform::from_scale(Vec3::splat(VOXEL_CUBE_SCALE))
.spawn((
Mesh3d(example_assets.voxel_cube.clone()),
MeshMaterial3d(voxel_cube_material.clone()),
Transform::from_scale(Vec3::splat(VOXEL_CUBE_SCALE))
.with_translation(pos),
..default()
})
))
.insert(VoxelCube)
.insert(NotShadowCaster)
.id();

View file

@ -39,86 +39,74 @@ fn setup(
asset_server: Res<AssetServer>,
) {
// ground plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(10.0, 10.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(10.0, 10.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::WHITE,
perceptual_roughness: 1.0,
..default()
}),
..default()
});
})),
));
// left wall
let mut transform = Transform::from_xyz(2.5, 2.5, 0.0);
transform.rotate_z(PI / 2.);
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(5.0, 0.15, 5.0)),
transform,
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(5.0, 0.15, 5.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: INDIGO.into(),
perceptual_roughness: 1.0,
..default()
}),
..default()
});
})),
transform,
));
// back (right) wall
let mut transform = Transform::from_xyz(0.0, 2.5, -2.5);
transform.rotate_x(PI / 2.);
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(5.0, 0.15, 5.0)),
transform,
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(5.0, 0.15, 5.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: INDIGO.into(),
perceptual_roughness: 1.0,
..default()
}),
..default()
});
})),
transform,
));
// Bevy logo to demonstrate alpha mask shadows
let mut transform = Transform::from_xyz(-2.2, 0.5, 1.0);
transform.rotate_y(PI / 8.);
commands.spawn((
PbrBundle {
mesh: meshes.add(Rectangle::new(2.0, 0.5)),
transform,
material: materials.add(StandardMaterial {
base_color_texture: Some(asset_server.load("branding/bevy_logo_light.png")),
perceptual_roughness: 1.0,
alpha_mode: AlphaMode::Mask(0.5),
cull_mode: None,
..default()
}),
Mesh3d(meshes.add(Rectangle::new(2.0, 0.5))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: Some(asset_server.load("branding/bevy_logo_light.png")),
perceptual_roughness: 1.0,
alpha_mode: AlphaMode::Mask(0.5),
cull_mode: None,
..default()
},
})),
transform,
Movable,
));
// cube
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(StandardMaterial {
base_color: DEEP_PINK.into(),
..default()
}),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: DEEP_PINK.into(),
..default()
},
})),
Transform::from_xyz(0.0, 0.5, 0.0),
Movable,
));
// sphere
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(0.5).mesh().uv(32, 18)),
material: materials.add(StandardMaterial {
base_color: LIMEGREEN.into(),
..default()
}),
transform: Transform::from_xyz(1.5, 1.0, 1.5),
Mesh3d(meshes.add(Sphere::new(0.5).mesh().uv(32, 18))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: LIMEGREEN.into(),
..default()
},
})),
Transform::from_xyz(1.5, 1.0, 1.5),
Movable,
));
@ -140,15 +128,14 @@ fn setup(
Transform::from_xyz(1.0, 2.0, 0.0),
))
.with_children(|builder| {
builder.spawn(PbrBundle {
mesh: meshes.add(Sphere::new(0.1).mesh().uv(32, 18)),
material: materials.add(StandardMaterial {
builder.spawn((
Mesh3d(meshes.add(Sphere::new(0.1).mesh().uv(32, 18))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: RED.into(),
emissive: LinearRgba::new(4.0, 0.0, 0.0, 0.0),
..default()
}),
..default()
});
})),
));
});
// green spot light
@ -164,18 +151,15 @@ fn setup(
},
Transform::from_xyz(-1.0, 2.0, 0.0).looking_at(Vec3::new(-1.0, 0.0, 0.0), Vec3::Z),
))
.with_children(|builder| {
builder.spawn(PbrBundle {
transform: Transform::from_rotation(Quat::from_rotation_x(PI / 2.0)),
mesh: meshes.add(Capsule3d::new(0.1, 0.125)),
material: materials.add(StandardMaterial {
base_color: LIME.into(),
emissive: LinearRgba::new(0.0, 4.0, 0.0, 0.0),
..default()
}),
.with_child((
Mesh3d(meshes.add(Capsule3d::new(0.1, 0.125))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: LIME.into(),
emissive: LinearRgba::new(0.0, 4.0, 0.0, 0.0),
..default()
});
});
})),
Transform::from_rotation(Quat::from_rotation_x(PI / 2.0)),
));
// blue point light
commands
@ -189,15 +173,14 @@ fn setup(
Transform::from_xyz(0.0, 4.0, 0.0),
))
.with_children(|builder| {
builder.spawn(PbrBundle {
mesh: meshes.add(Sphere::new(0.1).mesh().uv(32, 18)),
material: materials.add(StandardMaterial {
builder.spawn((
Mesh3d(meshes.add(Sphere::new(0.1).mesh().uv(32, 18))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: BLUE.into(),
emissive: LinearRgba::new(0.0, 0.0, 713.0, 0.0),
..default()
}),
..default()
});
})),
));
});
// directional 'sun' light

View file

@ -29,8 +29,8 @@ fn add_lightmaps_to_meshes(
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<StandardMaterial>>,
meshes: Query<
(Entity, &Name, &Handle<StandardMaterial>),
(With<Handle<Mesh>>, Without<Lightmap>),
(Entity, &Name, &MeshMaterial3d<StandardMaterial>),
(With<Mesh3d>, Without<Lightmap>),
>,
) {
let exposure = 250.0;

View file

@ -30,35 +30,33 @@ fn setup(
mut materials: ResMut<Assets<LineMaterial>>,
) {
// Spawn a list of lines with start and end points for each lines
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(LineList {
commands.spawn((
Mesh3d(meshes.add(LineList {
lines: vec![
(Vec3::ZERO, Vec3::new(1.0, 1.0, 0.0)),
(Vec3::new(1.0, 1.0, 0.0), Vec3::new(1.0, 0.0, 0.0)),
],
}),
transform: Transform::from_xyz(-1.5, 0.0, 0.0),
material: materials.add(LineMaterial {
})),
MeshMaterial3d(materials.add(LineMaterial {
color: LinearRgba::GREEN,
}),
..default()
});
})),
Transform::from_xyz(-1.5, 0.0, 0.0),
));
// Spawn a line strip that goes from point to point
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(LineStrip {
commands.spawn((
Mesh3d(meshes.add(LineStrip {
points: vec![
Vec3::ZERO,
Vec3::new(1.0, 1.0, 0.0),
Vec3::new(1.0, 0.0, 0.0),
],
}),
transform: Transform::from_xyz(0.5, 0.0, 0.0),
material: materials.add(LineMaterial {
})),
MeshMaterial3d(materials.add(LineMaterial {
color: LinearRgba::BLUE,
}),
..default()
});
})),
Transform::from_xyz(0.5, 0.0, 0.0),
));
// camera
commands.spawn(Camera3dBundle {

View file

@ -119,15 +119,14 @@ fn setup(
});
}
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: standard_materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(standard_materials.add(StandardMaterial {
base_color: Color::WHITE,
perceptual_roughness: 1.0,
..default()
}),
..default()
});
})),
));
}
#[derive(Asset, TypePath, AsBindGroup, Clone, Default)]

View file

@ -76,32 +76,30 @@ fn setup_scene(
Transform::default().looking_to(Vec3::new(-1.0, -0.7, -1.0), Vec3::X),
));
// Sky
commands.spawn(PbrBundle {
mesh: meshes.add(Sphere::default()),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Sphere::default())),
MeshMaterial3d(materials.add(StandardMaterial {
unlit: true,
base_color: Color::linear_rgb(0.1, 0.6, 1.0),
..default()
}),
transform: Transform::default().with_scale(Vec3::splat(-4000.0)),
..default()
});
})),
Transform::default().with_scale(Vec3::splat(-4000.0)),
));
// Ground
let mut plane: Mesh = Plane3d::default().into();
let uv_size = 4000.0;
let uvs = vec![[uv_size, 0.0], [0.0, 0.0], [0.0, uv_size], [uv_size; 2]];
plane.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
commands.spawn(PbrBundle {
mesh: meshes.add(plane),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(plane)),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::WHITE,
perceptual_roughness: 1.0,
base_color_texture: Some(images.add(uv_debug_texture())),
..default()
}),
transform: Transform::from_xyz(0.0, -0.65, 0.0).with_scale(Vec3::splat(80.)),
..default()
});
})),
Transform::from_xyz(0.0, -0.65, 0.0).with_scale(Vec3::splat(80.)),
));
spawn_cars(&asset_server, &mut meshes, &mut materials, &mut commands);
spawn_trees(&mut meshes, &mut materials, &mut commands);
@ -146,33 +144,25 @@ fn spawn_cars(
let color = colors[i % colors.len()].clone();
let mut entity = commands
.spawn((
PbrBundle {
mesh: box_mesh.clone(),
material: color.clone(),
transform: Transform::from_scale(Vec3::splat(0.5)),
..default()
},
Mesh3d(box_mesh.clone()),
MeshMaterial3d(color.clone()),
Transform::from_scale(Vec3::splat(0.5)),
Moves(i as f32 * 2.0),
))
.insert_if(CameraTracked, || i == 0);
entity.with_children(|parent| {
parent.spawn(PbrBundle {
mesh: box_mesh.clone(),
material: color,
transform: Transform::from_xyz(0.0, 0.08, 0.03)
.with_scale(Vec3::new(1.0, 1.0, 0.5)),
..default()
});
parent.spawn((
Mesh3d(box_mesh.clone()),
MeshMaterial3d(color),
Transform::from_xyz(0.0, 0.08, 0.03).with_scale(Vec3::new(1.0, 1.0, 0.5)),
));
let mut spawn_wheel = |x: f32, z: f32| {
parent.spawn((
PbrBundle {
mesh: cylinder.clone(),
material: wheel_matl.clone(),
transform: Transform::from_xyz(0.14 * x, -0.045, 0.15 * z)
.with_scale(Vec3::new(0.15, 0.04, 0.15))
.with_rotation(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2)),
..default()
},
Mesh3d(cylinder.clone()),
MeshMaterial3d(wheel_matl.clone()),
Transform::from_xyz(0.14 * x, -0.045, 0.15 * z)
.with_scale(Vec3::new(0.15, 0.04, 0.15))
.with_rotation(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2)),
Rotates,
));
};
@ -202,12 +192,11 @@ fn spawn_barriers(
offset,
(i as f32) / (N_CONES as f32) * std::f32::consts::PI * 2.0,
);
commands.spawn(PbrBundle {
mesh: capsule.clone(),
material: matl.clone(),
transform: Transform::from_xyz(pos.x, -0.65, pos.y).with_scale(Vec3::splat(0.07)),
..default()
});
commands.spawn((
Mesh3d(capsule.clone()),
MeshMaterial3d(matl.clone()),
Transform::from_xyz(pos.x, -0.65, pos.y).with_scale(Vec3::splat(0.07)),
));
}
};
spawn_with_offset(0.04);
@ -232,18 +221,16 @@ fn spawn_trees(
(i as f32) / (N_TREES as f32) * std::f32::consts::PI * 2.0,
);
let [x, z] = pos.into();
commands.spawn(PbrBundle {
mesh: sphere.clone(),
material: leaves.clone(),
transform: Transform::from_xyz(x, -0.3, z).with_scale(Vec3::splat(0.3)),
..default()
});
commands.spawn(PbrBundle {
mesh: capsule.clone(),
material: trunk.clone(),
transform: Transform::from_xyz(x, -0.5, z).with_scale(Vec3::new(0.05, 0.3, 0.05)),
..default()
});
commands.spawn((
Mesh3d(sphere.clone()),
MeshMaterial3d(leaves.clone()),
Transform::from_xyz(x, -0.3, z).with_scale(Vec3::splat(0.3)),
));
commands.spawn((
Mesh3d(capsule.clone()),
MeshMaterial3d(trunk.clone()),
Transform::from_xyz(x, -0.5, z).with_scale(Vec3::new(0.05, 0.3, 0.05)),
));
}
};
spawn_with_offset(0.07);

View file

@ -28,36 +28,31 @@ fn setup(
});
// plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// cubes
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(1.5, 0.5, 1.5),
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(1.5, 0.5, -1.5),
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(-1.5, 0.5, 1.5),
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(-1.5, 0.5, -1.5),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(1.5, 0.5, 1.5),
));
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(1.5, 0.5, -1.5),
));
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(-1.5, 0.5, 1.5),
));
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(-1.5, 0.5, -1.5),
));
// light
commands.spawn((PointLight::default(), Transform::from_xyz(3.0, 8.0, 5.0)));
}

View file

@ -231,22 +231,21 @@ fn setup(
.with_children(|commands| {
// represent the light source as a sphere
let mesh = meshes.add(Sphere::new(0.05).mesh().ico(3).unwrap());
commands.spawn(PbrBundle { mesh, ..default() });
commands.spawn((Mesh3d(mesh), MeshMaterial3d(materials.add(Color::WHITE))));
});
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(10.0, 10.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(10.0, 10.0))),
MeshMaterial3d(materials.add(StandardMaterial {
// standard material derived from dark green, but
// with roughness and reflectance set.
perceptual_roughness: 0.45,
reflectance: 0.18,
..Color::srgb_u8(0, 80, 0).into()
}),
transform: Transform::from_xyz(0.0, -1.0, 0.0),
..default()
});
})),
Transform::from_xyz(0.0, -1.0, 0.0),
));
let parallax_depth_scale = TargetDepth::default().0;
let max_parallax_layer_count = ops::exp2(TargetLayers::default().0);
@ -264,17 +263,16 @@ fn setup(
..default()
});
commands.spawn((
PbrBundle {
mesh: meshes.add(
Mesh3d(
meshes.add(
// NOTE: for normal maps and depth maps to work, the mesh
// needs tangents generated.
Mesh::from(Cuboid::default())
.with_generated_tangents()
.unwrap(),
),
material: parallax_material.clone_weak(),
..default()
},
),
MeshMaterial3d(parallax_material.clone()),
Spin { speed: 0.3 },
));
@ -286,12 +284,9 @@ fn setup(
let background_cube_bundle = |translation| {
(
PbrBundle {
transform: Transform::from_translation(translation),
mesh: background_cube.clone(),
material: parallax_material.clone(),
..default()
},
Mesh3d(background_cube.clone()),
MeshMaterial3d(parallax_material.clone()),
Transform::from_translation(translation),
Spin { speed: -0.1 },
)
};

View file

@ -37,22 +37,18 @@ fn setup(
// parent cube
commands
.spawn((
PbrBundle {
mesh: cube_handle.clone(),
material: cube_material_handle.clone(),
transform: Transform::from_xyz(0.0, 0.0, 1.0),
..default()
},
Mesh3d(cube_handle.clone()),
MeshMaterial3d(cube_material_handle.clone()),
Transform::from_xyz(0.0, 0.0, 1.0),
Rotator,
))
.with_children(|parent| {
// child cube
parent.spawn(PbrBundle {
mesh: cube_handle,
material: cube_material_handle,
transform: Transform::from_xyz(0.0, 0.0, 3.0),
..default()
});
parent.spawn((
Mesh3d(cube_handle),
MeshMaterial3d(cube_material_handle),
Transform::from_xyz(0.0, 0.0, 3.0),
));
});
// light
commands.spawn((PointLight::default(), Transform::from_xyz(4.0, 5.0, -4.0)));

View file

@ -24,32 +24,30 @@ fn setup(
let x01 = (x + 5) as f32 / 10.0;
let y01 = (y + 2) as f32 / 4.0;
// sphere
commands.spawn(PbrBundle {
mesh: sphere_mesh.clone(),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(sphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Srgba::hex("#ffd891").unwrap().into(),
// vary key PBR parameters on a grid of spheres to show the effect
metallic: y01,
perceptual_roughness: x01,
..default()
}),
transform: Transform::from_xyz(x as f32, y as f32 + 0.5, 0.0),
..default()
});
})),
Transform::from_xyz(x as f32, y as f32 + 0.5, 0.0),
));
}
}
// unlit sphere
commands.spawn(PbrBundle {
mesh: sphere_mesh,
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(sphere_mesh),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Srgba::hex("#ffd891").unwrap().into(),
// vary key PBR parameters on a grid of spheres to show the effect
unlit: true,
..default()
}),
transform: Transform::from_xyz(-5.0, -2.5, 0.0),
..default()
});
})),
Transform::from_xyz(-5.0, -2.5, 0.0),
));
commands.spawn((
DirectionalLight {

View file

@ -124,17 +124,15 @@ fn spawn_sphere(
let sphere_mesh = meshes.add(Sphere::new(1.0).mesh().ico(7).unwrap());
// Create a sphere.
commands.spawn(PbrBundle {
mesh: sphere_mesh.clone(),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(sphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Srgba::hex("#ffd891").unwrap().into(),
metallic: 1.0,
perceptual_roughness: 0.0,
..StandardMaterial::default()
}),
transform: Transform::default(),
..PbrBundle::default()
});
})),
));
}
// Spawns the reflection probe.

View file

@ -66,12 +66,9 @@ fn setup(
// The cube that will be rendered to the texture.
commands.spawn((
PbrBundle {
mesh: cube_handle,
material: cube_material_handle,
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
..default()
},
Mesh3d(cube_handle),
MeshMaterial3d(cube_material_handle),
Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
FirstPassCube,
first_pass_layer.clone(),
));
@ -113,13 +110,9 @@ fn setup(
// Main pass cube, with material containing the rendered first pass texture.
commands.spawn((
PbrBundle {
mesh: cube_handle,
material: material_handle,
transform: Transform::from_xyz(0.0, 0.0, 1.5)
.with_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
},
Mesh3d(cube_handle),
MeshMaterial3d(material_handle),
Transform::from_xyz(0.0, 0.0, 1.5).with_rotation(Quat::from_rotation_x(-PI / 5.0)),
MainPassCube,
));

View file

@ -63,9 +63,9 @@ fn spawn_sphere(
asset_server: &AssetServer,
sphere_mesh: &Handle<Mesh>,
) {
commands.spawn(PbrBundle {
mesh: sphere_mesh.clone(),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(sphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
clearcoat: 1.0,
clearcoat_perceptual_roughness: 0.3,
clearcoat_normal_texture: Some(asset_server.load_with_settings(
@ -76,10 +76,9 @@ fn spawn_sphere(
perceptual_roughness: 0.1,
base_color: GOLD.into(),
..default()
}),
transform: Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::splat(1.25)),
..default()
});
})),
Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::splat(1.25)),
));
}
/// Spawns a light.

View file

@ -79,24 +79,22 @@ fn setup(
));
// Spawn ground mesh.
commands.spawn(PbrBundle {
transform: Transform::from_xyz(0.0, -0.5, 0.0),
mesh: meshes.add(Cuboid::new(64.0, 1.0, 64.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(64.0, 1.0, 64.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::BLACK,
perceptual_roughness: 1.0,
..default()
}),
..default()
});
})),
Transform::from_xyz(0.0, -0.5, 0.0),
));
// Spawn pillar standing between the camera and the sun.
commands.spawn(PbrBundle {
transform: Transform::from_xyz(-10.0, 4.5, -11.0),
mesh: meshes.add(Cuboid::new(2.0, 9.0, 2.0)),
material: materials.add(Color::BLACK),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(2.0, 9.0, 2.0))),
MeshMaterial3d(materials.add(Color::BLACK)),
Transform::from_xyz(-10.0, 4.5, -11.0),
));
// Load a repeating 3d noise texture. Make sure to set ImageAddressMode to Repeat
// so that the texture wraps around as the density texture offset is moved along.

View file

@ -83,10 +83,10 @@ fn setup(
));
for z_i32 in (-spawn_plane_depth as i32..=0).step_by(2) {
commands.spawn(PbrBundle {
mesh: sphere_handle.clone(),
material: white_handle.clone(),
transform: Transform::from_xyz(
commands.spawn((
Mesh3d(sphere_handle.clone()),
MeshMaterial3d(white_handle.clone()),
Transform::from_xyz(
0.0,
if z_i32 % 4 == 0 {
spawn_height
@ -95,17 +95,15 @@ fn setup(
},
z_i32 as f32,
),
..default()
});
));
}
// ground plane
let plane_size = 2.0 * spawn_plane_depth;
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(plane_size, plane_size)),
material: white_handle,
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(plane_size, plane_size))),
MeshMaterial3d(white_handle),
));
let style = TextStyle::default();

View file

@ -40,42 +40,34 @@ fn setup(
let sphere_handle = meshes.add(Sphere::new(sphere_radius));
// sphere - initially a caster
commands.spawn(PbrBundle {
mesh: sphere_handle.clone(),
material: materials.add(Color::from(RED)),
transform: Transform::from_xyz(-1.0, spawn_height, 0.0),
..default()
});
commands.spawn((
Mesh3d(sphere_handle.clone()),
MeshMaterial3d(materials.add(Color::from(RED))),
Transform::from_xyz(-1.0, spawn_height, 0.0),
));
// sphere - initially not a caster
commands.spawn((
PbrBundle {
mesh: sphere_handle,
material: materials.add(Color::from(BLUE)),
transform: Transform::from_xyz(1.0, spawn_height, 0.0),
..default()
},
Mesh3d(sphere_handle),
MeshMaterial3d(materials.add(Color::from(BLUE))),
Transform::from_xyz(1.0, spawn_height, 0.0),
NotShadowCaster,
));
// floating plane - initially not a shadow receiver and not a caster
commands.spawn((
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(20.0, 20.0)),
material: materials.add(Color::from(LIME)),
transform: Transform::from_xyz(0.0, 1.0, -10.0),
..default()
},
Mesh3d(meshes.add(Plane3d::default().mesh().size(20.0, 20.0))),
MeshMaterial3d(materials.add(Color::from(LIME))),
Transform::from_xyz(0.0, 1.0, -10.0),
NotShadowCaster,
NotShadowReceiver,
));
// lower ground plane - initially a shadow receiver
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(20.0, 20.0)),
material: white_handle,
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(20.0, 20.0))),
MeshMaterial3d(white_handle),
));
println!("Using DirectionalLight");
@ -142,10 +134,10 @@ fn toggle_shadows(
mut commands: Commands,
input: Res<ButtonInput<KeyCode>>,
mut queries: ParamSet<(
Query<Entity, (With<Handle<Mesh>>, With<NotShadowCaster>)>,
Query<Entity, (With<Handle<Mesh>>, With<NotShadowReceiver>)>,
Query<Entity, (With<Handle<Mesh>>, Without<NotShadowCaster>)>,
Query<Entity, (With<Handle<Mesh>>, Without<NotShadowReceiver>)>,
Query<Entity, (With<Mesh3d>, With<NotShadowCaster>)>,
Query<Entity, (With<Mesh3d>, With<NotShadowReceiver>)>,
Query<Entity, (With<Mesh3d>, Without<NotShadowCaster>)>,
Query<Entity, (With<Mesh3d>, Without<NotShadowReceiver>)>,
)>,
) {
if input.just_pressed(KeyCode::KeyC) {

View file

@ -25,15 +25,14 @@ fn setup(
});
// plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(100.0, 100.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(100.0, 100.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.2, 0.2, 0.2),
perceptual_roughness: 0.08,
..default()
}),
..default()
});
})),
));
const COUNT: usize = 6;
let position_range = -2.0..2.0;
@ -48,17 +47,16 @@ fn setup(
// sphere light
commands
.spawn(PbrBundle {
mesh: mesh.clone(),
material: materials.add(StandardMaterial {
.spawn((
Mesh3d(mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.5, 0.5, 1.0),
unlit: true,
..default()
}),
transform: Transform::from_xyz(position_range.start + percent * pos_len, 0.3, 0.0)
})),
Transform::from_xyz(position_range.start + percent * pos_len, 0.3, 0.0)
.with_scale(Vec3::splat(radius)),
..default()
})
))
.with_child(PointLight {
radius,
color: Color::srgb(0.2, 0.2, 1.0),

View file

@ -22,11 +22,10 @@ fn setup(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(100.0, 100.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(100.0, 100.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
commands.spawn(SceneBundle {
scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")),

View file

@ -41,11 +41,8 @@ fn setup(
) {
// ground plane
commands.spawn((
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(100.0, 100.0)),
material: materials.add(Color::WHITE),
..default()
},
Mesh3d(meshes.add(Plane3d::default().mesh().size(100.0, 100.0))),
MeshMaterial3d(materials.add(Color::WHITE)),
Movable,
));
@ -64,12 +61,9 @@ fn setup(
let z = rng.gen_range(-5.0..5.0);
(
PbrBundle {
mesh: cube_mesh.clone(),
material: blue.clone(),
transform: Transform::from_xyz(x, y, z),
..default()
},
Mesh3d(cube_mesh.clone()),
MeshMaterial3d(blue.clone()),
Transform::from_xyz(x, y, z),
Movable,
)
})
@ -108,18 +102,14 @@ fn setup(
.looking_at(Vec3::new(1.0 + x, 0.0, z), Vec3::X),
))
.with_children(|builder| {
builder.spawn(PbrBundle {
mesh: sphere_mesh.clone(),
material: red_emissive.clone(),
..default()
});
builder.spawn((
PbrBundle {
transform: Transform::from_translation(Vec3::Z * -0.1),
mesh: sphere_mesh_direction.clone(),
material: maroon_emissive.clone(),
..default()
},
Mesh3d(sphere_mesh.clone()),
MeshMaterial3d(red_emissive.clone()),
));
builder.spawn((
Mesh3d(sphere_mesh_direction.clone()),
MeshMaterial3d(maroon_emissive.clone()),
Transform::from_translation(Vec3::Z * -0.1),
NotShadowCaster,
));
});

View file

@ -48,35 +48,29 @@ fn setup(
reflectance: 0.0,
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: material.clone(),
transform: Transform::from_xyz(0.0, 0.0, 1.0),
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: material.clone(),
transform: Transform::from_xyz(0.0, -1.0, 0.0),
..default()
});
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material,
transform: Transform::from_xyz(1.0, 0.0, 0.0),
..default()
});
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(0.4).mesh().uv(72, 36)),
material: materials.add(StandardMaterial {
base_color: Color::srgb(0.4, 0.4, 0.4),
perceptual_roughness: 1.0,
reflectance: 0.0,
..default()
}),
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(material.clone()),
Transform::from_xyz(0.0, 0.0, 1.0),
));
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(material.clone()),
Transform::from_xyz(0.0, -1.0, 0.0),
));
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(material),
Transform::from_xyz(1.0, 0.0, 0.0),
));
commands.spawn((
Mesh3d(meshes.add(Sphere::new(0.4).mesh().uv(72, 36))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.4, 0.4, 0.4),
perceptual_roughness: 1.0,
reflectance: 0.0,
..default()
},
})),
SphereMarker,
));

View file

@ -149,16 +149,15 @@ fn spawn_cube(
standard_materials: &mut Assets<StandardMaterial>,
) {
commands
.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: standard_materials.add(StandardMaterial {
.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(standard_materials.add(StandardMaterial {
base_color: Color::from(WHITE),
base_color_texture: Some(asset_server.load("branding/icon.png")),
..default()
}),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
})
})),
Transform::from_xyz(0.0, 0.5, 0.0),
))
.insert(CubeModel);
}
@ -182,9 +181,9 @@ fn spawn_water(
meshes: &mut Assets<Mesh>,
water_materials: &mut Assets<ExtendedMaterial<StandardMaterial, Water>>,
) {
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0))),
material: water_materials.add(ExtendedMaterial {
commands.spawn((
Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0)))),
MeshMaterial3d(water_materials.add(ExtendedMaterial {
base: StandardMaterial {
base_color: BLACK.into(),
perceptual_roughness: 0.0,
@ -215,10 +214,9 @@ fn spawn_water(
octave_strengths: vec4(0.16, 0.18, 0.093, 0.044),
},
},
}),
transform: Transform::from_scale(Vec3::splat(100.0)),
..default()
});
})),
Transform::from_scale(Vec3::splat(100.0)),
));
}
// Spawns the camera.

View file

@ -53,28 +53,23 @@ fn setup(
});
// textured quad - normal
commands.spawn(PbrBundle {
mesh: quad_handle.clone(),
material: material_handle,
transform: Transform::from_xyz(0.0, 0.0, 1.5)
.with_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
});
commands.spawn((
Mesh3d(quad_handle.clone()),
MeshMaterial3d(material_handle),
Transform::from_xyz(0.0, 0.0, 1.5).with_rotation(Quat::from_rotation_x(-PI / 5.0)),
));
// textured quad - modulated
commands.spawn(PbrBundle {
mesh: quad_handle.clone(),
material: red_material_handle,
transform: Transform::from_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
});
commands.spawn((
Mesh3d(quad_handle.clone()),
MeshMaterial3d(red_material_handle),
Transform::from_rotation(Quat::from_rotation_x(-PI / 5.0)),
));
// textured quad - modulated
commands.spawn(PbrBundle {
mesh: quad_handle,
material: blue_material_handle,
transform: Transform::from_xyz(0.0, 0.0, -1.5)
.with_rotation(Quat::from_rotation_x(-PI / 5.0)),
..default()
});
commands.spawn((
Mesh3d(quad_handle),
MeshMaterial3d(blue_material_handle),
Transform::from_xyz(0.0, 0.0, -1.5).with_rotation(Quat::from_rotation_x(-PI / 5.0)),
));
// camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(3.0, 5.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y),

View file

@ -144,13 +144,10 @@ fn setup_color_gradient_scene(
transform.translation += *transform.forward();
commands.spawn((
MaterialMeshBundle {
mesh: meshes.add(Rectangle::new(0.7, 0.7)),
material: materials.add(ColorGradientMaterial {}),
transform,
visibility: Visibility::Hidden,
..default()
},
Mesh3d(meshes.add(Rectangle::new(0.7, 0.7))),
MeshMaterial3d(materials.add(ColorGradientMaterial {})),
transform,
Visibility::Hidden,
SceneNumber(2),
));
}
@ -166,17 +163,14 @@ fn setup_image_viewer_scene(
// exr/hdr viewer (exr requires enabling bevy feature)
commands.spawn((
PbrBundle {
mesh: meshes.add(Rectangle::default()),
material: materials.add(StandardMaterial {
base_color_texture: None,
unlit: true,
..default()
}),
transform,
visibility: Visibility::Hidden,
Mesh3d(meshes.add(Rectangle::default())),
MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: None,
unlit: true,
..default()
},
})),
transform,
Visibility::Hidden,
SceneNumber(3),
HDRViewer,
));
@ -205,7 +199,7 @@ fn setup_image_viewer_scene(
// ----------------------------------------------------------------------------
fn drag_drop_image(
image_mat: Query<&Handle<StandardMaterial>, With<HDRViewer>>,
image_mat: Query<&MeshMaterial3d<StandardMaterial>, With<HDRViewer>>,
text: Query<Entity, (With<Text>, With<SceneNumber>)>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut drop_events: EventReader<FileDragAndDrop>,
@ -234,7 +228,7 @@ fn drag_drop_image(
}
fn resize_image(
image_mesh: Query<(&Handle<StandardMaterial>, &Handle<Mesh>), With<HDRViewer>>,
image_mesh: Query<(&MeshMaterial3d<StandardMaterial>, &Mesh3d), With<HDRViewer>>,
materials: Res<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
images: Res<Assets<Image>>,

View file

@ -77,17 +77,14 @@ fn setup(
// Cube #1
commands.spawn((
PbrBundle {
mesh: cube_mesh.clone(),
material: materials.add(StandardMaterial::default()),
transform: Transform::from_xyz(0.25, 0.5, -2.0).with_rotation(Quat::from_euler(
EulerRot::XYZ,
1.4,
3.7,
21.3,
)),
..default()
},
Mesh3d(cube_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial::default())),
Transform::from_xyz(0.25, 0.5, -2.0).with_rotation(Quat::from_euler(
EulerRot::XYZ,
1.4,
3.7,
21.3,
)),
ExampleControls {
color: true,
specular_transmission: false,
@ -97,17 +94,14 @@ fn setup(
// Cube #2
commands.spawn((
PbrBundle {
mesh: cube_mesh,
material: materials.add(StandardMaterial::default()),
transform: Transform::from_xyz(-0.75, 0.7, -2.0).with_rotation(Quat::from_euler(
EulerRot::XYZ,
0.4,
2.3,
4.7,
)),
..default()
},
Mesh3d(cube_mesh),
MeshMaterial3d(materials.add(StandardMaterial::default())),
Transform::from_xyz(-0.75, 0.7, -2.0).with_rotation(Quat::from_euler(
EulerRot::XYZ,
0.4,
2.3,
4.7,
)),
ExampleControls {
color: true,
specular_transmission: false,
@ -117,18 +111,15 @@ fn setup(
// Candle
commands.spawn((
PbrBundle {
mesh: cylinder_mesh,
material: materials.add(StandardMaterial {
base_color: Color::srgb(0.9, 0.2, 0.3),
diffuse_transmission: 0.7,
perceptual_roughness: 0.32,
thickness: 0.2,
..default()
}),
transform: Transform::from_xyz(-1.0, 0.0, 0.0),
Mesh3d(cylinder_mesh),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.9, 0.2, 0.3),
diffuse_transmission: 0.7,
perceptual_roughness: 0.32,
thickness: 0.2,
..default()
},
})),
Transform::from_xyz(-1.0, 0.0, 0.0),
ExampleControls {
color: true,
specular_transmission: false,
@ -147,36 +138,30 @@ fn setup(
};
commands.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
emissive,
diffuse_transmission: 1.0,
..default()
}),
transform: Transform::from_xyz(-1.0, 1.15, 0.0).with_scale(Vec3::new(0.1, 0.2, 0.1)),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
emissive,
diffuse_transmission: 1.0,
..default()
},
})),
Transform::from_xyz(-1.0, 1.15, 0.0).with_scale(Vec3::new(0.1, 0.2, 0.1)),
Flicker,
NotShadowCaster,
));
// Glass Sphere
commands.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
base_color: Color::WHITE,
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
}),
transform: Transform::from_xyz(1.0, 0.0, 0.0),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::WHITE,
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
},
})),
Transform::from_xyz(1.0, 0.0, 0.0),
ExampleControls {
color: true,
specular_transmission: true,
@ -186,20 +171,17 @@ fn setup(
// R Sphere
commands.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
base_color: RED.into(),
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
}),
transform: Transform::from_xyz(1.0, -0.5, 2.0).with_scale(Vec3::splat(0.5)),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: RED.into(),
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
},
})),
Transform::from_xyz(1.0, -0.5, 2.0).with_scale(Vec3::splat(0.5)),
ExampleControls {
color: true,
specular_transmission: true,
@ -209,20 +191,17 @@ fn setup(
// G Sphere
commands.spawn((
PbrBundle {
mesh: icosphere_mesh.clone(),
material: materials.add(StandardMaterial {
base_color: LIME.into(),
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
}),
transform: Transform::from_xyz(0.0, -0.5, 2.0).with_scale(Vec3::splat(0.5)),
Mesh3d(icosphere_mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: LIME.into(),
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
},
})),
Transform::from_xyz(0.0, -0.5, 2.0).with_scale(Vec3::splat(0.5)),
ExampleControls {
color: true,
specular_transmission: true,
@ -232,20 +211,17 @@ fn setup(
// B Sphere
commands.spawn((
PbrBundle {
mesh: icosphere_mesh,
material: materials.add(StandardMaterial {
base_color: BLUE.into(),
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
}),
transform: Transform::from_xyz(-1.0, -0.5, 2.0).with_scale(Vec3::splat(0.5)),
Mesh3d(icosphere_mesh),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: BLUE.into(),
specular_transmission: 0.9,
diffuse_transmission: 1.0,
thickness: 1.8,
ior: 1.5,
perceptual_roughness: 0.12,
..default()
},
})),
Transform::from_xyz(-1.0, -0.5, 2.0).with_scale(Vec3::splat(0.5)),
ExampleControls {
color: true,
specular_transmission: true,
@ -271,16 +247,13 @@ fn setup(
for x in -3..4 {
for z in -3..4 {
commands.spawn((
PbrBundle {
mesh: plane_mesh.clone(),
material: if (x + z) % 2 == 0 {
black_material.clone()
} else {
white_material.clone()
},
transform: Transform::from_xyz(x as f32 * 2.0, -1.0, z as f32 * 2.0),
..default()
},
Mesh3d(plane_mesh.clone()),
MeshMaterial3d(if (x + z) % 2 == 0 {
black_material.clone()
} else {
white_material.clone()
}),
Transform::from_xyz(x as f32 * 2.0, -1.0, z as f32 * 2.0),
ExampleControls {
color: true,
specular_transmission: false,
@ -292,22 +265,19 @@ fn setup(
// Paper
commands.spawn((
PbrBundle {
mesh: plane_mesh,
material: materials.add(StandardMaterial {
base_color: Color::WHITE,
diffuse_transmission: 0.6,
perceptual_roughness: 0.8,
reflectance: 1.0,
double_sided: true,
cull_mode: None,
..default()
}),
transform: Transform::from_xyz(0.0, 0.5, -3.0)
.with_scale(Vec3::new(2.0, 1.0, 1.0))
.with_rotation(Quat::from_euler(EulerRot::XYZ, PI / 2.0, 0.0, 0.0)),
Mesh3d(plane_mesh),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::WHITE,
diffuse_transmission: 0.6,
perceptual_roughness: 0.8,
reflectance: 1.0,
double_sided: true,
cull_mode: None,
..default()
},
})),
Transform::from_xyz(0.0, 0.5, -3.0)
.with_scale(Vec3::new(2.0, 1.0, 1.0))
.with_rotation(Quat::from_euler(EulerRot::XYZ, PI / 2.0, 0.0, 0.0)),
TransmittedShadowReceiver,
ExampleControls {
specular_transmission: false,
@ -419,7 +389,7 @@ impl Default for ExampleState {
fn example_control_system(
mut commands: Commands,
mut materials: ResMut<Assets<StandardMaterial>>,
controllable: Query<(&Handle<StandardMaterial>, &ExampleControls)>,
controllable: Query<(&MeshMaterial3d<StandardMaterial>, &ExampleControls)>,
mut camera: Query<
(
Entity,
@ -635,8 +605,8 @@ fn example_control_system(
}
fn flicker_system(
mut flame: Query<&mut Transform, (With<Flicker>, With<Handle<Mesh>>)>,
mut light: Query<(&mut PointLight, &mut Transform), (With<Flicker>, Without<Handle<Mesh>>)>,
mut flame: Query<&mut Transform, (With<Flicker>, With<Mesh3d>)>,
mut light: Query<(&mut PointLight, &mut Transform), (With<Flicker>, Without<Mesh3d>)>,
time: Res<Time>,
) {
let s = time.elapsed_seconds();

View file

@ -18,16 +18,15 @@ fn setup(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Opaque plane, uses `alpha_mode: Opaque` by default
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(6.0, 6.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(6.0, 6.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// Transparent sphere, uses `alpha_mode: Mask(f32)`
commands.spawn(PbrBundle {
mesh: meshes.add(Sphere::new(0.5).mesh().ico(3).unwrap()),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Sphere::new(0.5).mesh().ico(3).unwrap())),
MeshMaterial3d(materials.add(StandardMaterial {
// Alpha channel of the color controls transparency.
// We set it to 0.0 here, because it will be changed over time in the
// `fade_transparency` function.
@ -37,54 +36,49 @@ fn setup(
// alpha values above are fully opaque.
alpha_mode: AlphaMode::Mask(0.5),
..default()
}),
transform: Transform::from_xyz(1.0, 0.5, -1.5),
..default()
});
})),
Transform::from_xyz(1.0, 0.5, -1.5),
));
// Transparent unlit sphere, uses `alpha_mode: Mask(f32)`
commands.spawn(PbrBundle {
mesh: meshes.add(Sphere::new(0.5).mesh().ico(3).unwrap()),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Sphere::new(0.5).mesh().ico(3).unwrap())),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgba(0.2, 0.7, 0.1, 0.0),
alpha_mode: AlphaMode::Mask(0.5),
unlit: true,
..default()
}),
transform: Transform::from_xyz(-1.0, 0.5, -1.5),
..default()
});
})),
Transform::from_xyz(-1.0, 0.5, -1.5),
));
// Transparent cube, uses `alpha_mode: Blend`
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
// Notice how there is no need to set the `alpha_mode` explicitly here.
// When converting a color to a material using `into()`, the alpha mode is
// automatically set to `Blend` if the alpha channel is anything lower than 1.0.
material: materials.add(Color::srgba(0.5, 0.5, 1.0, 0.0)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
MeshMaterial3d(materials.add(Color::srgba(0.5, 0.5, 1.0, 0.0))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// Transparent cube, uses `alpha_mode: AlphaToCoverage`
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgba(0.5, 1.0, 0.5, 0.0),
alpha_mode: AlphaMode::AlphaToCoverage,
..default()
}),
transform: Transform::from_xyz(-1.5, 0.5, 0.0),
..default()
});
})),
Transform::from_xyz(-1.5, 0.5, 0.0),
));
// Opaque sphere
commands.spawn(PbrBundle {
mesh: meshes.add(Sphere::new(0.5).mesh().ico(3).unwrap()),
material: materials.add(Color::srgb(0.7, 0.2, 0.1)),
transform: Transform::from_xyz(0.0, 0.5, -1.5),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Sphere::new(0.5).mesh().ico(3).unwrap())),
MeshMaterial3d(materials.add(Color::srgb(0.7, 0.2, 0.1))),
Transform::from_xyz(0.0, 0.5, -1.5),
));
// Light
commands.spawn((

View file

@ -16,19 +16,17 @@ fn setup(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// Cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// Light
commands.spawn((

View file

@ -16,11 +16,10 @@ fn setup(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// cube
// Assign vertex colors based on vertex positions
let mut colorful_cube = Mesh::from(Cuboid::default());
@ -33,15 +32,14 @@ fn setup(
.collect();
colorful_cube.insert_attribute(Mesh::ATTRIBUTE_COLOR, colors);
}
commands.spawn(PbrBundle {
mesh: meshes.add(colorful_cube),
commands.spawn((
Mesh3d(meshes.add(colorful_cube)),
// This is the default color, but note that vertex colors are
// multiplied by the base color, so you'll likely want this to be
// white if using vertex colors.
material: materials.add(Color::srgb(1., 1., 1.)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
MeshMaterial3d(materials.add(Color::srgb(1., 1., 1.))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// Light
commands.spawn((

View file

@ -94,11 +94,10 @@ fn setup(
app_status: Res<AppStatus>,
) {
// Spawn a plane.
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)),
material: materials.add(Color::srgb(0.1, 0.2, 0.1)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(50.0, 50.0))),
MeshMaterial3d(materials.add(Color::srgb(0.1, 0.2, 0.1))),
));
// Spawn the two HLODs.
@ -170,7 +169,7 @@ fn setup(
// component as appropriate.
fn set_visibility_ranges(
mut commands: Commands,
mut new_meshes: Query<Entity, Added<Handle<Mesh>>>,
mut new_meshes: Query<Entity, Added<Mesh3d>>,
parents: Query<(Option<&Parent>, Option<&MainModel>)>,
) {
// Loop over each newly-added mesh.

View file

@ -56,29 +56,22 @@ fn setup(
) {
// Red cube: Never renders a wireframe
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::from(RED)),
transform: Transform::from_xyz(-1.0, 0.5, -1.0),
..default()
},
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::from(RED))),
Transform::from_xyz(-1.0, 0.5, -1.0),
NoWireframe,
));
// Orange cube: Follows global wireframe setting
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::from(ORANGE)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::from(ORANGE))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// Green cube: Always renders a wireframe
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::from(LIME)),
transform: Transform::from_xyz(1.0, 0.5, 1.0),
..default()
},
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::from(LIME))),
Transform::from_xyz(1.0, 0.5, 1.0),
Wireframe,
// This lets you configure the wireframe color of this entity.
// If not set, this will use the color in `WireframeConfig`
@ -87,11 +80,8 @@ fn setup(
// plane
commands.spawn((
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(Color::from(BLUE)),
..default()
},
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(Color::from(BLUE))),
// You can insert this component without the `Wireframe` component
// to override the color of the global wireframe for this mesh
WireframeColor {

View file

@ -59,11 +59,10 @@ fn setup(
});
// Plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(500000.0, 500000.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(500000.0, 500000.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// Light
commands.spawn((

View file

@ -134,11 +134,8 @@ fn setup(
// First entity is the planet
let planet_entity = commands
.spawn((
PbrBundle {
mesh: meshes.add(Sphere::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
..default()
},
Mesh3d(meshes.add(Sphere::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
// Add the animation graph and player
planet,
graphs.add(graph),
@ -164,12 +161,9 @@ fn setup(
.with_children(|p| {
// The satellite, placed at a distance of the planet
p.spawn((
PbrBundle {
transform: Transform::from_xyz(1.5, 0.0, 0.0),
mesh: meshes.add(Cuboid::new(0.5, 0.5, 0.5)),
material: materials.add(Color::srgb(0.3, 0.9, 0.3)),
..default()
},
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.9, 0.3))),
Transform::from_xyz(1.5, 0.0, 0.0),
AnimationTarget {
id: satellite_animation_target_id,
player: planet_entity,

View file

@ -240,12 +240,11 @@ fn setup_scene(
// Ground
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(7.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Circle::new(7.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
));
}
/// Places the help text at the top left of the window.

View file

@ -125,12 +125,11 @@ fn setup_scene(
});
// Spawn the ground.
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(7.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Circle::new(7.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
));
}
// Creates the UI.

View file

@ -38,12 +38,9 @@ fn setup(
// Spawning a cube to experiment on
commands.spawn((
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::from(ORANGE)),
transform: Transform::from_translation(points[0][0]),
..default()
},
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::from(ORANGE))),
Transform::from_translation(points[0][0]),
Curve(bezier),
));
@ -59,11 +56,10 @@ fn setup(
));
// ground plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50., 50.)),
material: materials.add(Color::from(SILVER)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(50., 50.))),
MeshMaterial3d(materials.add(Color::from(SILVER))),
));
// The camera
commands.spawn(Camera3dBundle {

View file

@ -142,15 +142,12 @@ fn setup(
// Create skinned mesh renderer. Note that its transform doesn't affect the position of the mesh.
commands.spawn((
PbrBundle {
mesh: mesh.clone(),
material: materials.add(Color::srgb(
rng.gen_range(0.0..1.0),
rng.gen_range(0.0..1.0),
rng.gen_range(0.0..1.0),
)),
..default()
},
Mesh3d(mesh.clone()),
MeshMaterial3d(materials.add(Color::srgb(
rng.gen_range(0.0..1.0),
rng.gen_range(0.0..1.0),
rng.gen_range(0.0..1.0),
))),
SkinnedMesh {
inverse_bindposes: inverse_bindposes.clone(),
joints: joint_entities,

View file

@ -37,8 +37,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
///
/// ```text
/// <Parent entity>
/// + Mesh node (without `PbrBundle` or `SkinnedMesh` component)
/// + Skinned mesh entity (with `PbrBundle` and `SkinnedMesh` component, created by glTF loader)
/// + Mesh node (without `Mesh3d` or `SkinnedMesh` component)
/// + Skinned mesh entity (with `Mesh3d` and `SkinnedMesh` component, created by glTF loader)
/// + First joint
/// + Second joint
/// ```

View file

@ -160,19 +160,17 @@ fn setup(
// Scene example for non black box picture
// circular base
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(4.0)),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Circle::new(4.0))),
MeshMaterial3d(materials.add(Color::WHITE)),
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
));
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::srgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// light
commands.spawn((
PointLight {

View file

@ -104,23 +104,17 @@ fn setup(
commands.spawn((
Left,
Name::new("Left Shape"),
PbrBundle {
mesh: left_shape_model,
material: material_handle.clone(),
transform: Transform::from_xyz(-3.0, 0.0, 0.0),
..default()
},
Mesh3d(left_shape_model),
MeshMaterial3d(material_handle.clone()),
Transform::from_xyz(-3.0, 0.0, 0.0),
left_shape,
));
commands.spawn((
Name::new("Right Shape"),
PbrBundle {
mesh: right_shape_model,
material: material_handle,
transform: Transform::from_xyz(3.0, 0.0, 0.0),
..default()
},
Mesh3d(right_shape_model),
MeshMaterial3d(material_handle),
Transform::from_xyz(3.0, 0.0, 0.0),
right_shape,
));
@ -168,11 +162,11 @@ fn spawn_text(mut commands: Commands) {
fn alter_handle(
asset_server: Res<AssetServer>,
mut right_shape: Query<(&mut Handle<Mesh>, &mut Shape), Without<Left>>,
mut right_shape: Query<(&mut Mesh3d, &mut Shape), Without<Left>>,
) {
// Mesh handles, like other parts of the ECS, can be queried as mutable and modified at
// runtime. We only spawned one shape without the `Left` marker component.
let Ok((mut handle, mut shape)) = right_shape.get_single_mut() else {
let Ok((mut mesh, mut shape)) = right_shape.get_single_mut() else {
return;
};
@ -182,7 +176,7 @@ fn alter_handle(
// Modify the handle associated with the Shape on the right side. Note that we will only
// have to load the same path from storage media once: repeated attempts will re-use the
// asset.
*handle = asset_server.load(
mesh.0 = asset_server.load(
GltfAssetLabel::Primitive {
mesh: 0,
primitive: 0,
@ -193,7 +187,7 @@ fn alter_handle(
fn alter_mesh(
mut is_mesh_scaled: Local<bool>,
left_shape: Query<&Handle<Mesh>, With<Left>>,
left_shape: Query<&Mesh3d, With<Left>>,
mut meshes: ResMut<Assets<Mesh>>,
) {
// It's convenient to retrieve the asset handle stored with the shape on the left. However,

View file

@ -73,26 +73,23 @@ fn setup(
});
// torus
commands.spawn(PbrBundle {
mesh: torus_handle,
material: material_handle.clone(),
transform: Transform::from_xyz(-3.0, 0.0, 0.0),
..default()
});
commands.spawn((
Mesh3d(torus_handle),
MeshMaterial3d(material_handle.clone()),
Transform::from_xyz(-3.0, 0.0, 0.0),
));
// cube
commands.spawn(PbrBundle {
mesh: cube_handle,
material: material_handle.clone(),
transform: Transform::from_xyz(0.0, 0.0, 0.0),
..default()
});
commands.spawn((
Mesh3d(cube_handle),
MeshMaterial3d(material_handle.clone()),
Transform::from_xyz(0.0, 0.0, 0.0),
));
// sphere
commands.spawn(PbrBundle {
mesh: sphere_handle,
material: material_handle,
transform: Transform::from_xyz(3.0, 0.0, 0.0),
..default()
});
commands.spawn((
Mesh3d(sphere_handle),
MeshMaterial3d(material_handle),
Transform::from_xyz(3.0, 0.0, 0.0),
));
// light
commands.spawn((PointLight::default(), Transform::from_xyz(4.0, 5.0, 4.0)));
// camera

View file

@ -224,11 +224,8 @@ fn setup_scene(
// Plane
commands.spawn((
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50000.0, 50000.0)),
material: materials.add(Color::srgb(0.7, 0.2, 0.2)),
..default()
},
Mesh3d(meshes.add(Plane3d::default().mesh().size(50000.0, 50000.0))),
MeshMaterial3d(materials.add(Color::srgb(0.7, 0.2, 0.2))),
Loading,
));
}
@ -250,12 +247,11 @@ fn wait_on_load(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Change color of plane to green
commands.spawn((PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50000.0, 50000.0)),
material: materials.add(Color::srgb(0.3, 0.5, 0.3)),
transform: Transform::from_translation(Vec3::Z * -0.01),
..default()
},));
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(50000.0, 50000.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
Transform::from_translation(Vec3::Z * -0.01),
));
// Spawn our scenes.
for i in 0..10 {

View file

@ -26,20 +26,19 @@ fn setup(
asset_server.load("textures/fantasy_ui_borders/panel-border-010.png");
// central cube with not repeated texture
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: Some(image_with_default_sampler.clone()),
..default()
}),
transform: Transform::from_translation(Vec3::ZERO),
..default()
});
})),
Transform::from_translation(Vec3::ZERO),
));
// left cube with repeated texture
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: Some(asset_server.load_with_settings(
"textures/fantasy_ui_borders/panel-border-010-repeated.png",
|s: &mut _| {
@ -59,15 +58,14 @@ fn setup(
// that's why you can use rotation and shift also
uv_transform: Affine2::from_scale(Vec2::new(2., 3.)),
..default()
}),
transform: Transform::from_xyz(-1.5, 0.0, 0.0),
..default()
});
})),
Transform::from_xyz(-1.5, 0.0, 0.0),
));
// right cube with scaled texture, because with default sampler
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(StandardMaterial {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(StandardMaterial {
// there is no sampler set, that's why
// by default you see only one small image in a row/column
// and other space is filled by image edge
@ -77,10 +75,9 @@ fn setup(
// that's why you can use rotation and shift also
uv_transform: Affine2::from_scale(Vec2::new(2., 3.)),
..default()
}),
transform: Transform::from_xyz(1.5, 0.0, 0.0),
..default()
});
})),
Transform::from_xyz(1.5, 0.0, 0.0),
));
// light
commands.spawn((

View file

@ -84,13 +84,12 @@ fn spawn_tasks(mut commands: Commands) {
world
.entity_mut(entity)
// Add our new PbrBundle of components to our tagged entity
.insert(PbrBundle {
mesh: box_mesh_handle,
material: box_material_handle,
// Add our new `Mesh3d` and `MeshMaterial3d` to our tagged entity
.insert((
Mesh3d(box_mesh_handle),
MeshMaterial3d(box_material_handle),
transform,
..default()
})
))
// Task is complete, so remove task component from entity
.remove::<ComputeTransform>();
});
@ -107,7 +106,7 @@ fn spawn_tasks(mut commands: Commands) {
/// This system queries for entities that have our Task<Transform> component. It polls the
/// tasks to see if they're complete. If the task is complete it takes the result, adds a
/// new [`PbrBundle`] of components to the entity using the result from the task's work, and
/// new [`Mesh3d`] and [`MeshMaterial3d`] to the entity using the result from the task's work, and
/// removes the task component from the entity.
fn handle_tasks(mut commands: Commands, mut transform_tasks: Query<&mut ComputeTransform>) {
for mut task in &mut transform_tasks {

View file

@ -3,7 +3,6 @@ use bevy::{
audio::{AudioPlugin, SpatialScale},
color::palettes::css::*,
prelude::*,
sprite::MaterialMesh2dBundle,
};
/// Spatial audio uses the distance to attenuate the sound volume. In 2D with the default camera,
@ -34,12 +33,9 @@ fn setup(
// sound emitter
commands.spawn((
MaterialMesh2dBundle {
mesh: meshes.add(Circle::new(15.0)).into(),
material: materials.add(Color::from(BLUE)),
transform: Transform::from_translation(Vec3::new(0.0, 50.0, 0.0)),
..default()
},
Mesh2d(meshes.add(Circle::new(15.0))),
MeshMaterial2d(materials.add(Color::from(BLUE))),
Transform::from_translation(Vec3::new(0.0, 50.0, 0.0)),
Emitter::default(),
AudioBundle {
source: asset_server.load("sounds/Windless Slopes.ogg"),

View file

@ -24,12 +24,9 @@ fn setup(
// sound emitter
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::new(0.2).mesh().uv(32, 18)),
material: materials.add(Color::from(BLUE)),
transform: Transform::from_xyz(0.0, 0.0, 0.0),
..default()
},
Mesh3d(meshes.add(Sphere::new(0.2).mesh().uv(32, 18))),
MeshMaterial3d(materials.add(Color::from(BLUE))),
Transform::from_xyz(0.0, 0.0, 0.0),
Emitter::default(),
AudioBundle {
source: asset_server.load("sounds/Windless Slopes.ogg"),
@ -42,20 +39,18 @@ fn setup(
.spawn((SpatialBundle::default(), listener.clone()))
.with_children(|parent| {
// left ear indicator
parent.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(0.2, 0.2, 0.2)),
material: materials.add(Color::from(RED)),
transform: Transform::from_translation(listener.left_ear_offset),
..default()
});
parent.spawn((
Mesh3d(meshes.add(Cuboid::new(0.2, 0.2, 0.2))),
MeshMaterial3d(materials.add(Color::from(RED))),
Transform::from_translation(listener.left_ear_offset),
));
// right ear indicator
parent.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(0.2, 0.2, 0.2)),
material: materials.add(Color::from(LIME)),
transform: Transform::from_translation(listener.right_ear_offset),
..default()
});
parent.spawn((
Mesh3d(meshes.add(Cuboid::new(0.2, 0.2, 0.2))),
MeshMaterial3d(materials.add(Color::from(LIME))),
Transform::from_translation(listener.right_ear_offset),
));
});
// light

View file

@ -9,12 +9,7 @@
//! | `A` | Move left |
//! | `D` | Move right |
use bevy::{
core_pipeline::bloom::Bloom,
math::vec3,
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
use bevy::{core_pipeline::bloom::Bloom, prelude::*};
/// Player movement speed factor.
const PLAYER_SPEED: f32 = 100.;
@ -39,24 +34,17 @@ fn setup_scene(
mut materials: ResMut<Assets<ColorMaterial>>,
) {
// World where we move the player
commands.spawn(MaterialMesh2dBundle {
mesh: Mesh2dHandle(meshes.add(Rectangle::new(1000., 700.))),
material: materials.add(Color::srgb(0.2, 0.2, 0.3)),
..default()
});
commands.spawn((
Mesh2d(meshes.add(Rectangle::new(1000., 700.))),
MeshMaterial2d(materials.add(Color::srgb(0.2, 0.2, 0.3))),
));
// Player
commands.spawn((
Player,
MaterialMesh2dBundle {
mesh: meshes.add(Circle::new(25.)).into(),
material: materials.add(Color::srgb(6.25, 9.4, 9.1)), // RGB values exceed 1 to achieve a bright color for the bloom effect
transform: Transform {
translation: vec3(0., 0., 2.),
..default()
},
..default()
},
Mesh2d(meshes.add(Circle::new(25.))),
MeshMaterial2d(materials.add(Color::srgb(6.25, 9.4, 9.1))), // RGB values exceed 1 to achieve a bright color for the bloom effect
Transform::from_xyz(0., 0., 2.),
));
}

View file

@ -58,26 +58,20 @@ fn setup(
commands.spawn((
Name::new("Plane"),
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(StandardMaterial {
base_color: Color::srgb(0.3, 0.5, 0.3),
// Turning off culling keeps the plane visible when viewed from beneath.
cull_mode: None,
..default()
}),
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.3, 0.5, 0.3),
// Turning off culling keeps the plane visible when viewed from beneath.
cull_mode: None,
..default()
},
})),
));
commands.spawn((
Name::new("Cube"),
PbrBundle {
mesh: meshes.add(Cuboid::default()),
material: materials.add(Color::srgb(0.8, 0.7, 0.6)),
transform: Transform::from_xyz(1.5, 0.51, 1.5),
..default()
},
Mesh3d(meshes.add(Cuboid::default())),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(1.5, 0.51, 1.5),
));
commands.spawn((

View file

@ -147,12 +147,9 @@ fn spawn_view_model(
// Spawn the player's right arm.
parent.spawn((
MaterialMeshBundle {
mesh: arm,
material: arm_material,
transform: Transform::from_xyz(0.2, -0.1, -0.25),
..default()
},
Mesh3d(arm),
MeshMaterial3d(arm_material),
Transform::from_xyz(0.2, -0.1, -0.25),
// Ensure the arm is only rendered by the view model camera.
RenderLayers::layer(VIEW_MODEL_RENDER_LAYER),
// The arm is free-floating, so shadows would look weird.
@ -173,25 +170,19 @@ fn spawn_world_model(
// The world model camera will render the floor and the cubes spawned in this system.
// Assigning no `RenderLayers` component defaults to layer 0.
commands.spawn(MaterialMeshBundle {
mesh: floor,
material: material.clone(),
..default()
});
commands.spawn((Mesh3d(floor), MeshMaterial3d(material.clone())));
commands.spawn(MaterialMeshBundle {
mesh: cube.clone(),
material: material.clone(),
transform: Transform::from_xyz(0.0, 0.25, -3.0),
..default()
});
commands.spawn((
Mesh3d(cube.clone()),
MeshMaterial3d(material.clone()),
Transform::from_xyz(0.0, 0.25, -3.0),
));
commands.spawn(MaterialMeshBundle {
mesh: cube,
material,
transform: Transform::from_xyz(0.75, 1.75, 0.0),
..default()
});
commands.spawn((
Mesh3d(cube),
MeshMaterial3d(material),
Transform::from_xyz(0.75, 1.75, 0.0),
));
}
fn spawn_lights(mut commands: Commands) {

View file

@ -67,16 +67,13 @@ fn setup(
commands.spawn((
Name::new("Plane"),
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(StandardMaterial {
base_color: Color::srgb(0.3, 0.5, 0.3),
// Turning off culling keeps the plane visible when viewed from beneath.
cull_mode: None,
..default()
}),
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.3, 0.5, 0.3),
// Turning off culling keeps the plane visible when viewed from beneath.
cull_mode: None,
..default()
},
})),
));
commands.spawn((

View file

@ -28,7 +28,8 @@ struct Star;
#[derive(Bundle, Default)]
struct BodyBundle {
pbr: PbrBundle,
mesh: Mesh3d,
material: MeshMaterial3d<StandardMaterial>,
mass: Mass,
last_pos: LastPos,
acceleration: Acceleration,
@ -61,32 +62,31 @@ fn generate_bodies(
* ops::cbrt(rng.gen_range(0.2f32..1.0))
* 15.;
commands.spawn(BodyBundle {
pbr: PbrBundle {
transform: Transform {
translation: position,
scale: Vec3::splat(radius),
..default()
},
mesh: mesh.clone(),
material: materials.add(Color::srgb(
commands.spawn((
BodyBundle {
mesh: Mesh3d(mesh.clone()),
material: MeshMaterial3d(materials.add(Color::srgb(
rng.gen_range(color_range.clone()),
rng.gen_range(color_range.clone()),
rng.gen_range(color_range.clone()),
)),
))),
mass: Mass(mass_value),
acceleration: Acceleration(Vec3::ZERO),
last_pos: LastPos(
position
- Vec3::new(
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
) * time.timestep().as_secs_f32(),
),
},
Transform {
translation: position,
scale: Vec3::splat(radius),
..default()
},
mass: Mass(mass_value),
acceleration: Acceleration(Vec3::ZERO),
last_pos: LastPos(
position
- Vec3::new(
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
) * time.timestep().as_secs_f32(),
),
});
));
}
// add bigger "star" body in the center
@ -94,19 +94,17 @@ fn generate_bodies(
commands
.spawn((
BodyBundle {
pbr: PbrBundle {
transform: Transform::from_scale(Vec3::splat(star_radius)),
mesh: meshes.add(Sphere::new(1.0).mesh().ico(5).unwrap()),
material: materials.add(StandardMaterial {
base_color: ORANGE_RED.into(),
emissive: LinearRgba::from(ORANGE_RED) * 2.,
..default()
}),
mesh: Mesh3d(meshes.add(Sphere::new(1.0).mesh().ico(5).unwrap())),
material: MeshMaterial3d(materials.add(StandardMaterial {
base_color: ORANGE_RED.into(),
emissive: LinearRgba::from(ORANGE_RED) * 2.,
..default()
},
})),
mass: Mass(500.0),
..default()
},
Transform::from_scale(Vec3::splat(star_radius)),
Star,
))
.with_child(PointLight {

Some files were not shown because too many files have changed in this diff Show more