use glam::{Vec2, Vec4};
use super::post::Image;
pub(crate) const MAX_LEVELS: usize = 6;
pub(crate) fn level_count(width: usize, height: usize) -> usize {
let (mut w, mut h, mut levels) = (width, height, 1);
while levels < MAX_LEVELS && w > 8 && h > 8 {
w = (w / 2).max(1);
h = (h / 2).max(1);
levels += 1;
}
levels
}
pub(crate) fn level_of(roughness: f32, levels: usize) -> f32 {
let last = (levels - 1) as f32;
(roughness.clamp(0.0, 1.0).sqrt() * last).min(last)
}
pub(crate) struct ReflectionMap {
levels: Vec<Image>,
}
impl ReflectionMap {
pub(crate) fn new(width: usize, height: usize, data: Vec<Vec4>) -> Self {
let frame = Image {
width,
height,
data,
};
Self {
levels: frame.mip_chain(),
}
}
pub(crate) fn sample(&self, uv: Vec2, roughness: f32) -> Vec4 {
let lod = level_of(roughness, self.levels.len());
let l0 = lod.floor() as usize;
let l1 = (l0 + 1).min(self.levels.len() - 1);
let a = self.levels[l0].sample(uv.x, uv.y);
if l1 == l0 {
return a;
}
a.lerp(self.levels[l1].sample(uv.x, uv.y), lod - l0 as f32)
}
}