diff --git a/Cargo.toml b/Cargo.toml index 409ed65..690cfb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ serde_derive = "1.0.114" toml = "0.5.6" gilrs = "0.7.4" gltf = "0.15.2" +glyph_brush = "0.7" [[bin]] name = "converter" diff --git a/config/log.toml b/config/log.toml index ff52a44..e28c9f3 100644 --- a/config/log.toml +++ b/config/log.toml @@ -1,5 +1,5 @@ -vulkan_validation_layers = false -mesh_load_info = false +vulkan_validation_layers = true +mesh_load_info = true [input] mouse_motion = false diff --git a/models/OverpassRegular.ttf b/models/OverpassRegular.ttf new file mode 100644 index 0000000..43169d2 Binary files /dev/null and b/models/OverpassRegular.ttf differ diff --git a/src/game/level.rs b/src/game/level.rs index 1223bd7..f0a8644 100644 --- a/src/game/level.rs +++ b/src/game/level.rs @@ -54,9 +54,9 @@ pub fn load_level(path: &str, game: &mut TestGame, renderer: &mut VulkanRenderer } pub fn save_level(path: &str, game: &mut TestGame, renderer: &mut VulkanRenderer) -> Result<(), Box> { - let meshes = renderer.game_data.meshes.iter().map(|mesh| { + let meshes = renderer.game_data.meshes.iter().filter(|m| m.original_path.is_some()).map(|mesh| { MeshJson { - path: mesh.original_path.to_string() + path: mesh.original_path.clone().unwrap() } }).collect(); diff --git a/src/game/mod.rs b/src/game/mod.rs index ba1719d..5b9f868 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,7 +1,8 @@ - use std::time::SystemTime; - use cgmath::{Deg, Euler, Quaternion, vec3}; +use glyph_brush::{BrushAction, BrushError, GlyphBrushBuilder, Section, Text}; +use glyph_brush::ab_glyph::FontArc; +use vulkano::format::Format; use winit::event::Event; use level::{load_level, save_level}; @@ -9,9 +10,9 @@ use player::Player; use crate::{config::LogConfig, vulkan}; use crate::input::InputState; -use crate::vulkan::{Game, MeshHandle, VulkanRenderer}; +use crate::vulkan::{Game, MeshHandle, TextureHandle, Vertex, VulkanRenderer}; use crate::vulkan::gameobject::{GameObject, GameObjectHandle, Updatable}; -use crate::vulkan::mesh; +use crate::vulkan::mesh::{self, CPUMesh}; use crate::vulkan::pipelines::vs::ty::ObjectUniformData; pub mod player; @@ -79,7 +80,6 @@ impl Game for TestGame { if !self.paused { self.player.update(frame_time, &self.input, renderer); } - // self.game_objects[1].get_game_object_mut(renderer).unwrap().rotation = Quaternion::from_angle_y(Deg(time * -20.)).normalize(); // End frame self.last_time = time; @@ -116,6 +116,55 @@ impl TestGame { pub fn game_start(self: &mut Self, renderer: &mut VulkanRenderer) { load_level("levels/test.lvl", self, renderer).unwrap(); println!("Game loaded!"); + + let font = FontArc::try_from_slice(include_bytes!("../../models/OverpassRegular.ttf")).unwrap(); + let mut glyph_brush = GlyphBrushBuilder::using_font(font).build(); + glyph_brush.queue(Section::default().add_text(Text::new("rRRRRRRRRRRRRRr"))); + match glyph_brush.process_queued(|rect, text_data| { + renderer.upload_texture(text_data, rect.width(), rect.height(), Format::R8Srgb, renderer.device.clone()); + self.texture_index_counter += 1; + }, |vertex_data| { + vec![ + Vertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.min.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.min.y], normal: [0., 0., 1.], ..Default::default() }, + Vertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.max.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.max.y], normal: [0., 0., 1.], ..Default::default() }, + ] + }) { + Ok(BrushAction::Draw(quads)) => { + let mut final_vertices = vec![]; + let mut final_indices = vec![]; + let mut height = 0.2; + let mut index_offset = 2; + final_vertices.push(Vertex { position: [0., 0., 0.], uv: [0., 0.], normal: [0., 0., 1.], ..Default::default() }); + final_vertices.push(Vertex { position: [0., height, 0.], uv: [0., 1.], normal: [0., 0., 1.], ..Default::default() }); + for quad in quads { + final_vertices.append(&mut quad.clone()); + final_indices.append(&mut [0, 2, 3, 0, 3, 1].iter().map(|x| *x + index_offset - 2).collect()); + index_offset += quad.len() as u32; + } + println!("v: {:?}", final_vertices); + println!("i: {:?}", final_indices); + let mesh = CPUMesh { + vertices: final_vertices, + indices: final_indices, + local_texture_index: Some(self.texture_index_counter - 1), + local_normal_map_index: None, + name: Some("font_texture".to_string()), + }; + let mesh_index = renderer.upload_mesh(mesh, None); + let mesh_handle = MeshHandle { + index: mesh_index, + diffuse_handle: self.texture_index_counter - 1, + normal_handle: None, + original_path: None, + }; + let mut game_object_handle = self.add_game_object(renderer, mesh_handle); + game_object_handle.get_game_object_mut(renderer).unwrap().scale = vec3(10., 10., 10.); + self.game_objects.push(game_object_handle); + }, + Ok(BrushAction::ReDraw) => {}, + Err(BrushError::TextureTooSmall { suggested: _ }) => { println!("texture too small!"); }, + } + } pub fn offset_texture_id(&mut self, local_tex_id: Option) -> usize { @@ -137,12 +186,12 @@ impl TestGame { let normal_id = self.offset_texture_id(cpu_mesh.local_normal_map_index); // Upload mesh - let mesh_id = renderer.upload_mesh(cpu_mesh, gltf_path.to_string()); + let mesh_id = renderer.upload_mesh(cpu_mesh, Some(gltf_path.to_string())); let mesh_handle = MeshHandle { index: mesh_id, diffuse_handle: diffuse_id, - normal_handle: normal_id, - original_path: gltf_path.to_string() + normal_handle: Some(normal_id), + original_path: Some(gltf_path.to_string()) }; mesh_handles.push(mesh_handle); } diff --git a/src/game/player.rs b/src/game/player.rs index 217a3dd..87ea9e1 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -83,7 +83,7 @@ impl Camera { self.rotation.invert().rotate_vector(vec) } - pub fn world_to_local(&self, vec:Vector3) -> Vector3 { + pub fn _world_to_local(&self, vec:Vector3) -> Vector3 { self.rotation.rotate_vector(vec) } } @@ -185,7 +185,7 @@ impl Updatable for Player { let ray_direction = self.camera.viewport_pos_to_ray_direction(input.mouse_position, renderer.game_data.dimensions).unwrap(); for game_object in &mut renderer.game_data.game_objects { let mesh = &renderer.game_data.meshes[game_object.mesh_index]; - if let Some(dist) = intersection_distance(self.camera.position, ray_direction, mesh, game_object) { + if let Some(_) = intersection_distance(self.camera.position, ray_direction, mesh, game_object) { game_object.is_selected = !game_object.is_selected; } } diff --git a/src/vulkan/gameobject.rs b/src/vulkan/gameobject.rs index e90d061..77b21c0 100644 --- a/src/vulkan/gameobject.rs +++ b/src/vulkan/gameobject.rs @@ -23,7 +23,7 @@ pub struct GameObject { impl GameObject { pub fn new(mesh: MeshHandle) -> GameObject { - GameObject { mesh_index: mesh.index, texture_index: mesh.diffuse_handle, normal_map_index: mesh.normal_handle, position: Vector3::new(0.0, 0.0, 0.0), + GameObject { mesh_index: mesh.index, texture_index: mesh.diffuse_handle, normal_map_index: mesh.normal_handle.unwrap_or(0), position: Vector3::new(0.0, 0.0, 0.0), rotation: Quaternion::new(1.0, 0.0, 0.0, 0.0), scale: Vector3::new(1.0, 1.0, 1.0), children: vec![], descriptor_sets: vec![], is_selected: false } } diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs index d522e46..003d2ec 100644 --- a/src/vulkan/mod.rs +++ b/src/vulkan/mod.rs @@ -3,7 +3,7 @@ use std::time::SystemTime; use cgmath::{Matrix4, SquareMatrix}; use dds::get_block_size; -use vulkano::{buffer::{BufferUsage, CpuAccessibleBuffer}, command_buffer::{CommandBuffer, SubpassContents}, image::{ImageLayout, ImageUsage, MipmapsCount, immutable::SubImage}}; +use vulkano::{buffer::{BufferUsage, CpuAccessibleBuffer}, command_buffer::{CommandBuffer, SubpassContents}, image::{ImageAccess, ImageLayout, ImageUsage, MipmapsCount, immutable::SubImage}}; use vulkano::command_buffer::{AutoCommandBuffer, AutoCommandBufferBuilder, DynamicState}; use vulkano::descriptor::DescriptorSet; use vulkano::device::{Device, DeviceExtensions, Queue}; @@ -23,7 +23,7 @@ use winit::event_loop::{ControlFlow, EventLoop}; use winit::window::{Window, WindowBuilder}; use mesh::CPUMesh; -use pipelines::{Drawcall, LineShader}; +use pipelines::{Drawcall}; use pipelines::line_vs::ty::LinePushConstants; use pipelines::DefaultShader; use pipelines::vs; @@ -69,15 +69,15 @@ pub trait Game { pub struct Mesh { pub vertex_buffer: Arc>, pub index_buffer: Arc>, - pub original_path: String, + pub original_path: Option, } #[derive(Debug, Clone)] pub struct MeshHandle { pub index: usize, pub diffuse_handle: TextureHandle, - pub normal_handle: TextureHandle, - pub original_path: String + pub normal_handle: Option, + pub original_path: Option } pub(crate) type TextureHandle = usize; @@ -411,7 +411,7 @@ impl VulkanRenderer { }; } - pub fn upload_mesh(self: &mut Self, mesh: CPUMesh, original_path: String) -> usize { + pub fn upload_mesh(self: &mut Self, mesh: CPUMesh, original_path: Option) -> usize { // let mut collision_mesh = mgf::Mesh::new(); // mesh.vertices.iter().for_each(|v| { // collision_mesh.push_vert(v.position.into()); @@ -438,12 +438,13 @@ impl VulkanRenderer { }; let layout = ImageLayout::ShaderReadOnlyOptimal; + let mip_maps = if format == Format::R8Srgb { MipmapsCount::One } else { MipmapsCount::Log2 }; let (image_view, initializer) = ImmutableImage::uninitialized( device.clone(), dimensions, format, - MipmapsCount::Log2, + mip_maps, usage, layout, device.active_queue_families(), @@ -462,21 +463,14 @@ impl VulkanRenderer { let mut offset = 0; - let block_bytes = get_block_size(format).expect(&format!("Unknown texture format {:?}!", format)); - - for i in 0..image_view.mipmap_levels() { - let mip_size = dimensions.to_image_dimensions().mipmap_dimensions(i).unwrap().width_height_depth(); - - let mip_byte_size = ( - (u32::max(4, mip_size[0]) / 4) - * (u32::max(4, mip_size[1]) / 4) - * block_bytes) as usize; + let block_bytes = get_block_size(format); + let mut upload_bytes = |data: &[u8], mip_index: u32, mip_size: [u32; 3]| { let source = CpuAccessibleBuffer::from_iter( device.clone(), BufferUsage::transfer_source(), false, - bytes[offset..(offset + mip_byte_size)].iter().cloned(), + data.iter().cloned(), ).unwrap(); cbb.copy_buffer_to_image_dimensions( @@ -486,11 +480,26 @@ impl VulkanRenderer { mip_size, 0, dimensions.array_layers_with_cube(), - i, - ) - .unwrap(); + mip_index, + ).unwrap(); + }; - offset += mip_byte_size; + if let Some(block_byte_size) = block_bytes { + for i in 0..image_view.mipmap_levels() { + + let mip_size = dimensions.to_image_dimensions().mipmap_dimensions(i).unwrap().width_height_depth(); + + let mip_byte_size = ( + (u32::max(4, mip_size[0]) / 4) + * (u32::max(4, mip_size[1]) / 4) + * block_byte_size) as usize; + + let data = &bytes[offset..(offset + mip_byte_size)]; + upload_bytes(data, i, mip_size); + offset += mip_byte_size; + } + } else { + upload_bytes(bytes, 0, dimensions.to_image_dimensions().width_height_depth()); } let cb = cbb.build().unwrap(); diff --git a/src/vulkan/pipelines.rs b/src/vulkan/pipelines.rs index c9628ab..0271aeb 100644 --- a/src/vulkan/pipelines.rs +++ b/src/vulkan/pipelines.rs @@ -204,7 +204,7 @@ pub struct LineShader { } impl LineShader { - pub fn new(device: Arc, render_pass: RP, vertex_buffer: Arc>) -> Self { + pub fn _new(device: Arc, render_pass: RP, vertex_buffer: Arc>) -> Self { LineShader { pipeline: Self::create_pipeline(device, render_pass), vertex_buffer