fix: cross-fade tiles to sky tile using alpha instead of color tint
Replace df_fade_color (multiplicative tint that preserves texture hue) with tile_for_depth which cross-fades between real tile and sky tile: - z_diff <= 0: real tile at full opacity (no fade) - z_diff in (0, threshold): real tile fades out via alpha - z_diff past threshold: sky tile (index 0) fades in - invisible tiles: solid sky colour Also fix tile_id_to_tileset_index to include sky (id=0) as index 0, so sky tiles render correctly as the fade target.
This commit is contained in:
@@ -69,7 +69,7 @@ pub const FIXTURE_ROW_OFFSET: u16 = 6;
|
|||||||
|
|
||||||
fn tile_id_to_tileset_index(tile_id: u32) -> Option<u16> {
|
fn tile_id_to_tileset_index(tile_id: u32) -> Option<u16> {
|
||||||
if tile_id == 0 {
|
if tile_id == 0 {
|
||||||
return None;
|
return Some(0);
|
||||||
}
|
}
|
||||||
if tile_id <= 5 {
|
if tile_id <= 5 {
|
||||||
return Some(tile_id as u16);
|
return Some(tile_id as u16);
|
||||||
@@ -82,22 +82,44 @@ fn tile_id_to_tileset_index(tile_id: u32) -> Option<u16> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn df_fade_color(z_diff: i32) -> Color {
|
fn tile_for_depth(real_index: u16, z_diff: i32) -> TileData {
|
||||||
|
const SKY_R: f32 = 133_f32 / 255_f32;
|
||||||
|
const SKY_G: f32 = 167_f32 / 255_f32;
|
||||||
|
const SKY_B: f32 = 178_f32 / 255_f32;
|
||||||
|
const LAYER_ALPHA: f32 = 70_f32 / 255_f32;
|
||||||
|
|
||||||
if z_diff <= 0 {
|
if z_diff <= 0 {
|
||||||
return Color::WHITE;
|
return TileData {
|
||||||
|
tileset_index: real_index,
|
||||||
|
color: Color::WHITE,
|
||||||
|
visible: true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let n = (z_diff as f32).min(8_f32);
|
let n = (z_diff as f32).min(8_f32);
|
||||||
let overlay_r = 133_f32 / 255_f32;
|
let t = 1_f32 - (1_f32 - LAYER_ALPHA).powf(n);
|
||||||
let overlay_g = 167_f32 / 255_f32;
|
|
||||||
let overlay_b = 178_f32 / 255_f32;
|
if t >= 0.98 {
|
||||||
let layer_alpha = 41_f32 / 255_f32;
|
return TileData {
|
||||||
let acc_alpha = 1_f32 - (1_f32 - layer_alpha).powf(n);
|
tileset_index: 0,
|
||||||
let inv = 1_f32 - acc_alpha;
|
color: Color::srgb(SKY_R, SKY_G, SKY_B),
|
||||||
Color::srgb(
|
visible: true,
|
||||||
overlay_r * acc_alpha + inv,
|
};
|
||||||
overlay_g * acc_alpha + inv,
|
}
|
||||||
overlay_b * acc_alpha + inv,
|
|
||||||
)
|
if t < 0.5 {
|
||||||
|
TileData {
|
||||||
|
tileset_index: real_index,
|
||||||
|
color: Color::srgba(1_f32, 1_f32, 1_f32, 1_f32 - t * 2_f32),
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TileData {
|
||||||
|
tileset_index: 0,
|
||||||
|
color: Color::srgba(SKY_R, SKY_G, SKY_B, (t - 0.5_f32) * 2_f32),
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_tile_visible_at_z(tile_data: &FloorTileData, z_index: usize) -> bool {
|
fn is_tile_visible_at_z(tile_data: &FloorTileData, z_index: usize) -> bool {
|
||||||
@@ -134,19 +156,19 @@ fn populate_chunk_tiles(
|
|||||||
);
|
);
|
||||||
let tile = tilemap.get_floor(&world_pos);
|
let tile = tilemap.get_floor(&world_pos);
|
||||||
match tile {
|
match tile {
|
||||||
Some(t) if tile_id_to_tileset_index(t.id as u32).is_some() => {
|
Some(t) => {
|
||||||
let visible = is_tile_visible_at_z(t, z_index);
|
let idx = tile_id_to_tileset_index(t.id as u32);
|
||||||
let color = if visible {
|
if let Some(tileset_idx) = idx {
|
||||||
df_fade_color(z_diff)
|
let is_visible = is_tile_visible_at_z(t, z_index);
|
||||||
|
let tile_data = if is_visible {
|
||||||
|
tile_for_depth(tileset_idx, z_diff)
|
||||||
} else {
|
} else {
|
||||||
Color::BLACK
|
tile_for_depth(0, 999)
|
||||||
};
|
};
|
||||||
let tileset_idx = tile_id_to_tileset_index(t.id as u32).unwrap();
|
tiles.push(Some(tile_data));
|
||||||
tiles.push(Some(TileData {
|
} else {
|
||||||
tileset_index: tileset_idx,
|
tiles.push(None);
|
||||||
color,
|
}
|
||||||
visible,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
_ => tiles.push(None),
|
_ => tiles.push(None),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user