#sprites #bevy-plugin #lots #draw #render #call #instanced

bevy_sprite_instancing

一个用于渲染大量实例精灵的Bevy插件

2个版本

0.1.1 2023年5月25日
0.1.0 2023年5月25日

#1288 in 游戏开发

26 每月下载量

MIT/Apache

30KB
594

bevy_sprite_instancing

crates.io License

Bevy插件,用于在一次绘制调用中渲染大量实例精灵。

插件是如何工作的?

插件不是逐个处理类似实体精灵,而是提供 SpriteInstancingGroup,其中可以包含这些精灵的实体ID。然后插件收集所有这些精灵的变换,并将它们作为一个大缓冲区提交给GPU,然后用于一次性绘制所有精灵。

Animated example

功能

  • 动画瓦片
  • 绘制大量精灵时FPS表现良好(高达100万)

我该如何使用它?

查看这个快速示例: 示例

以下是如何绘制大量精灵的简单示例

pub const ENTITY_COUNT: usize = 100000;

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
	// Create a camera
	commands.spawn(Camera2dBundle::default());

	// Load a spritesheet
	let spritesheet = InstancedSpritesheet {
		image: asset_server.load("textures/my_spritesheet.png"),
		// Size of this spritesheet in tiles
		width_tiles: 32,
		height_tiles: 32,
	};

	// Create an instancing group for the sprites
	let mut instancing_group = SpriteInstancingGroup {
		entities: HashSet::new(),
	};
	let group_id = commands.spawn_empty().id();

	// Spawn the sprites
	for _ in 0..ENTITY_COUNT {
		let position = Vec3::new(..., 0.0); // some random position
		let scale = Vec3::new(..., 1.0); // some random size
		let transform = ...; // create a transform from these
		let sprite = InstancedSprite {
			group_id,
			texture_index: 0
		};

		let entity = commands.spawn((transform, sprite)).id();
		instancing_group.entities.insert(entity);
	}

	// Attach the instancing group and its spritesheet
	commands.entity(group_id).insert((instancing_group, spritesheet));
}

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

尚未实现的功能

还有一些高级功能我尚未实现

  • 视图区域裁剪:无需提交屏幕上不存在的精灵的变换
  • GPU动画:不是为每个精灵提交一个 texture_index,也许通过单独的实例化缓冲区提交 anim_start_indexanim_len 是一个好主意

... 以及一些低级功能

  • SpriteInstancingGroup 标记为静态(即实体不移动),以避免每帧重新提交其实例化数据

依赖关系

~37–73MB
~1M SLoC