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> {
|
||||
if tile_id == 0 {
|
||||
return None;
|
||||
return Some(0);
|
||||
}
|
||||
if tile_id <= 5 {
|
||||
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 {
|
||||
return Color::WHITE;
|
||||
return TileData {
|
||||
tileset_index: real_index,
|
||||
color: Color::WHITE,
|
||||
visible: true,
|
||||
};
|
||||
}
|
||||
|
||||
let n = (z_diff as f32).min(8_f32);
|
||||
let overlay_r = 133_f32 / 255_f32;
|
||||
let overlay_g = 167_f32 / 255_f32;
|
||||
let overlay_b = 178_f32 / 255_f32;
|
||||
let layer_alpha = 41_f32 / 255_f32;
|
||||
let acc_alpha = 1_f32 - (1_f32 - layer_alpha).powf(n);
|
||||
let inv = 1_f32 - acc_alpha;
|
||||
Color::srgb(
|
||||
overlay_r * acc_alpha + inv,
|
||||
overlay_g * acc_alpha + inv,
|
||||
overlay_b * acc_alpha + inv,
|
||||
)
|
||||
let t = 1_f32 - (1_f32 - LAYER_ALPHA).powf(n);
|
||||
|
||||
if t >= 0.98 {
|
||||
return TileData {
|
||||
tileset_index: 0,
|
||||
color: Color::srgb(SKY_R, SKY_G, SKY_B),
|
||||
visible: true,
|
||||
};
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -134,19 +156,19 @@ fn populate_chunk_tiles(
|
||||
);
|
||||
let tile = tilemap.get_floor(&world_pos);
|
||||
match tile {
|
||||
Some(t) if tile_id_to_tileset_index(t.id as u32).is_some() => {
|
||||
let visible = is_tile_visible_at_z(t, z_index);
|
||||
let color = if visible {
|
||||
df_fade_color(z_diff)
|
||||
Some(t) => {
|
||||
let idx = tile_id_to_tileset_index(t.id as u32);
|
||||
if let Some(tileset_idx) = idx {
|
||||
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 {
|
||||
Color::BLACK
|
||||
tile_for_depth(0, 999)
|
||||
};
|
||||
let tileset_idx = tile_id_to_tileset_index(t.id as u32).unwrap();
|
||||
tiles.push(Some(TileData {
|
||||
tileset_index: tileset_idx,
|
||||
color,
|
||||
visible,
|
||||
}));
|
||||
tiles.push(Some(tile_data));
|
||||
} else {
|
||||
tiles.push(None);
|
||||
}
|
||||
}
|
||||
_ => tiles.push(None),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user