-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bevy 0.15 #6
base: main
Are you sure you want to change the base?
Bevy 0.15 #6
Conversation
This is awesome thank you so much for doing this! I will give it a look as soon as I can, probably over this weekend. I'm totally good to use bevys version of Glam, when I was working on it initially I was running into issues with it but if it can be swapped and works fine then I'm good with that. I'm good with removing bevy fast tilemap from here, I'll probably pull the example into its own crate so this crate can be updated. Bevy_fast_tilemap normally receives an update within a few weeks of bevy releases but it would be nice to not be directly tied to it. |
No problem, it was really interesting! I played a bit with In the meantime, I'll remove |
Removed |
I wrote a much simpler shader which work like #import bevy_sprite::mesh2d_vertex_output::VertexOutput
// in tiles
@group(2) @binding(0) var<uniform> map_size: vec2<u32>;
// in pixels
@group(2) @binding(1) var<uniform> tile_size: f32;
@group(2) @binding(2) var atlas_texture: texture_2d<f32>;
@group(2) @binding(3) var atlas_sampler: sampler;
// in pixels
@group(2) @binding(4) var<uniform> atlas_size: vec2<f32>;
// map by tile index
@group(2) @binding(5) var<storage,read> map_tiles: array<u32>;
fn get_color(uv: vec2<f32>) -> vec4<f32> {
// from 0..n_x_map_tiles
let tile_x = uv.x * f32(map_size.x);
// from 0..n_y_map_tiles
let tile_y = uv.y * f32(map_size.y);
// from 0..atlas_column*atlas_row
let tile_idx = map_tiles[u32(tile_y) * map_size.x + u32(tile_x)];
let atlas_column: u32 = u32(atlas_size.x / tile_size);
let atlas_row: u32 = u32(atlas_size.y / tile_size);
let column = tile_idx % atlas_column;
let row = tile_idx / atlas_column;
let pixel_position_in_tile = vec2<f32>(uv * vec2<f32>(map_size) * tile_size % tile_size);
let pixel_position_in_atlas = pixel_position_in_tile + vec2<f32>(f32(column), f32(row)) * tile_size;
let color = textureSample(atlas_texture, atlas_sampler, pixel_position_in_atlas / atlas_size);
return color;
}
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
return get_color(in.uv);
} Here is rust code use bevy::{
asset::RenderAssetUsages,
prelude::*,
render::{
render_resource::{AsBindGroup, ShaderRef},
storage::ShaderStorageBuffer,
},
sprite::{Material2d, Material2dPlugin},
};
pub struct TileMapRenderPlugin;
impl Plugin for TileMapRenderPlugin {
fn build(&self, app: &mut App) {
app.add_plugins(Material2dPlugin::<TileMapMaterial>::default())
.add_systems(Startup, setup)
.add_systems(Update, spawn_tile_map);
}
}
const MAP_SIZE: u32 = 2;
const TILE_SIZE: f32 = 16.;
#[derive(Debug, Clone, TypePath, AsBindGroup, Asset)]
pub struct TileMapMaterial {
#[uniform(0)]
map_size: UVec2,
#[uniform(1)]
tile_size: f32,
#[texture(2)]
#[sampler(3)]
atlas_texture: Handle<Image>,
/// The size of the atlas texture in pixels.
#[uniform(4)]
atlas_size: Vec2,
#[storage(5, read_only)]
map_tiles: Handle<ShaderStorageBuffer>,
}
const SHADER_PATH: &str = "shaders/tile_map.wgsl";
impl Material2d for TileMapMaterial {
fn fragment_shader() -> ShaderRef {
SHADER_PATH.into()
}
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let handle = asset_server.load("temp/tileset.png");
commands.insert_resource(TileSetHandle(handle));
}
fn spawn_tile_map(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<TileMapMaterial>>,
images: Res<Assets<Image>>,
asset_server: Res<AssetServer>,
tileset_handle: Res<TileSetHandle>,
mut buffers: ResMut<Assets<ShaderStorageBuffer>>,
) {
let load_state = asset_server.get_load_state(&tileset_handle.0);
if !load_state.map(|s| s.is_loaded()).unwrap_or_default() {
return;
}
let map_size_in_pixel = MAP_SIZE * TILE_SIZE as u32;
let tile_set = images.get(&tileset_handle.0).unwrap();
let map_tiles: Vec<u32> = vec![17, 18, 24, 25];
let buffer = buffers.add(ShaderStorageBuffer {
data: Some(bytemuck::cast_slice(&map_tiles).to_vec()),
asset_usage: RenderAssetUsages::RENDER_WORLD,
..default()
});
commands.spawn((
Mesh2d(meshes.add(Rectangle::new(
map_size_in_pixel as f32,
map_size_in_pixel as f32,
))),
MeshMaterial2d(materials.add(TileMapMaterial {
map_size: UVec2::splat(MAP_SIZE),
tile_size: TILE_SIZE,
atlas_texture: tileset_handle.0.clone(),
atlas_size: tile_set.size().as_vec2(),
map_tiles: buffer,
})),
));
}
#[derive(Debug, Resource)]
struct TileSetHandle(Handle<Image>); |
Fantastic, I was trying to come up with a simple example of this! I'm just rolling through a 0.15 migration for |
|
||
fn spawn_map(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) { | ||
let map_size = UVec2::new(5, 5); | ||
let max_chunk_size = UVec2::new(1, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: Make the chunk sizes larger
let max_chunk_size = UVec2::new(1, 1); | |
let max_chunk_size = UVec2::new(3, 3); |
@@ -40,7 +40,7 @@ impl MapData for HexMapData { | |||
|
|||
fn break_data_vecs_down_into_chunk_data<TileData>( | |||
&self, | |||
data: &Vec<Vec<TileData>>, | |||
data: &[Vec<TileData>], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain what this change does? I saw that its made throughout the project and everything is working great but I would like to understand the difference that it makes.
@@ -19,3 +19,9 @@ pub enum TilemapManagerError { | |||
#[error("TileData does not exist for the given ChunkCell")] | |||
TileDataDoesNotExist, | |||
} | |||
|
|||
impl<'w> From<QueryEntityError<'w>> for TilemapManagerError { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain what this change does? Is there a reason to not use the #[from] generated impl?
@notmd Thank you very much for that example! I'm gonna put together a repo for rendering examples and I will include that in it. I'd like to keep this crate itself free from dealing with rendering as its way outside my wheelbox and I want to maintain the capability of updating it easily in the future. @bas-ie Did a quick pass through and everything seems great! Should be good to publish it whenever dependencies are updated and this pr can actually be merged. Thank you so much for doing the update! |
Yep, almost there, have all but finished the |
I've been playing with
bevy_sparse_tilemap
a bit lately, because the "BYO renderer" model is quite interesting and helps me learn a bit about how rendering is changing in 0.15. I've managed to cobble together a version that works reasonably well with 0.15.0-rc.3. I've avoided the problem ofbevy_fast_tilemap
use for now, though I may reintroduce it if I end up upgrading that library too 😆I have branches for upgrading
hexx
andlettuces
also, which I'll PR when I know I don't need any more changes in those.I did run into some trouble with incompatible versions of
glam
. I wondered if it would be possible to standardise on Bevy's exported versions of e.g. Vec2 and Vec3 to avoid that problem, not sure 🤔Where you find a change that doesn't seem to be related to 0.15, it's probably because clippy was complaining about it 😄 I think I've managed to get rid of all the warnings now.