use ::pixel::Pixel;
pub struct FrameBuffer<P: Pixel> {
width: u32,
height: u32,
depth: Vec<f32>,
color: Vec<P>,
viewport: (f32, f32),
}
pub const DEFAULT_DEPTH_VALUE: f32 = ::std::f32::MAX;
impl<P: Pixel> FrameBuffer<P> {
pub fn new(width: u32, height: u32) -> FrameBuffer<P> where P: Default {
FrameBuffer::new_with(width, height, P::default())
}
pub fn new_with(width: u32, height: u32, pixel: P) -> FrameBuffer<P> {
let len = width as usize * height as usize;
FrameBuffer {
width: width,
height: height,
depth: vec![DEFAULT_DEPTH_VALUE; len],
color: vec![pixel; len],
viewport: (width as f32, height as f32)
}
}
pub fn empty_clone(&self) -> FrameBuffer<P> {
let len = self.width as usize * self.height as usize;
FrameBuffer {
width: self.width,
height: self.height,
depth: self.depth.clone(),
color: vec![P::empty(); len],
viewport: self.viewport
}
}
pub fn merge_into(&self, mut other: &mut FrameBuffer<P>, blend_func: &Box<Fn(P, P) -> P + Send + Sync>) {
let (pcolor, pdepth) = self.buffers();
let (mut fcolor, mut fdepth) = other.buffers_mut();
debug_assert_eq!(pcolor.len(), fcolor.len());
debug_assert_eq!(pdepth.len(), fdepth.len());
debug_assert_eq!(pcolor.len(), fdepth.len());
for i in 0..pcolor.len() {
unsafe {
let fd = fdepth.get_unchecked_mut(i);
let pd = pdepth.get_unchecked(i);
if *fd > *pd {
*fd = *pd;
let pc = pcolor.get_unchecked(i);
let fc = fcolor.get_unchecked_mut(i);
*fc = (*blend_func)(*pc, *fc);
}
}
}
}
pub fn clear(&mut self) where P: Default {
self.clear_with(P::default())
}
pub fn clear_with(&mut self, pixel: P) {
for mut dv in &mut self.depth { *dv = DEFAULT_DEPTH_VALUE; }
for mut pv in &mut self.color { *pv = pixel; }
}
pub fn color_buffer(&self) -> &Vec<P> { &self.color }
pub fn color_buffer_mut(&mut self) -> &mut Vec<P> { &mut self.color }
pub fn depth_buffer(&self) -> &Vec<f32> { &self.depth }
pub fn depth_buffer_mut(&mut self) -> &mut Vec<f32> { &mut self.depth }
#[inline]
pub fn buffers(&self) -> (&Vec<P>, &Vec<f32>) {
(&self.color, &self.depth)
}
#[inline]
pub fn buffers_mut(&mut self) -> (&mut Vec<P>, &mut Vec<f32>) {
(&mut self.color, &mut self.depth)
}
#[inline(always)]
pub fn viewport(&self) -> (f32, f32) { self.viewport }
pub fn set_viewport(&mut self, viewport: (f32, f32)) {
self.viewport = viewport;
}
#[inline(always)]
pub fn width(&self) -> u32 { self.width }
#[inline(always)]
pub fn height(&self) -> u32 { self.height }
#[inline(always)]
pub fn check_coordinate(&self, x: u32, y: u32) -> bool {
x < self.width && y < self.height
}
#[inline]
pub unsafe fn pixel(&self, x: u32, y: u32) -> &P {
self.color.get_unchecked(x as usize + y as usize * self.width as usize)
}
#[inline]
pub unsafe fn pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
self.color.get_unchecked_mut(x as usize + y as usize * self.width as usize)
}
#[inline]
pub unsafe fn depth(&self, x: u32, y: u32) -> &f32 {
self.depth.get_unchecked(x as usize + y as usize * self.width as usize)
}
#[inline]
pub unsafe fn depth_mut(&mut self, x: u32, y: u32) -> &mut f32 {
self.depth.get_unchecked_mut(x as usize + y as usize * self.width as usize)
}
#[inline]
pub unsafe fn pixel_depth_mut(&mut self, x: u32, y: u32) -> (&mut P, &mut f32) {
let i = x as usize + y as usize * self.width as usize;
(self.color.get_unchecked_mut(i), self.depth.get_unchecked_mut(i))
}
}