From 8eb9ab2d636d15682f0cb38b2cabf38d10211fbd Mon Sep 17 00:00:00 2001 From: Jared Roberts Date: Mon, 10 Oct 2016 18:43:09 -0700 Subject: [PATCH] use upscaled mipmaps for tiles --- src/bin/vrtue.rs | 6 +++- src/ega.rs | 68 +++++++++++++++++++++++++++++++++++++++++---- src/scenes/world.rs | 10 ++++--- src/tile.rs | 31 +++++++++++++++------ 4 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/bin/vrtue.rs b/src/bin/vrtue.rs index 3750385..7c2d4f7 100644 --- a/src/bin/vrtue.rs +++ b/src/bin/vrtue.rs @@ -19,7 +19,11 @@ pub fn main() { .vsync(false) .build().expect("Building Window"); - let mut scene = scenes::world::WorldScene::new(&mut window.factory, &mut window.encoder); + let mut aux_command = window.factory.create_command_buffer(); + let mut scene = scenes::world::WorldScene::new(&mut window.device, + &mut window.factory, + &mut window.encoder, + &mut aux_command); let view = view::ViewRoot:: ::create_view(&mut window, &mut vr); diff --git a/src/ega.rs b/src/ega.rs index 54c9710..bd59539 100644 --- a/src/ega.rs +++ b/src/ega.rs @@ -28,12 +28,68 @@ pub enum Tiling { pub struct EgaPage { pub data: Vec, - pub tilesize: u16, + pub dim: usize, } impl EgaPage { pub fn iter<'a>(&'a self) -> impl Iterator { - self.data.chunks(self.tilesize as usize) + self.data.chunks(4 * self.dim * self.dim) + } + + pub fn mipmap(&self, scale_levels: u8) -> Mipmap { + let scale = 1 << scale_levels; + let scaled: Vec> = self.iter().map(|tile| { + let mut tilevec = Vec::new(); + for row in tile.chunks(4 * self.dim) { + for _ in 0..scale { + for px in row.chunks(4) { + for subpx in px.iter().cycle().take(4 * scale) { + tilevec.push(*subpx); + } + } + } + } + tilevec + }).collect(); + + // dummy buffers just to provide proper sizing on texture for mips + let dim = self.dim << scale_levels; + let mut dummies = Vec::new(); + + let mut level = 1; + loop { + let mipdim = dim >> level; + if mipdim == 0 { break; } + dummies.push(vec![0; 4 * mipdim * mipdim]); + level += 1; + } + + Mipmap { + len: self.data.len() / (4 * self.dim * self.dim), + dim: dim, + backing: scaled, + dummies: dummies, + } + } +} + +pub struct Mipmap { + pub len: usize, + pub dim: usize, + backing: Vec>, + dummies: Vec>, +} + +impl Mipmap { + pub fn slices(&self) -> Vec<&[u8]> { + let mut slices: Vec<&[u8]> = Vec::with_capacity((1 + self.dummies.len()) * self.len); + for tile in self.backing.iter() { + slices.push(tile); + for dummy in self.dummies.iter() { + slices.push(&dummy); + } + } + slices } } @@ -53,9 +109,9 @@ pub fn decode<'a>(buf: &[u8], compression: Compression, tiling: Tiling) .collect(), _ => unimplemented!() }; - let tilesize = match tiling { - Tiling::TILED(tiledim) => 4 * tiledim * tiledim, - Tiling::UNTILED => out.len() as u16 + let dim = match tiling { + Tiling::TILED(tiledim) => tiledim as usize, + Tiling::UNTILED => out.len() }; - EgaPage { data: out, tilesize: tilesize} + EgaPage { data: out, dim: dim} } diff --git a/src/scenes/world.rs b/src/scenes/world.rs index d059785..541b89e 100644 --- a/src/scenes/world.rs +++ b/src/scenes/world.rs @@ -136,8 +136,10 @@ pub struct WorldScene> WorldScene { - pub fn new(factory: &mut F, - encoder: &mut gfx::Encoder) -> WorldScene { + pub fn new(device: &mut D, + factory: &mut F, + encoder: &mut gfx::Encoder, + aux_command: &mut ::CommandBuffer) -> WorldScene { let (model, model_idx) = get_model(&get_data_model()); let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&model, &model_idx[..]); @@ -155,8 +157,8 @@ impl> WorldScene { camera: na::Matrix4::one(), constants: constants, locals: factory.create_constant_buffer(1), - atlas: tile::get_tiles::<_, _, view::ColorFormat>(factory), - sampler: factory.create_sampler(tex::SamplerInfo::new(tex::FilterMethod::Scale, + atlas: tile::get_tiles::<_, _, view::ColorFormat>(device, factory, aux_command), + sampler: factory.create_sampler(tex::SamplerInfo::new(tex::FilterMethod::Jrd, tex::WrapMode::Tile)), f: PhantomData, diff --git a/src/tile.rs b/src/tile.rs index 882003c..b412fae 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -6,30 +6,45 @@ use ::std; use std::io::Read; use std::path::Path; +use self::gfx::{CommandBuffer, Typed}; use self::gfx::tex; +const TILEDIM: u16 = 16; + #[repr(C)] #[derive(Clone, Copy)] pub struct Tile { pub val: u8, } -pub fn get_tiles(factory: &mut F) -> (//gfx::handle::Texture, - gfx::handle::ShaderResourceView) - where R: gfx::Resources, - F: gfx::Factory, +pub fn get_tiles(device: &mut D, + factory: &mut F, + command: &mut ::CommandBuffer) + -> gfx::handle::ShaderResourceView + where D: gfx::Device, + F: gfx::Factory, T: gfx::format::TextureFormat { let filename = "data/SHAPES.EGA"; let mut file = std::fs::File::open(Path::new(filename)) .expect(&format!("failed opening tiles file: {}", filename)); let mut ega_bytes = Vec::new(); file.read_to_end(&mut ega_bytes).expect("Read tiles file"); - let ega_page = ega::decode(&ega_bytes, ega::Compression::UNCOMPRESSED, ega::Tiling::TILED(16)); - let tiles: Vec<&[u8]> = ega_page.iter().collect(); - let tex = factory.create_texture_const_u8::(tex::Kind::D2Array(16, 16, 256, + let ega_page = ega::decode(&ega_bytes, ega::Compression::UNCOMPRESSED, ega::Tiling::TILED(TILEDIM)); + let mipmap = ega_page.mipmap(2); + + let tex = factory.create_texture_const_u8::(tex::Kind::D2Array(mipmap.dim as u16, + mipmap.dim as u16, + mipmap.len as u16, tex::AaMode::Single), - &tiles) + &mipmap.slices()) .expect("create tile texture"); + + { + let mut manager = gfx::handle::Manager::::new(); + let view = manager.ref_srv(tex.1.raw()); + command.generate_mipmap(*view); + device.submit(command); + } tex.1 }