texture.rs
1 //! Texture test featuring my cat Rusty. 2 //! 3 //! Press space to bitshift random pixels to make an interesting effect. 4 5 use glam::vec2; 6 use gpu::{VulkanTypes, texture::TextureId}; 7 use image::ImageBuffer; 8 use let_engine::prelude::*; 9 10 static RES: UVec2 = uvec2(1122, 821); 11 12 fn main() { 13 // Log messages 14 simple_logger::SimpleLogger::new() 15 .with_level(log::LevelFilter::Debug) 16 .init() 17 .unwrap(); 18 19 // First you make a builder containing the description of the window. 20 21 let window_builder = WindowBuilder::new() 22 .inner_size(RES) 23 .title(env!("CARGO_CRATE_NAME")); 24 25 let_engine::start( 26 EngineSettings::default() 27 .window(window_builder) 28 .gpu(gpu::GpuSettings { 29 present_mode: gpu::PresentMode::Fifo, 30 ..Default::default() 31 }), 32 Game::new, 33 ) 34 .unwrap(); 35 } 36 37 /// Makes a game struct containing 38 struct Game { 39 texture: TextureId, 40 } 41 42 impl Game { 43 /// Constructor for this scene. 44 pub fn new(context: EngineContext) -> Result<Self, ()> { 45 context.scene.root_view_mut().scaling = CameraScaling::Expand; 46 47 // A square model with textured vertices. 48 let model = context 49 .gpu 50 .load_model(&Model::new_indexed( 51 vec![ 52 tvert(1.0, 1.0, 1.0, 1.0), 53 tvert(1.0, -1.0, 1.0, 0.0), 54 tvert(-1.0, 1.0, 0.0, 1.0), 55 tvert(-1.0, -1.0, 0.0, 0.0), 56 ], 57 vec![0, 1, 2, 2, 1, 3], 58 BufferAccess::Fixed, 59 )) 60 .unwrap(); 61 62 let texture = Texture::from_bytes( 63 include_bytes!("../assets/example-texture.png").to_vec(), 64 ImageFormat::Png, 65 TextureSettingsBuilder::default() 66 .format(Format::Rgba8Unorm) 67 .access_pattern(BufferAccess::RingBuffer { buffers: 2 }) // `BufferAccess::Pinned` to make the texture mutable for each frame 68 .unwrap() 69 .build() 70 .unwrap(), 71 ) 72 .unwrap(); 73 74 // Load the texture to the GPU 75 let gpu_texture = context.gpu.load_texture(&texture).unwrap(); 76 77 let default_material = context 78 .gpu 79 .load_material::<TVert>(&Material::default_textured()) 80 .unwrap(); 81 82 let color_buffer = context 83 .gpu 84 .load_buffer(&Buffer::from_data( 85 buffer::BufferUsage::Uniform, 86 BufferAccess::Fixed, 87 Color::WHITE, 88 )) 89 .unwrap(); 90 91 let dim = texture.dimensions().extent(); 92 93 let appearance = AppearanceBuilder::<VulkanTypes, TVert>::default() 94 .model(model) 95 .material(default_material) 96 .transform(Transform::with_size_2d(vec2(dim[0] as f32, dim[1] as f32))) 97 .descriptors(&[ 98 (Location::new(0, 0), Descriptor::Mvp), 99 (Location::new(1, 0), Descriptor::buffer(color_buffer)), 100 (Location::new(2, 0), Descriptor::Texture(gpu_texture)), 101 ]) 102 .build(&context.gpu) 103 .unwrap(); 104 105 let object = ObjectBuilder::with_appearance(appearance); 106 107 // Initializes the object to the layer 108 context 109 .scene 110 .add_object(context.scene.root_layer_id(), object) 111 .unwrap(); 112 113 Ok(Self { 114 texture: gpu_texture, 115 }) 116 } 117 } 118 119 /// Implement the Game trait into the Game struct. 120 impl let_engine::Game for Game { 121 // Exit when the X button on the window is pressed. 122 fn window(&mut self, context: EngineContext, event: events::WindowEvent) -> Result<(), ()> { 123 if let WindowEvent::CloseRequested = event { 124 context.exit(); 125 } 126 Ok(()) 127 } 128 129 fn input(&mut self, context: EngineContext, event: events::InputEvent) -> Result<(), ()> { 130 if let InputEvent::KeyboardInput { input } = event 131 && let ElementState::Pressed = input.state 132 { 133 match input.key { 134 // Exit when the escape key is pressed. 135 Key::Named(NamedKey::Escape) => { 136 context.exit(); 137 } 138 // Edit texture when space is pressed. 139 Key::Named(NamedKey::Space) => { 140 // Write data to the texture 141 context.gpu[self.texture] 142 .write_data(|data| { 143 let mut buffer: ImageBuffer<image::Rgba<u8>, &mut [u8]> = 144 ImageBuffer::from_raw(RES.x, RES.y, data).unwrap(); 145 146 const PIXELS: usize = 100000; 147 148 log::info!("Shifting {PIXELS} pixels"); 149 for _ in 0..PIXELS { 150 let c = uvec2( 151 rand::random_range(0..RES.x), 152 rand::random_range(0..RES.y), 153 ); 154 155 let pixel = buffer.get_pixel_mut(c.x, c.y); 156 pixel.0[0..2].iter_mut().for_each(|rgb: &mut u8| { 157 *rgb = rgb.rotate_left(1); 158 }); 159 } 160 }) 161 .unwrap(); 162 } 163 _ => (), 164 } 165 } 166 Ok(()) 167 } 168 }