diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:21 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:21 +0100 |
commit | 9f6b7a10e7e00edf6ab50a9cf162b377d84a43f6 (patch) | |
tree | fe4ebd024c59376c425073b4fa747fa70824d171 | |
parent | 26c325640df7ab8b9ea4a6c3fd5166f7df7f80ff (diff) |
feat(render) WIP: textures, using a fixed size texture array
currently using an 8 long texture array with seperate samplers.
also move to a trait for resolving textures from the bsp file rather than adding them manually. currently stuck with one static implementation though. this means all textures in the file are loaded when the map is.
not currently drawing with anything other than the first texture array, so files with >8 textures will fail.
-rw-r--r-- | examples/render-bsp/Cargo.toml | 1 | ||||
-rw-r--r-- | examples/render-bsp/src/main.rs | 25 | ||||
-rw-r--r-- | stockton-render/src/draw/context.rs | 24 | ||||
-rw-r--r-- | stockton-render/src/draw/data/stockton.frag | 4 | ||||
-rw-r--r-- | stockton-render/src/draw/data/stockton.vert | 4 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/chunk.rs | 152 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/image.rs (renamed from stockton-render/src/draw/texture.rs) | 195 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/loader.rs | 161 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/mod.rs | 22 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/resolver.rs | 54 | ||||
-rw-r--r-- | stockton-render/src/lib.rs | 4 |
11 files changed, 425 insertions, 221 deletions
diff --git a/examples/render-bsp/Cargo.toml b/examples/render-bsp/Cargo.toml index 666f035..b8b5a9d 100644 --- a/examples/render-bsp/Cargo.toml +++ b/examples/render-bsp/Cargo.toml @@ -8,5 +8,6 @@ stockton-render = { path = "../../stockton-render", features = ["vulkan"] } stockton-types = { path = "../../stockton-types" } stockton-levels = { path = "../../stockton-levels" } winit = "^0.21" +log = "0.4.0" simple_logger = "1.0" image = "0.23.2" diff --git a/examples/render-bsp/src/main.rs b/examples/render-bsp/src/main.rs index 51fc80f..0d81759 100644 --- a/examples/render-bsp/src/main.rs +++ b/examples/render-bsp/src/main.rs @@ -19,6 +19,7 @@ extern crate stockton_types; extern crate stockton_levels; extern crate stockton_render; extern crate winit; +extern crate log; extern crate simple_logger; extern crate image; @@ -93,7 +94,7 @@ impl KeyState { } fn main() { - simple_logger::init().unwrap(); + simple_logger::init_with_level(log::Level::Debug).unwrap(); // Load the world and renderer let event_loop = EventLoop::new(); @@ -112,17 +113,17 @@ fn main() { let world = World::new(bsp); let mut renderer = Renderer::new(world, &window).unwrap(); - { - renderer.context.add_texture( - load_from_memory(include_bytes!("../../render-quad/data/test1.png")) - .expect("Couldn't load test texture 1") - .into_rgba()).unwrap(); - - renderer.context.add_texture( - load_from_memory(include_bytes!("../../render-quad/data/test2.png")) - .expect("Couldn't load test texture 2") - .into_rgba()).unwrap(); - } + // { + // renderer.context.add_texture( + // load_from_memory(include_bytes!("../../render-quad/data/test1.png")) + // .expect("Couldn't load test texture 1") + // .into_rgba()).unwrap(); + + // renderer.context.add_texture( + // load_from_memory(include_bytes!("../../render-quad/data/test2.png")) + // .expect("Couldn't load test texture 2") + // .into_rgba()).unwrap(); + // } let mut last_update = SystemTime::now(); let mut key_state = KeyState::new(); diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs index db543a4..d4b1f84 100644 --- a/stockton-render/src/draw/context.rs +++ b/stockton-render/src/draw/context.rs @@ -123,7 +123,7 @@ pub struct RenderingContext<'a> { impl<'a> RenderingContext<'a> { /// Create a new RenderingContext for the given window. - pub fn new(window: &Window) -> Result<Self, error::CreationError> { + pub fn new<T: HasTextures>(window: &Window, file: &T) -> Result<Self, error::CreationError> { // Create surface let (instance, mut surface, mut adapters) = unsafe { use hal::Instance; @@ -136,7 +136,7 @@ impl<'a> RenderingContext<'a> { }; // TODO: Properly figure out which adapter to use - let adapter = adapters.remove(0); + let mut adapter = adapters.remove(0); // Device & Queue group let (mut device, mut queue_group) = { @@ -263,7 +263,10 @@ impl<'a> RenderingContext<'a> { }; // Texture store - let texture_store = TextureStore::new(&mut device, INITIAL_TEX_SIZE)?; + let texture_store = TextureStore::new(&mut device, + &mut adapter, + &mut queue_group.queues[0], + &mut cmd_pool, file)?; // Camera // TODO: Settings @@ -467,15 +470,6 @@ impl<'a> RenderingContext<'a> { Ok((format, viewport, extent, swapchain, backbuffer)) } - /// Load the given image into the texturestore, returning the index or an error. - pub fn add_texture(&mut self, image: RgbaImage) -> Result<usize, &'static str> { - self.texture_store.add_texture(image, - &mut self.device, - &mut self.adapter, - &mut self.queue_group.queues[0], - &mut self.cmd_pool) - } - #[allow(clippy::type_complexity)] fn create_pipeline<T>(device: &mut Device, extent: hal::image::Extent, subpass: &hal::pass::Subpass<back::Backend>, set_layouts: T) -> Result< ( @@ -700,7 +694,7 @@ impl<'a> RenderingContext<'a> { buffer.bind_graphics_pipeline(&self.pipeline); let mut descriptor_sets: ArrayVec<[_; 1]> = ArrayVec::new(); - descriptor_sets.push(&self.texture_store.descriptor_set); + descriptor_sets.push(self.texture_store.get_chunk_descriptor_set(0)); buffer.bind_graphics_descriptor_sets( &self.pipeline_layout, @@ -773,11 +767,11 @@ impl<'a> RenderingContext<'a> { /// Load all active faces into the vertex buffers for drawing // TODO: This is just a POC, we need to restructure things a lot for actually texturing, etc - pub fn set_active_faces<M: MinBSPFeatures<VulkanSystem>>(&mut self, faces: Vec<u32>, file: &M) -> () { + pub fn set_active_faces<M: MinBSPFeatures<VulkanSystem>>(&mut self, faces: &Vec<u32>, file: &M) -> () { let mut curr_vert_idx: usize = 0; let mut curr_idx_idx: usize = 0; - for face in faces.into_iter().map(|idx| file.get_face(idx)) { + for face in faces.into_iter().map(|idx| file.get_face(*idx)) { if face.face_type == FaceType::Polygon || face.face_type == FaceType::Mesh { let base = face.vertices_idx.start; diff --git a/stockton-render/src/draw/data/stockton.frag b/stockton-render/src/draw/data/stockton.frag index c50e1b9..5c6e1d7 100644 --- a/stockton-render/src/draw/data/stockton.frag +++ b/stockton-render/src/draw/data/stockton.frag @@ -1,8 +1,8 @@ #version 450 // DescriptorSet 0 = Textures -layout(set = 0, binding = 0) uniform texture2D tex[2]; -layout(set = 0, binding = 1) uniform sampler samp[2]; +layout(set = 0, binding = 0) uniform texture2D tex[8]; +layout(set = 0, binding = 1) uniform sampler samp[8]; layout (location = 1) in vec2 frag_uv; layout (location = 2) in flat int frag_tex; diff --git a/stockton-render/src/draw/data/stockton.vert b/stockton-render/src/draw/data/stockton.vert index 3146a25..aaee1a5 100644 --- a/stockton-render/src/draw/data/stockton.vert +++ b/stockton-render/src/draw/data/stockton.vert @@ -6,8 +6,8 @@ layout (push_constant) uniform PushConsts { } push; layout (location = 0) in vec3 position; -layout (location = 1) in vec2 uv; -layout (location = 2) in int tex; +layout (location = 1) in int tex; +layout (location = 2) in vec2 uv; out gl_PerVertex { vec4 gl_Position; diff --git a/stockton-render/src/draw/texture/chunk.rs b/stockton-render/src/draw/texture/chunk.rs new file mode 100644 index 0000000..9356274 --- /dev/null +++ b/stockton-render/src/draw/texture/chunk.rs @@ -0,0 +1,152 @@ +// Copyright (C) 2019 Oscar Shrimpton + +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. + +//! A chunk of textures is an array of textures, the size of which is known at compile time. +//! This reduces the number of times we need to re-bind our descriptor sets + +use image::{Rgba, RgbaImage}; +use hal::prelude::*; + +use core::{ + mem::{replace} +}; +use std::ops::{Range, Deref}; + +use crate::{ + types::*, + error +}; + +use log::debug; +use super::resolver::TextureResolver; +use super::image::LoadedImage; +use stockton_levels::prelude::*; + +/// The size of a chunk. Needs to match up with the fragment shader +pub const CHUNK_SIZE: usize = 8; + +/// An array of textures +pub struct TextureChunk { + pub(crate) descriptor_set: DescriptorSet, + loaded_images: Vec<LoadedImage>, +} + +impl TextureChunk { + pub fn new<T: HasTextures, R: TextureResolver>(device: &mut Device, + adapter: &mut Adapter, + command_queue: &mut CommandQueue, + command_pool: &mut CommandPool, + pool: &mut DescriptorPool, + layout: &DescriptorSetLayout, + file: &T, range: Range<u32>, + resolver: &mut R) -> Result<TextureChunk, error::CreationError> { + + let descriptor_set = unsafe { + pool.allocate_set(&layout).map_err(|e| { + println!("{:?}", e); + error::CreationError::OutOfMemoryError + })? + }; + + let mut store = TextureChunk { + descriptor_set: descriptor_set, + loaded_images: Vec::with_capacity(CHUNK_SIZE), + }; + + let mut local_idx = 0; + + debug!("Created descriptor set"); + for tex_idx in range { + debug!("Loading tex {}", local_idx + 1); + let tex = file.get_texture(tex_idx); + let img = resolver.resolve(tex); + store.put_texture(img, local_idx, + device, adapter, + command_queue, command_pool).unwrap(); + + local_idx += 1; + } + + // Pad out the end if needed + while local_idx < CHUNK_SIZE { + debug!("Putting a placeholder in slot {}", local_idx); + store.put_texture(RgbaImage::from_pixel(1, 1, Rgba ([0, 0, 0, 1])), local_idx, + device, adapter, + command_queue, command_pool).unwrap(); + + local_idx += 1; + } + + Ok(store) + } + + + pub fn put_texture(&mut self, image: RgbaImage, + idx: usize, + device: &mut Device, + adapter: &mut Adapter, + command_queue: &mut CommandQueue, + command_pool: &mut CommandPool) -> Result<(), &'static str>{ + + // Load the image + let texture = LoadedImage::load( + image, + device, + adapter, + command_queue, + command_pool, + )?; + + // Write it to the descriptor set + unsafe { + use hal::pso::{DescriptorSetWrite, Descriptor}; + use hal::image::Layout; + + device.write_descriptor_sets(vec![ + DescriptorSetWrite { + set: &self.descriptor_set, + binding: 0, + array_offset: idx, + descriptors: Some(Descriptor::Image( + texture.image_view.deref(), + Layout::ShaderReadOnlyOptimal + )), + }, + DescriptorSetWrite { + set: &self.descriptor_set, + binding: 1, + array_offset: idx, + descriptors: Some(Descriptor::Sampler(texture.sampler.deref())), + }, + ]); + }; + + // Store it so we can safely deactivate it when we need to + // Deactivate the old image if we need to + if idx < self.loaded_images.len() { + replace(&mut self.loaded_images[idx], texture).deactivate(device); + } else { + self.loaded_images.push(texture); + } + + Ok(()) + } + + pub fn deactivate(mut self, device: &mut Device) -> () { + for img in self.loaded_images.drain(..) { + img.deactivate(device); + } + } +}
\ No newline at end of file diff --git a/stockton-render/src/draw/texture.rs b/stockton-render/src/draw/texture/image.rs index 19f60d9..fec84a2 100644 --- a/stockton-render/src/draw/texture.rs +++ b/stockton-render/src/draw/texture/image.rs @@ -13,17 +13,12 @@ // You should have received a copy of the GNU General Public License along // with this program. If not, see <http://www.gnu.org/licenses/>. -//! Deals with loading textures into GPU memory - -use core::mem::{ManuallyDrop, size_of}; -use std::{ - mem::replace, - ptr::copy_nonoverlapping, - convert::TryInto, - iter::once, - ops::Deref -}; - +use core::ptr::copy_nonoverlapping; +use std::iter::once; +use core::mem::size_of; +use image::RgbaImage; +use draw::buffer::create_buffer; +use core::mem::ManuallyDrop; use hal::{ MemoryTypeId, buffer::Usage as BufUsage, @@ -33,188 +28,12 @@ use hal::{ memory::{Properties as MemProperties, Dependencies as MemDependencies, Segment}, prelude::*, }; - -use image::RgbaImage; - -use crate::error; +use std::convert::TryInto; use crate::types::*; -use super::buffer::create_buffer; /// The size of each pixel in an image const PIXEL_SIZE: usize = size_of::<image::Rgba<u8>>(); -/// Stores all loaded textures in GPU memory. -/// When rendering, the descriptor sets are bound to the buffer -/// The descriptor set layout should have the same count of textures as this does. -/// Note that it's possible not all descriptors are actually initialised images -pub struct TextureStore { - descriptor_pool: ManuallyDrop<DescriptorPool>, - pub descriptor_set: DescriptorSet, - pub descriptor_set_layout: ManuallyDrop<DescriptorSetLayout>, - loaded_images: Vec<LoadedImage>, - next_index: usize, - size: usize -} - -impl TextureStore { - pub fn new(device: &mut Device, size: usize) -> Result<TextureStore, error::CreationError> { - - // Descriptor set layout - let descriptor_set_layout = unsafe { - use hal::pso::{DescriptorSetLayoutBinding, DescriptorType, ShaderStageFlags, ImageDescriptorType}; - - device.create_descriptor_set_layout( - &[ - DescriptorSetLayoutBinding { - binding: 0, - ty: DescriptorType::Image { - ty: ImageDescriptorType::Sampled { - with_sampler: false - } - }, - count: size, - stage_flags: ShaderStageFlags::FRAGMENT, - immutable_samplers: false - }, - DescriptorSetLayoutBinding { - binding: 1, - ty: DescriptorType::Sampler, - count: size, - stage_flags: ShaderStageFlags::FRAGMENT, - immutable_samplers: false - } - ], - &[], - ) - }.map_err(|_| error::CreationError::OutOfMemoryError)?; - - let (descriptor_pool, descriptor_set) = unsafe { - use hal::pso::{DescriptorRangeDesc, DescriptorType, DescriptorPoolCreateFlags, ImageDescriptorType}; - - let mut pool = device.create_descriptor_pool( - 1, - &[ - DescriptorRangeDesc { - ty: DescriptorType::Image { - ty: ImageDescriptorType::Sampled { - with_sampler: false - } - }, - count: size - }, - DescriptorRangeDesc { - ty: DescriptorType::Sampler, - count: size - } - ], - DescriptorPoolCreateFlags::empty() - ).map_err(|_| error::CreationError::OutOfMemoryError)?; - - let set = pool.allocate_set(&descriptor_set_layout).map_err(|_| error::CreationError::OutOfMemoryError)?; - - (pool, set) - }; - - Ok(TextureStore { - descriptor_pool: ManuallyDrop::new(descriptor_pool), - descriptor_set: descriptor_set, - loaded_images: Vec::with_capacity(size), - descriptor_set_layout: ManuallyDrop::new(descriptor_set_layout), - next_index: 0, - size - }) - } - - /// Add the texture to this texturestore - /// Returns the allocated index or the error. - // TODO: Better error - pub fn add_texture(&mut self, image: RgbaImage, - device: &mut Device, - adapter: &mut Adapter, - command_queue: &mut CommandQueue, - command_pool: &mut CommandPool) -> Result<usize, &'static str> { - - if self.next_index == self.size { - return Err("Texture requested but store is out of space!"); - } - - let idx = self.next_index; - self.put_texture(image, idx, device, adapter, command_queue, command_pool)?; - self.next_index += 1; - - Ok(idx) - } - - pub fn put_texture(&mut self, image: RgbaImage, - idx: usize, - device: &mut Device, - adapter: &mut Adapter, - command_queue: &mut CommandQueue, - command_pool: &mut CommandPool) -> Result<(), &'static str>{ - - if idx >= self.size || idx > self.loaded_images.len() { - return Err("Texture index out of bounds or non-continuous index!"); - } - - // Load the image - let texture = LoadedImage::load( - image, - device, - adapter, - command_queue, - command_pool, - )?; - - // Write it to the descriptor set - unsafe { - use hal::pso::{DescriptorSetWrite, Descriptor}; - use hal::image::Layout; - - device.write_descriptor_sets(vec![ - DescriptorSetWrite { - set: &self.descriptor_set, - binding: 0, - array_offset: idx, - descriptors: Some(Descriptor::Image( - texture.image_view.deref(), - Layout::ShaderReadOnlyOptimal - )), - }, - DescriptorSetWrite { - set: &self.descriptor_set, - binding: 1, - array_offset: idx, - descriptors: Some(Descriptor::Sampler(texture.sampler.deref())), - }, - ]); - }; - - // Store it so we can safely deactivate it when we need to - // Deactivate the old image if we need to - if idx < self.loaded_images.len() { - replace(&mut self.loaded_images[idx], texture).deactivate(device); - } else { - self.loaded_images.push(texture); - } - - Ok(()) - } - - pub fn deactivate(mut self, device: &mut Device) -> () { - unsafe { - use core::ptr::read; - - for img in self.loaded_images.drain(..) { - img.deactivate(device) - } - - self.descriptor_pool.reset(); - device.destroy_descriptor_pool(ManuallyDrop::into_inner(read(&self.descriptor_pool))); - device - .destroy_descriptor_set_layout(ManuallyDrop::into_inner(read(&self.descriptor_set_layout))); - } - } -} /// Holds an image that's loaded into GPU memory and can be sampled from pub struct LoadedImage { diff --git a/stockton-render/src/draw/texture/loader.rs b/stockton-render/src/draw/texture/loader.rs new file mode 100644 index 0000000..017030f --- /dev/null +++ b/stockton-render/src/draw/texture/loader.rs @@ -0,0 +1,161 @@ +// Copyright (C) 2019 Oscar Shrimpton + +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. +//! Deals with loading textures into GPU memory + +use std::path::Path; +use draw::texture::resolver::BasicFSResolver; +use draw::texture::chunk::CHUNK_SIZE; +use core::mem::{ManuallyDrop}; +use super::chunk::TextureChunk; + +use log::debug; + +use hal::{ + prelude::*, +}; + +use stockton_levels::prelude::*; + +use crate::error; +use crate::types::*; + +/// Stores all loaded textures in GPU memory. +/// When rendering, the descriptor sets are bound to the buffer +/// The descriptor set layout should have the same count of textures as this does. +/// Note that it's possible not all descriptors are actually initialised images +pub struct TextureStore { + descriptor_pool: ManuallyDrop<DescriptorPool>, + pub(crate) descriptor_set_layout: ManuallyDrop<DescriptorSetLayout>, + chunks: Box<[TextureChunk]> +} + +impl TextureStore { + pub fn new<T: HasTextures>(device: &mut Device, + adapter: &mut Adapter, + command_queue: &mut CommandQueue, + command_pool: &mut CommandPool, file: &T) -> Result<TextureStore, error::CreationError> { + // Figure out how many textures in this file + let size = file.textures_iter().count(); + let num_chunks = { + let mut x = size / CHUNK_SIZE; + if size % CHUNK_SIZE != 0 { + x += 1; + } + x + }; + let rounded_size = num_chunks * CHUNK_SIZE; + + let mut descriptor_pool = unsafe { + use hal::pso::{DescriptorRangeDesc, DescriptorType, DescriptorPoolCreateFlags, ImageDescriptorType}; + + device.create_descriptor_pool( + num_chunks, + &[ + DescriptorRangeDesc { + ty: DescriptorType::Image { + ty: ImageDescriptorType::Sampled { + with_sampler: false + } + }, + count: rounded_size + }, + DescriptorRangeDesc { + ty: DescriptorType::Sampler, + count: rounded_size + } + ], + DescriptorPoolCreateFlags::empty() + ).map_err(|e| { + println!("{:?}", e); + error::CreationError::OutOfMemoryError + })? + }; + + // Descriptor set layout + let mut descriptor_set_layout = unsafe { + use hal::pso::{DescriptorSetLayoutBinding, DescriptorType, ShaderStageFlags, ImageDescriptorType}; + + device.create_descriptor_set_layout( + &[ + DescriptorSetLayoutBinding { + binding: 0, + ty: DescriptorType::Image { + ty: ImageDescriptorType::Sampled { + with_sampler: false + } + }, + count: CHUNK_SIZE, + stage_flags: ShaderStageFlags::FRAGMENT, + immutable_samplers: false + }, + DescriptorSetLayoutBinding { + binding: 1, + ty: DescriptorType::Sampler, + count: CHUNK_SIZE, + stage_flags: ShaderStageFlags::FRAGMENT, + immutable_samplers: false + } + ], + &[], + ) + }.map_err(|_| error::CreationError::OutOfMemoryError)?; + + // Set up all our chunks + debug!("Starting to load textures..."); + + let mut resolver = BasicFSResolver::new(Path::new(".")); + + let mut chunks = Vec::with_capacity(num_chunks); + for i in 0..num_chunks { + let range = { + let mut r = (i * CHUNK_SIZE) as u32..((i + 1) * CHUNK_SIZE) as u32; + if r.end > size as u32 { + r.end = size as u32; + } + r + }; + debug!("Chunk {} / {} covering {:?}", i + 1, num_chunks, range); + + chunks.push(TextureChunk::new(device, adapter, command_queue, command_pool, &mut descriptor_pool, &mut descriptor_set_layout, file, range, &mut resolver)?); + } + + debug!("All textures loaded."); + + Ok(TextureStore { + descriptor_pool: ManuallyDrop::new(descriptor_pool), + descriptor_set_layout: ManuallyDrop::new(descriptor_set_layout), + chunks: chunks.into_boxed_slice() + }) + } + + pub fn deactivate(mut self, device: &mut Device) -> () { + unsafe { + use core::ptr::read; + + for chunk in self.chunks.into_vec().drain(..) { + chunk.deactivate(device) + } + + self.descriptor_pool.reset(); + device + .destroy_descriptor_set_layout(ManuallyDrop::into_inner(read(&self.descriptor_set_layout))); + device.destroy_descriptor_pool(ManuallyDrop::into_inner(read(&self.descriptor_pool))); + } + } + + pub fn get_chunk_descriptor_set<'a>(&'a self, idx: usize) -> &'a DescriptorSet { + &self.chunks[idx].descriptor_set + } +} diff --git a/stockton-render/src/draw/texture/mod.rs b/stockton-render/src/draw/texture/mod.rs new file mode 100644 index 0000000..896e1d2 --- /dev/null +++ b/stockton-render/src/draw/texture/mod.rs @@ -0,0 +1,22 @@ +// Copyright (C) 2019 Oscar Shrimpton + +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. + +mod resolver; +mod image; +mod chunk; +pub mod loader; + +pub use self::loader::TextureStore; +pub use self::image::LoadedImage;
\ No newline at end of file diff --git a/stockton-render/src/draw/texture/resolver.rs b/stockton-render/src/draw/texture/resolver.rs new file mode 100644 index 0000000..66bce9e --- /dev/null +++ b/stockton-render/src/draw/texture/resolver.rs @@ -0,0 +1,54 @@ +// Copyright (C) 2019 Oscar Shrimpton + +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. + +//! Resolves a texture in a BSP File to an image + +use stockton_levels::traits::textures::Texture; + +use image::{ + RgbaImage, + io::Reader +}; + +use std::path::Path; + +/// An object that can be used to resolve a texture from a BSP File +pub trait TextureResolver { + fn resolve(&mut self, texture: &Texture) -> RgbaImage; +} + +pub struct BasicFSResolver<'a> { + path: &'a Path +} + +impl<'a> BasicFSResolver<'a> { + pub fn new(path: &'a Path) -> BasicFSResolver<'a> { + BasicFSResolver { + path + } + } +} + +impl<'a> TextureResolver for BasicFSResolver<'a> { + fn resolve(&mut self, tex: &Texture) -> RgbaImage { + let path = self.path.join(&tex.name); + println!("Loading texture from {:?}", path); + + Reader::open(path).unwrap() + .with_guessed_format().unwrap() + .decode().unwrap() + .into_rgba() + } +}
\ No newline at end of file diff --git a/stockton-render/src/lib.rs b/stockton-render/src/lib.rs index b0d73d3..c282967 100644 --- a/stockton-render/src/lib.rs +++ b/stockton-render/src/lib.rs @@ -53,7 +53,7 @@ impl<'a, T: MinBSPFeatures<VulkanSystem>> Renderer<'a, T> { /// Create a new Renderer. /// This initialises all the vulkan context, etc needed. pub fn new(world: World<T>, window: &winit::window::Window) -> Result<Self, CreationError> { - let context = RenderingContext::new(window)?; + let context = RenderingContext::new(window, &world.map)?; Ok(Renderer { world, context @@ -66,7 +66,7 @@ impl<'a, T: MinBSPFeatures<VulkanSystem>> Renderer<'a, T> { let faces = get_visible_faces(self.context.camera_pos(), &self.world.map); // Load them in - self.context.set_active_faces(faces, &self.world.map); + self.context.set_active_faces(&faces, &self.world.map); // Then draw them if let Err(_) = self.context.draw_vertices() { |