use crate::{
core::algebra::Matrix4,
renderer::framework::{
error::FrameworkError,
gpu_texture::{
GpuTexture, GpuTextureDescriptor, GpuTextureKind, MagnificationFilter,
MinificationFilter, PixelKind, WrapMode,
},
server::GraphicsServer,
},
};
use std::{cell::RefCell, rc::Rc};
pub struct MatrixStorage {
texture: Rc<RefCell<dyn GpuTexture>>,
matrices: Vec<Matrix4<f32>>,
}
impl MatrixStorage {
pub fn new(server: &dyn GraphicsServer) -> Result<Self, FrameworkError> {
let identity = [Matrix4::<f32>::identity()];
Ok(Self {
texture: server.create_texture(GpuTextureDescriptor {
kind: GpuTextureKind::Rectangle {
width: 4,
height: 1,
},
pixel_kind: PixelKind::RGBA32F,
min_filter: MinificationFilter::Nearest,
mag_filter: MagnificationFilter::Nearest,
s_wrap_mode: WrapMode::ClampToEdge,
t_wrap_mode: WrapMode::ClampToEdge,
r_wrap_mode: WrapMode::ClampToEdge,
data: Some(crate::core::array_as_u8_slice(&identity)),
..Default::default()
})?,
matrices: Default::default(),
})
}
pub fn texture(&self) -> &Rc<RefCell<dyn GpuTexture>> {
&self.texture
}
pub fn upload(
&mut self,
matrices: impl Iterator<Item = Matrix4<f32>>,
) -> Result<(), FrameworkError> {
self.matrices.clear();
self.matrices.extend(matrices);
let matrices_tex_size = 1024;
let actual_matrices_pixel_count = self.matrices.len() * 4;
let matrices_w = actual_matrices_pixel_count.min(matrices_tex_size);
let matrices_h = (actual_matrices_pixel_count as f32 / matrices_w as f32)
.ceil()
.max(1.0) as usize;
for _ in 0..(((matrices_w * matrices_h) - actual_matrices_pixel_count) / 4) {
self.matrices.push(Default::default());
}
if matrices_w != 0 && matrices_h != 0 {
self.texture.borrow_mut().set_data(
GpuTextureKind::Rectangle {
width: matrices_w,
height: matrices_h,
},
PixelKind::RGBA32F,
1,
Some(crate::core::array_as_u8_slice(&self.matrices)),
)?;
}
Ok(())
}
}