Skip to main content

repeated_texture/
repeated_texture.rs

1//! By default Bevy loads images to textures that clamps the image to the edges
2//! This example shows how to configure it to repeat the image instead.
3
4use bevy::{
5    image::{ImageAddressMode, ImageLoaderSettings, ImageSampler, ImageSamplerDescriptor},
6    math::Affine2,
7    prelude::*,
8};
9
10fn main() {
11    App::new()
12        .add_plugins(DefaultPlugins)
13        .add_systems(Startup, setup)
14        .run();
15}
16
17fn setup(
18    mut commands: Commands,
19    asset_server: Res<AssetServer>,
20    mut meshes: ResMut<Assets<Mesh>>,
21    mut materials: ResMut<Assets<StandardMaterial>>,
22) {
23    let image_with_default_sampler =
24        asset_server.load("textures/fantasy_ui_borders/panel-border-010.png");
25
26    // central cube with not repeated texture
27    commands.spawn((
28        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
29        MeshMaterial3d(materials.add(StandardMaterial {
30            base_color_texture: Some(image_with_default_sampler.clone()),
31            ..default()
32        })),
33        Transform::from_translation(Vec3::ZERO),
34    ));
35
36    // left cube with repeated texture
37    commands.spawn((
38        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
39        MeshMaterial3d(
40            materials.add(StandardMaterial {
41                base_color_texture: Some(
42                    asset_server
43                        .load_builder()
44                        .with_settings(|s: &mut _| {
45                            *s = ImageLoaderSettings {
46                                sampler: ImageSampler::Descriptor(ImageSamplerDescriptor {
47                                    // rewriting mode to repeat image,
48                                    address_mode_u: ImageAddressMode::Repeat,
49                                    address_mode_v: ImageAddressMode::Repeat,
50                                    ..default()
51                                }),
52                                ..default()
53                            }
54                        })
55                        .load("textures/fantasy_ui_borders/panel-border-010-repeated.png"),
56                ),
57
58                // uv_transform used here for proportions only, but it is full Affine2
59                // that's why you can use rotation and shift also
60                uv_transform: Affine2::from_scale(Vec2::new(2., 3.)),
61                ..default()
62            }),
63        ),
64        Transform::from_xyz(-1.5, 0.0, 0.0),
65    ));
66
67    // right cube with scaled texture, because with default sampler
68    commands.spawn((
69        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
70        MeshMaterial3d(materials.add(StandardMaterial {
71            // there is no sampler set, that's why
72            // by default you see only one small image in a row/column
73            // and other space is filled by image edge
74            base_color_texture: Some(image_with_default_sampler),
75
76            // uv_transform used here for proportions only, but it is full Affine2
77            // that's why you can use rotation and shift also
78            uv_transform: Affine2::from_scale(Vec2::new(2., 3.)),
79            ..default()
80        })),
81        Transform::from_xyz(1.5, 0.0, 0.0),
82    ));
83
84    // light
85    commands.spawn((
86        PointLight {
87            shadow_maps_enabled: true,
88            ..default()
89        },
90        Transform::from_xyz(4.0, 8.0, 4.0),
91    ));
92    // camera
93    commands.spawn((
94        Camera3d::default(),
95        Transform::from_xyz(0.0, 1.5, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
96    ));
97}