Skip to content

Commit

Permalink
feat: add a new TilemapRenderSettings to control chunks RenderOrder
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien-bon committed Jul 24, 2024
1 parent 857caa5 commit 1b4e653
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 3 deletions.
3 changes: 2 additions & 1 deletion examples/3d_iso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Map size is 12x12 so we'll have render chunks that are:
// 12 tiles wide and 1 tile tall.
render_chunk_size: UVec2::new(3, 1),
y_sort: true,
y_sort: true, // equivalent to render_order: RenderOrder::YReverseThenX
..Default::default()
},
..Default::default()
});
Expand Down
72 changes: 71 additions & 1 deletion src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,80 @@ use bevy::ecs::reflect::ReflectMapEntities;
use bevy::prelude::{ReflectComponent, Res, ResMut};
use bevy::render::render_resource::TextureUsages;
use bevy::{
math::{UVec2, Vec2},
math::{UVec2, Vec2, Vec3},
prelude::{Component, Deref, DerefMut, Entity, Handle, Image, Reflect},
};

/// The default chunk_size (in tiles) used per mesh.
pub const CHUNK_SIZE_2D: UVec2 = UVec2::from_array([64, 64]);

/// The order in which we want to perform the render
#[derive(Clone, Debug, Copy, Default)]
pub enum RenderOrder {
#[default]
None,
XThenY,
XReverseThenY,
XThenYReverse,
XReverseThenYReverse,
YThenX,
YReverseThenX,
YThenXReverse,
YReverseThenXReverse,
}

impl RenderOrder {
/// Compute a new Z translation value based upon the selected render order
/// Returned Z value will have an offset between 0 and 11
pub fn compute_z_translation(
&self,
translation: &Vec3,
tilemap_size: TilemapSize,
tile_size: TilemapTileSize,
) -> f32 {
let scaling_factor = 10.;
let map_size_x = tilemap_size.x as f32 * tile_size.x;
let map_size_y = tilemap_size.y as f32 * tile_size.y;
let mut z_value = translation.z;
match self {
Self::XThenY => {
z_value += scaling_factor * (translation.x / map_size_x);
z_value += translation.y / map_size_y;
}
Self::XReverseThenY => {
z_value += scaling_factor * (1. - (translation.x / map_size_x));
z_value += translation.y / map_size_y;
}
Self::XThenYReverse => {
z_value += scaling_factor * (translation.x / map_size_x);
z_value += 1. - (translation.y / map_size_y);
}
Self::XReverseThenYReverse => {
z_value += scaling_factor * (1. - (translation.x / map_size_x));
z_value += 1. - (translation.y / map_size_y);
}
Self::YThenX => {
z_value += translation.x / map_size_x;
z_value += scaling_factor * (translation.y / map_size_y);
}
Self::YReverseThenX => {
z_value += translation.x / map_size_x;
z_value += scaling_factor * (1. - (translation.y / map_size_y));
}
Self::YThenXReverse => {
z_value += 1. - (translation.x / map_size_x);
z_value += scaling_factor * (translation.y / map_size_y);
}
Self::YReverseThenXReverse => {
z_value += 1. - (translation.x / map_size_x);
z_value += scaling_factor * (1. - (translation.y / map_size_y));
}
_ => {}
};
z_value
}
}

/// Custom parameters for the render pipeline.
///
/// It must be added as a component to the tilemap entity.
Expand All @@ -30,13 +97,16 @@ pub struct TilemapRenderSettings {
///
/// `render_chunk_size`'s `z` value should be `1` when using this for 3d isometric tilemaps.
pub y_sort: bool,
/// The order in which we will render each chunk relative to each other
pub render_chunk_order: RenderOrder,
}

impl Default for TilemapRenderSettings {
fn default() -> Self {
Self {
render_chunk_size: CHUNK_SIZE_2D,
y_sort: false,
render_chunk_order: RenderOrder::None,
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/render/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use bevy::{
render::mesh::MeshVertexBufferLayouts,
};

use crate::map::RenderOrder;
use crate::prelude::helpers::transform::{chunk_aabb, chunk_index_to_world_space};
use crate::render::extract::ExtractedFrustum;
use crate::{
Expand Down Expand Up @@ -59,6 +60,7 @@ impl RenderChunk2dStorage {
frustum_culling: &FrustumCulling,
render_size: RenderChunkSize,
y_sort: bool,
render_order: RenderOrder,
) -> &mut RenderChunk2d {
let pos = position.xyz();

Expand Down Expand Up @@ -96,6 +98,7 @@ impl RenderChunk2dStorage {
**frustum_culling,
render_size,
y_sort,
render_order,
);
self.entity_to_chunk.insert(chunk_entity, pos);
chunk_storage.insert(pos, chunk);
Expand Down Expand Up @@ -220,6 +223,7 @@ pub struct RenderChunk2d {
pub frustum_culling: bool,
pub render_size: RenderChunkSize,
pub y_sort: bool,
pub render_chunk_order: RenderOrder,
}

impl RenderChunk2d {
Expand All @@ -241,6 +245,7 @@ impl RenderChunk2d {
frustum_culling: bool,
render_size: RenderChunkSize,
y_sort: bool,
render_chunk_order: RenderOrder,
) -> Self {
let position = chunk_index_to_world_space(index.xy(), size_in_tiles, &grid_size, &map_type);
let local_transform = Transform::from_translation(position.extend(0.0));
Expand Down Expand Up @@ -277,6 +282,7 @@ impl RenderChunk2d {
frustum_culling,
render_size,
y_sort,
render_chunk_order,
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/render/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,11 @@ pub fn queue_material_tilemap_meshes<M: MaterialTilemap>(
- (transform.translation.y
/ (chunk.map_size.y as f32 * chunk.tile_size.y)))
} else {
transform.translation.z
chunk.render_chunk_order.compute_z_translation(
&transform.translation,
chunk.map_size,
chunk.tile_size,
)
};
transparent_phase.add(Transparent2d {
entity,
Expand Down
1 change: 1 addition & 0 deletions src/render/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ pub(crate) fn prepare(
frustum_culling,
chunk_size,
tilemap_render_settings.y_sort,
tilemap_render_settings.render_chunk_order,
);
chunk.set(
&in_chunk_tile_index.into(),
Expand Down

0 comments on commit 1b4e653

Please sign in to comment.