@Kevin_Ring and this this the implementation of mine fog cull.
// fog_cull.rs
#[derive(Debug, Clone)]
struct FogDensityAtHeight {
height: f64,
density: f64,
}
static FOG_DENSITY_TABLE: [FogDensityAtHeight; 21] = [
FogDensityAtHeight {
height: 359.393,
density: 2.0e-5,
},
FogDensityAtHeight {
height: 800.749,
density: 2.0e-4,
},
FogDensityAtHeight {
height: 1275.6501,
density: 1.0e-4,
},
FogDensityAtHeight {
height: 2151.1192,
density: 7.0e-5,
},
FogDensityAtHeight {
height: 3141.7763,
density: 5.0e-5,
},
FogDensityAtHeight {
height: 4777.5198,
density: 4.0e-5,
},
FogDensityAtHeight {
height: 6281.2493,
density: 3.0e-5,
},
FogDensityAtHeight {
height: 12364.307,
density: 1.9e-5,
},
FogDensityAtHeight {
height: 15900.765,
density: 1.0e-5,
},
FogDensityAtHeight {
height: 49889.0549,
density: 8.5e-6,
},
FogDensityAtHeight {
height: 78026.8259,
density: 6.2e-6,
},
FogDensityAtHeight {
height: 99260.7344,
density: 5.8e-6,
},
FogDensityAtHeight {
height: 120036.3873,
density: 5.3e-6,
},
FogDensityAtHeight {
height: 151011.0158,
density: 5.2e-6,
},
FogDensityAtHeight {
height: 156091.1953,
density: 5.1e-6,
},
FogDensityAtHeight {
height: 203849.3112,
density: 4.2e-6,
},
FogDensityAtHeight {
height: 274866.9803,
density: 4.0e-6,
},
FogDensityAtHeight {
height: 319916.3149,
density: 3.4e-6,
},
FogDensityAtHeight {
height: 493552.0528,
density: 2.6e-6,
},
FogDensityAtHeight {
height: 628733.5874,
density: 2.2e-6,
},
FogDensityAtHeight {
height: 1_000_000.0,
density: 0.0,
},
];
#[inline]
pub fn compute_fog_density(height: f64) -> f64 {
let table = &FOG_DENSITY_TABLE;
let idx = match table.binary_search_by(|e| {
e.height
.partial_cmp(&height)
.unwrap_or(std::cmp::Ordering::Less)
}) {
Ok(i) => i,
Err(i) => i,
};
if idx >= table.len() {
return table.last().unwrap().density;
}
if idx == 0 {
return table[0].density;
}
let a = &table[idx - 1];
let b = &table[idx];
let height_a = a.height;
let density_a = a.density;
let height_b = b.height;
let density_b = b.density;
let t = ((height - height_a) / (height_b - height_a)).clamp(0.0, 1.0);
density_a + t * (density_b - density_a)
}
#[inline]
pub fn is_visible_in_fog(distance: f64, fog_density: f64) -> bool {
if fog_density <= 0.0 {
return true;
}
let fog_scalar = distance * fog_density;
(-fog_scalar * fog_scalar).exp() > 0.0
}
and here is max culling distance use the shrink ellipsoid
fn compute_max_culling_distance(position: DVec3, ellipsoid: &Ellipsoid) -> Option<f64> {
let altitude = ellipsoid.cartesian_to_cartographic(position).altitude;
if altitude <= 0.0 {
return None;
}
let d = position.length();
let r = d - altitude;
Some(((d - r) * (d + r)).sqrt())
}