use crate::vertex_2d::{ColoredVertex2D, Vertex2D}; use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState}; use crate::Sprite; use std::collections::HashMap; use vulkano::buffer::{BufferAccess, CpuAccessibleBuffer, BufferUsage}; use std::sync::Arc; use vulkano::format::{ClearValue, Format}; use vulkano::framebuffer::FramebufferAbstract; use vulkano::device::{Device, Queue}; use vulkano::instance::PhysicalDevice; use vulkano::image::immutable::ImmutableImage; use crate::util::shader_kernels::ShaderKernels; use vulkano::image::{Dimensions, ImageUsage, ImageAccess, ImageDimensions}; use vulkano::sampler::{Sampler, SamplerAddressMode, MipmapMode, Filter}; use vulkano::descriptor::DescriptorSet; use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; use std::path::PathBuf; use image::GenericImageView; // Canvas is the accumulator of Sprites for drawing // Needs to know: // textured? // colored? // vertices /* If it is textured. It needs to be rendered with the texture shader which requires a separate graphics pipeline. Might as well have a new render pass as well. I need a second version of shaderkernels So framebuffer is tied to the swapchains images as well as the renderpass it appears that renderpass is tied to the individual shader */ // I want to be able to draw 2d sprites. // These sprites might be textured or a single color // All of the single colors will be grouped into one batch using colored vertices. // The rest will be grouped by their texture and run individually /* vertex count differing is a big nono ColoredVertex2D Non-Textured Vertex2D Textured Colored, vs non-colored: Calling the color() field or not I just wanna */ pub trait Vertex { fn position(&self) -> (f32, f32) { (0.0,0.0) } fn color(&self) -> Option<(f32, f32, f32, f32)> { Some((0.,0.,0.,0.)) } fn textured(&self) -> bool { false } } impl Vertex for ColoredVertex2D { fn position(&self) -> (f32, f32) { (0.0,0.0) } fn color(&self) -> Option<(f32, f32, f32, f32)> { Some((0.,0.,0.,0.)) } fn textured(&self) -> bool { false } } pub trait Drawable { fn get_vertices(&self) -> Vec<(f32, f32)>; fn get_color(&self) -> (f32, f32, f32, f32); fn get_texture_id(&self) -> Option; } pub struct Canvas { colored_drawables : Vec, textured_drawables: HashMap>, vertex_buffers: Vec>, shader_kernels: Vec, textures: Vec>>, } impl Canvas { // needs to take in the texture list pub fn new() -> Canvas { Canvas { colored_drawables: vec![], textured_drawables: Default::default(), vertex_buffers: vec![], shader_kernels: Vec::new(), textures: vec![] } } fn get_texture_from_file(image_filename: String, queue: Arc) -> Arc> { let project_root = std::env::current_dir() .expect("failed to get root directory"); let mut compute_path = project_root.clone(); compute_path.push(PathBuf::from("resources/images/")); compute_path.push(PathBuf::from(image_filename)); let img = image::open(compute_path).expect("Couldn't find image"); let xy = img.dimensions(); let data_length = xy.0 * xy.1 * 4; let pixel_count = img.raw_pixels().len(); let mut image_buffer = Vec::new(); if pixel_count != data_length as usize { println!("Creating apha channel..."); for i in img.raw_pixels().iter() { if (image_buffer.len() + 1) % 4 == 0 { image_buffer.push(255); } image_buffer.push(*i); } image_buffer.push(255); } else { image_buffer = img.raw_pixels(); } let (texture, tex_future) = ImmutableImage::from_iter( image_buffer.iter().cloned(), Dimensions::Dim2d { width: xy.0, height: xy.1 }, Format::R8G8B8A8Srgb, queue.clone() ).unwrap(); texture } pub fn load_texture_from_filename(&mut self, filename: String, queue: Arc) { let texture = Canvas::get_texture_from_file(filename.clone(), queue.clone()); self.textures.push(texture); let texture1 = Canvas::get_texture_from_file(String::from("button.png"), queue.clone()); self.textures.push(texture1); } pub fn draw(&mut self, drawable: &dyn Drawable) { match drawable.get_texture_id() { Some(id) => { // This dont work self.textured_drawables.get(&id).unwrap(); }, None => { let colors = drawable.get_color(); self.colored_drawables.extend( drawable.get_vertices().iter().map(|n| ColoredVertex2D { position: [n.0, n.1], color: [colors.0, colors.1, colors.2, colors.3] } ) ); } } } pub fn allocate_vertex_buffers(&mut self, device: Arc) { self.vertex_buffers.push( CpuAccessibleBuffer::from_iter( device.clone(), BufferUsage::vertex_buffer(), self.colored_drawables.iter().cloned() ).unwrap() ); } // The image set is the containing object for all texture and image hooks. fn get_texture_set(&mut self, device: Arc) -> Box { let sampler = Sampler::new(device.clone(), Filter::Linear, Filter::Linear, MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(); let o : Box = Box::new( PersistentDescriptorSet::start( self.shader_kernels.get(0).unwrap().clone().unwrap().get_pipeline(), 0 ) .add_sampled_image(self.textures.get(0).unwrap().clone(), sampler.clone()).unwrap() .build().unwrap()); o } // The image set is the containing object for all texture and image hooks. fn get_compute_swap_set(&mut self, device: Arc) -> Box { let sampler = Sampler::new(device.clone(), Filter::Linear, Filter::Linear, MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(); let o : Box = Box::new( PersistentDescriptorSet::start( self.shader_kernels.get(0).unwrap().clone().unwrap().get_pipeline(), 0 ) .add_image(self.compute_image.clone().unwrap().clone().get_swap_buffer().clone()).unwrap() .build().unwrap()); o } /* So I need the image set in order to get my texture or compute texture compute image currently holds the set for compute and its swap buffer vkprocessor creates the image sets for draw calls takes the pipeline from the ShaderKernel adds vk processor owned texture adds compute image taken from the ComputeImage we have shaderkernel in here so thats fine Who should own the texture? I would need to borrow it each time I created an image set... These are tied very closely to the input output of a shader, which we would own I just need to add a third option on sprite and allow it to have a swap buffer */ pub fn draw_commands(&mut self, command_buffer: AutoCommandBufferBuilder, framebuffers: Vec>, image_num: usize) -> AutoCommandBufferBuilder { // Specify the color to clear the framebuffer with i.e. blue let clear_values = vec!(ClearValue::Float([0.0, 0.0, 1.0, 1.0])); let dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None }; let mut command_buffer = command_buffer.begin_render_pass( framebuffers[image_num].clone(), false, clear_values.clone() ).unwrap(); // for i in self.shader_kernels { // command_buffer = command_buffer.draw( // i.clone().unwrap().get_pipeline(), // &dynamic_state.clone(), self.vertex_buffers, // vec![self.get_image_set()], () // ).unwrap(); // } // // .draw(self.shader_kernels.clone().unwrap().get_pipeline(), // &dynamic_state.clone(), self.vertex_buffers, // vec![self.get_gui_image_set()], ()) // .unwrap(); // command_buffer .end_render_pass() .unwrap() } }