如何在 Bevy 中将纹理分配给 2D 网格?

How do I assign textures to 2D meshes in Bevy?

我想创建类似于 Civilization 的六角形图块,我可以单击这些图块并使用拖放系统将东西移入和移出它们。我编写的代码在 运行 程序后抛出错误:

Mesh is missing requested attribute: Vertex_Normal (MeshVertexAttributeId(1), pipeline type: Some("bevy_sprite::mesh2d::material::Material2dPipeline<bevy_sprite::mesh2d::color_material::ColorMaterial>"))

我不确定为什么这会引发错误,因为当我从四边形 (meshes.add(Mesh::from(shape::Quad::default())).into()) 创建基本网格时程序 运行 没问题,但我想要一个 2D 六边形。

这是我的设置代码:

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    asset_server: Res<AssetServer>
) {
    let vertices = vec![
        [-0.8660, 0.5000],
        [ 0.8660, 0.5000],
        [-1.0000, 0.0000],
        [ 1.0000, 0.0000],
        [-0.8660,-0.5000],
        [ 0.8660,-0.5000]];
    let indeces = Indices::U16(vec![
        0, 1, 2,
        1, 3, 2,
        2, 3, 4,
        3, 5, 4
    ]);

    let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
    mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vertices);
    mesh.set_indices(Some(indeces));

    commands.spawn_bundle(OrthographicCameraBundle::new_2d());
    commands.spawn_bundle(MaterialMesh2dBundle {
        mesh: meshes.add(mesh).into(),
        transform: Transform::default().with_scale(Vec3::splat(128.)),
        material: materials.add(asset_server.load(TILE_SPRITE).into()),
        ..default()
    });
}

这是我的主要内容:

const TILE_SPRITE: &str = "tile.png";

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup)
        .run();
    }

使用 bevy 中的默认着色器,您的网格还必须为每个顶点设置 法线uvs

您可以提供自己的着色器或添加所需的属性,类似于 中显示的方法。

除此之外,您提供的 positionsindices 似乎不正确。即使您在 2D 模式下使用 bevy,您仍然必须使用三个坐标提供位置(z beeing 设置为零)。您可以在下面的 RenderDoc 屏幕截图中看到其他情况:

这是一个小示例,其中包含更正的索引和位置,以及 UV 和法线的占位符值,应该可以帮助您入门:

use bevy::{
    prelude::*,
    render::mesh::{Indices, PrimitiveTopology},
    sprite::MaterialMesh2dBundle,
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup)
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    _asset_server: Res<AssetServer>,
) {
    let vertices = vec![
        [-0.8660, 0.5000, 0f32],
        [0.8660, 0.5000, 0f32],
        [-1.0000, 0.0000, 0f32],
        [1.0000, 0.0000, 0f32],
        [-0.8660, -0.5000, 0f32],
        [0.8660, -0.5000, 0f32],
    ];
    let normals = vec![
        [0f32, 0f32, 1f32],
        [0f32, 0f32, 1f32],
        [0f32, 0f32, 1f32],
        [0f32, 0f32, 1f32],
        [0f32, 0f32, 1f32],
        [0f32, 0f32, 1f32],
    ];
    let uvs = vec![
        [0.0000, 0.0000],
        [0.0000, 0.0000],
        [0.0000, 0.0000],
        [0.0000, 0.0000],
        [0.0000, 0.0000],
        [0.0000, 0.0000],
    ];
    let indices = Indices::U16(vec![1, 0, 2, 3, 1, 2, 3, 2, 4, 3, 4, 5]);

    let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
    mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vertices);
    mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
    mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
    mesh.set_indices(Some(indices));

    let mut camera = OrthographicCameraBundle::new_2d();
    camera.orthographic_projection.scale = 1f32;

    commands.spawn_bundle(camera);
    commands.spawn_bundle(MaterialMesh2dBundle {
        mesh: meshes.add(mesh).into(),
        transform: Transform::default().with_scale(Vec3::splat(128.)),
        material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
        ..default()
    });
}

请注意,为了让您的 Sprite 显示出来,您必须更改 UV 坐标(我确实将它们留在了 0, 0,因为我不知道您想如何映射您的精灵/纹理到六边形)。