From 9b6a81ae93bc994ae6ab3e5d15c1b164599ac23a Mon Sep 17 00:00:00 2001 From: Asuro Date: Fri, 27 Nov 2020 02:24:50 +0100 Subject: [PATCH] mip maps (but broken because of vulkano) --- src/main.rs | 4 +-- src/vulkan.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index 598d3d2..34015b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,7 +78,7 @@ impl Game for TestGame { // Custom game object stuff let light_pos = self.player.camera.position * -1.0; - self.player.update(frame_time, input, renderer); + self.player.update(frame_time, &self.input, renderer); // End frame self.last_time = time; @@ -112,7 +112,7 @@ impl TestGame { let plane = self.add_from_gltf(renderer, "models/plane.glb"); plane.get_game_object(renderer).unwrap().position = vec3(0.0, -1.0, 0.0); - + println!("Game loaded!"); } diff --git a/src/vulkan.rs b/src/vulkan.rs index 6bd5f98..8176199 100644 --- a/src/vulkan.rs +++ b/src/vulkan.rs @@ -4,7 +4,7 @@ use std::time::SystemTime; use cgmath::{Matrix4, SquareMatrix}; use image::{ImageBuffer, ImageFormat, Rgb, Rgba}; use image::buffer::ConvertBuffer; -use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer}; +use vulkano::{command_buffer::CommandBuffer, buffer::{BufferUsage, CpuAccessibleBuffer}, image::{ImageLayout, MipmapsCount}}; use vulkano::command_buffer::{AutoCommandBuffer, AutoCommandBufferBuilder, DynamicState}; use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; use vulkano::descriptor::DescriptorSet; @@ -279,7 +279,7 @@ impl VulkanRenderer { let default_tex = { let image = image::load_from_memory_with_format(include_bytes!("../models/missing-texture.jpg"), - ImageFormat::Jpeg).unwrap().to_rgba(); + ImageFormat::Jpeg).unwrap().to_rgba8(); let image_data = image.into_raw().clone(); let (image_view, future) = ImmutableImage::from_iter( @@ -482,17 +482,72 @@ impl VulkanRenderer { } pub fn upload_texture(self: &mut Self, texture_data: &gltf::image::Data) { + // Format buffer on cpu for upload let buffer: ImageBuffer, Vec> = image::ImageBuffer::from_raw(texture_data.width, texture_data.height, texture_data.pixels.clone()).unwrap(); let new_buffer: ImageBuffer, Vec> = buffer.convert(); + let dimensions = Dimensions::Dim2d { width: texture_data.width, height: texture_data.height }; - let (image_view, future) = ImmutableImage::from_iter( + let source = CpuAccessibleBuffer::from_iter( + self.device.clone(), + BufferUsage::transfer_source(), + false, new_buffer.iter().cloned(), - Dimensions::Dim2d { width: texture_data.width, height: texture_data.height }, - Format::R8G8B8A8Unorm, - self.queue.clone(), ).unwrap(); - future.flush().unwrap(); + // Create image + let (image_view, init) = ImmutableImage::uninitialized( + self.device.clone(), + dimensions, + Format::R8G8B8A8Unorm, + MipmapsCount::Log2, + ImageUsage { + transfer_source: true, + transfer_destination: true, + sampled: true, + ..ImageUsage::none() + }, + ImageLayout::ShaderReadOnlyOptimal, + self.device.active_queue_families() + ).unwrap(); + + // Upload image data + let mut command_buffer_builder = AutoCommandBufferBuilder::new(self.device.clone(), self.queue.family()).unwrap(); + command_buffer_builder.copy_buffer_to_image_dimensions( + source, + init, + [0, 0, 0], + dimensions.width_height_depth(), + 0, + dimensions.array_layers_with_cube(), + 0, + ).unwrap(); + + // Generate mipmaps + let mut mip_width = image_view.dimensions().width() as i32; + let mut mip_height = image_view.dimensions().height() as i32; + + for i in 0..image_view.mipmap_levels() { + command_buffer_builder.blit_image( + image_view.clone(), + [0; 3], + [mip_width, mip_height, 1], + 0, + i, + image_view.clone(), + [0; 3], + [mip_width / 2, mip_height / 2, 1], + 0, + i + 1, + dimensions.array_layers_with_cube(), + Filter::Linear).unwrap(); + + if mip_width > 1 { mip_width = mip_width / 2; } + if mip_height > 1 { mip_height = mip_height / 2; } + } + + let command_buffer = command_buffer_builder.build().unwrap(); + let command_buffer_future = command_buffer.execute(self.queue.clone()).unwrap(); + command_buffer_future.flush().unwrap(); self.game_data.textures.push(image_view); }