use crate::{
fog::FogState,
Rgba,
};
pub trait Acc {
type Data: Clone + Sync;
type In;
type Out;
fn new(data: Self::Data) -> Self;
fn clear(&mut self);
fn upd(&mut self, i: u32, j: u32, depth: f32, data: Self::In);
fn acc(&self, i: u32, j: u32) -> Self::Out;
}
pub struct TileRgbaMinDepthAcc<const TILE_SIZE: usize> {
pub buf: [[(f32, Rgba); TILE_SIZE]; TILE_SIZE],
}
impl<const TILE_SIZE: usize> Acc for TileRgbaMinDepthAcc<TILE_SIZE> {
type Data = ();
type In = Rgba;
type Out = Rgba;
fn new(_: ()) -> Self {
Self {
buf: [[(0.0, [0.0; 4]); TILE_SIZE]; TILE_SIZE],
}
}
fn clear(&mut self) {
self.buf = [[(0.0, [0.0; 4]); TILE_SIZE]; TILE_SIZE];
}
fn upd(&mut self, i: u32, j: u32, depth: f32, color: Rgba) {
let (d, c) = &mut self.buf[j as usize][i as usize];
if *d == 0.0 || *d > depth {
*d = depth;
*c = color;
}
}
fn acc(&self, i: u32, j: u32) -> Rgba {self.buf[j as usize][i as usize].1}
}
pub struct TileRgbaSrgbSemiFogAcc<const TILE_SIZE: usize, const ACC: usize> {
pub buf: [[[(f32, Rgba); ACC]; TILE_SIZE]; TILE_SIZE],
pub len: [[u8; TILE_SIZE]; TILE_SIZE],
}
impl<const TILE_SIZE: usize, const ACC: usize> Acc for TileRgbaSrgbSemiFogAcc<TILE_SIZE, ACC> {
type Data = ();
type In = Rgba;
type Out = Rgba;
fn new(_: ()) -> Self {
Self {
buf: [[[(0.0, [0.0; 4]); ACC]; TILE_SIZE]; TILE_SIZE],
len: [[0; TILE_SIZE]; TILE_SIZE],
}
}
fn clear(&mut self) {
self.buf = [[[(0.0, [0.0; 4]); ACC]; TILE_SIZE]; TILE_SIZE];
self.len = [[0; TILE_SIZE]; TILE_SIZE];
}
fn upd(&mut self, i: u32, j: u32, depth: f32, color: Rgba) {
let len = {
let len = &mut self.len[j as usize][i as usize];
if *len as usize >= ACC {return};
*len += 1;
*len
};
self.ins(len, i, j, depth, color);
}
fn acc(&self, i: u32, j: u32) -> Rgba {
let len = self.len[j as usize][i as usize];
let buf = &self.buf[j as usize][i as usize];
let mut color = [0.0; 4];
let mut fog = FogState::None;
for k in 0..len {
let (d, c) = buf[k as usize];
fog.acc_alpha_blend_srgb_over(d, c, &mut color);
}
fog.acc_end_alpha_blend_srgb_over(&mut color);
color
}
}
impl<const TILE_SIZE: usize, const ACC: usize> TileRgbaSrgbSemiFogAcc<TILE_SIZE, ACC> {
fn ins(&mut self, len: u8, i: u32, j: u32, mut depth: f32, mut color: Rgba) {
let buf = &mut self.buf[j as usize][i as usize];
for k in 0..len {
let (d, c) = buf[k as usize];
if d == 0.0 {
buf[k as usize] = (depth, color);
return;
} else if d > depth {
buf[k as usize] = (depth, color);
if color[3] >= 1.0 {
self.len[j as usize][i as usize] = k + 1;
return
};
depth = d;
color = c;
}
}
}
}
pub struct TileRgbaLinearSemiFogAcc<const TILE_SIZE: usize, const ACC: usize> {
pub buf: [[[(f32, Rgba); ACC]; TILE_SIZE]; TILE_SIZE],
pub len: [[u8; TILE_SIZE]; TILE_SIZE],
}
impl<const TILE_SIZE: usize, const ACC: usize> Acc for TileRgbaLinearSemiFogAcc<TILE_SIZE, ACC> {
type Data = ();
type In = Rgba;
type Out = Rgba;
fn new(_: ()) -> Self {
Self {
buf: [[[(0.0, [0.0; 4]); ACC]; TILE_SIZE]; TILE_SIZE],
len: [[0; TILE_SIZE]; TILE_SIZE],
}
}
fn clear(&mut self) {
self.buf = [[[(0.0, [0.0; 4]); ACC]; TILE_SIZE]; TILE_SIZE];
self.len = [[0; TILE_SIZE]; TILE_SIZE];
}
fn upd(&mut self, i: u32, j: u32, depth: f32, color: Rgba) {
let len = {
let len = &mut self.len[j as usize][i as usize];
if *len as usize >= ACC {return};
*len += 1;
*len
};
self.ins(len, i, j, depth, color);
}
fn acc(&self, i: u32, j: u32) -> Rgba {
let len = self.len[j as usize][i as usize];
let buf = &self.buf[j as usize][i as usize];
let mut color = [0.0; 4];
let mut fog = FogState::None;
for k in 0..len {
let (d, c) = buf[k as usize];
fog.acc_alpha_blend_linear_over(d, c, &mut color);
}
fog.acc_end_alpha_blend_linear_over(&mut color);
color
}
}
impl<const TILE_SIZE: usize, const ACC: usize> TileRgbaLinearSemiFogAcc<TILE_SIZE, ACC> {
fn ins(&mut self, len: u8, i: u32, j: u32, mut depth: f32, mut color: Rgba) {
let buf = &mut self.buf[j as usize][i as usize];
for k in 0..len {
let (d, c) = buf[k as usize];
if d == 0.0 {
buf[k as usize] = (depth, color);
return;
} else if d > depth {
buf[k as usize] = (depth, color);
if color[3] >= 1.0 {
self.len[j as usize][i as usize] = k + 1;
return
};
depth = d;
color = c;
}
}
}
}