You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.9 KiB
212 lines
7.9 KiB
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
|
use rusttype::{Font, PositionedGlyph, Scale, Rect, point};
|
|
use rusttype::gpu_cache::Cache;
|
|
use vulkano::buffer::{BufferAccess, BufferUsage, ImmutableBuffer, CpuAccessibleBuffer};
|
|
use vulkano::device::{Device, Queue};
|
|
use std::sync::Arc;
|
|
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
|
|
use vulkano::image::{ImmutableImage, ImageUsage, ImageLayout, Dimensions};
|
|
use vulkano::format::ClearValue;
|
|
use vulkano::format::Format::R8Unorm;
|
|
|
|
|
|
/*
|
|
|
|
So I think this thing is going to build text vertex buffers to send to the GPU.
|
|
I assume I will just lay them out in ASCII for now along with a list of
|
|
transformation matrices
|
|
|
|
Glpyh:
|
|
index: 0-255,
|
|
scale: 0.0 - 99.99
|
|
transform: (0.0, 0.0) - (1.0, 1.0)
|
|
|
|
I'm not sure if I want to send a new transformation matrix for each frame. But I suppose
|
|
that can come when I look at caching the sprites
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
pub struct Glyph {
|
|
|
|
}
|
|
|
|
/// Typed wrapper for a u32 shader handle (index id)
|
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
|
pub struct CanvasFontHandle {
|
|
pub handle: u32
|
|
}
|
|
|
|
/// So currently, I'm using these as container classes which vkprocessor owns
|
|
/// I then use a CanvasFrame which accumulates lists of handles and vertices.
|
|
pub struct CanvasText {
|
|
device: Arc<Device>,
|
|
queue: Arc<Queue>,
|
|
font: Font<'static>,
|
|
}
|
|
|
|
impl CanvasText {
|
|
|
|
/// Load the font
|
|
pub fn new(device: Arc<Device>, queue: Arc<Queue>) -> CanvasText {
|
|
|
|
let font_data = include_bytes!("../../resources/fonts/sansation.ttf");
|
|
let font = Font::from_bytes(font_data as &[u8]).unwrap();
|
|
|
|
CanvasText {
|
|
device: device.clone(),
|
|
queue: queue.clone(),
|
|
font: font,
|
|
}
|
|
}
|
|
|
|
/// Generate a vertex buffer from the font
|
|
/*
|
|
So... These fonts are going to have unequal amounts of vertices.
|
|
|
|
*/
|
|
pub fn get_vertex_buffer(&self) {
|
|
unimplemented!()
|
|
}
|
|
|
|
/// postpone this until caching
|
|
pub fn queue_text(&mut self,
|
|
x: f32, y: f32,
|
|
size: f32, color: [f32; 4],
|
|
text: &str) {
|
|
let glyphs: Vec<PositionedGlyph> = self.font.layout(text, Scale::uniform(size), point(x, y)).map(|x| x.standalone()).collect();
|
|
for glyph in &glyphs {
|
|
self.cache.queue_glyph(0, glyph.clone());
|
|
}
|
|
// self.texts.push(TextData {
|
|
// glyphs: glyphs.clone(),
|
|
// color: color,
|
|
// });
|
|
}
|
|
|
|
pub fn draw_text(&mut self,
|
|
command_buffer: AutoCommandBufferBuilder,
|
|
image_num: usize
|
|
) -> AutoCommandBufferBuilder {
|
|
|
|
// let screen_width = 0;
|
|
// let screen_height = 0;
|
|
//
|
|
// let cache_pixel_buffer = &mut self.cache_pixel_buffer;
|
|
// let cache = &mut self.cache;
|
|
//
|
|
// // update texture cache
|
|
// cache.cache_queued(
|
|
// |rect, src_data| {
|
|
// let width = (rect.max.x - rect.min.x) as usize;
|
|
// let height = (rect.max.y - rect.min.y) as usize;
|
|
// let mut dst_index = rect.min.y as usize * CACHE_WIDTH + rect.min.x as usize;
|
|
// let mut src_index = 0;
|
|
//
|
|
// for _ in 0..height {
|
|
// let dst_slice = &mut cache_pixel_buffer[dst_index..dst_index+width];
|
|
// let src_slice = &src_data[src_index..src_index+width];
|
|
// dst_slice.copy_from_slice(src_slice);
|
|
//
|
|
// dst_index += CACHE_WIDTH;
|
|
// src_index += width;
|
|
// }
|
|
// }
|
|
// ).unwrap();
|
|
//
|
|
// // need to get a hold of the cache buffer handle after I create it
|
|
// // will then get swapped into this texture buffer
|
|
// // Hmmm so this uninit call returns the texture and then a handle for whatever fills it up
|
|
// let (cache_texture, cache_texture_write) = ImmutableImage::uninitialized(
|
|
// self.device.clone(),
|
|
// Dimensions::Dim2d { width: CACHE_WIDTH as u32, height: CACHE_HEIGHT as u32 },
|
|
// R8Unorm,
|
|
// 1,
|
|
// ImageUsage {
|
|
// sampled: true,
|
|
// transfer_destination: true,
|
|
// .. ImageUsage::none()
|
|
// },
|
|
// ImageLayout::General,
|
|
// Some(self.queue.family())
|
|
// ).unwrap();
|
|
//
|
|
//
|
|
//
|
|
// let set = Arc::new(
|
|
// PersistentDescriptorSet::start(self.pipeline.clone(), 0)
|
|
// .add_sampled_image(cache_texture.clone(), sampler).unwrap()
|
|
// .build().unwrap()
|
|
// );
|
|
//
|
|
// let mut command_buffer = command_buffer
|
|
// .copy_buffer_to_image(
|
|
// buffer.clone(),
|
|
// cache_texture_write,
|
|
// ).unwrap()
|
|
// .begin_render_pass(self.framebuffers[image_num].clone(), false, vec!(ClearValue::None)).unwrap();
|
|
//
|
|
// // draw
|
|
// for text in &mut self.texts.drain(..) {
|
|
// let vertices: Vec<Vertex2D> = text.glyphs.iter().flat_map(|g| {
|
|
// if let Ok(Some((uv_rect, screen_rect))) = cache.rect_for(0, g) {
|
|
// let gl_rect = Rect {
|
|
// min: point(
|
|
// (screen_rect.min.x as f32 / screen_width as f32 - 0.5) * 2.0,
|
|
// (screen_rect.min.y as f32 / screen_height as f32 - 0.5) * 2.0
|
|
// ),
|
|
// max: point(
|
|
// (screen_rect.max.x as f32 / screen_width as f32 - 0.5) * 2.0,
|
|
// (screen_rect.max.y as f32 / screen_height as f32 - 0.5) * 2.0
|
|
// )
|
|
// };
|
|
// vec!(
|
|
//// Vertex {
|
|
//// position: [gl_rect.min.x, gl_rect.max.y],
|
|
//// tex_position: [uv_rect.min.x, uv_rect.max.y],
|
|
//// color: text.color,
|
|
//// },
|
|
//// Vertex {
|
|
//// position: [gl_rect.min.x, gl_rect.min.y],
|
|
//// tex_position: [uv_rect.min.x, uv_rect.min.y],
|
|
//// color: text.color,
|
|
//// },
|
|
//// Vertex {
|
|
//// position: [gl_rect.max.x, gl_rect.min.y],
|
|
//// tex_position: [uv_rect.max.x, uv_rect.min.y],
|
|
//// color: text.color,
|
|
//// },
|
|
////
|
|
//// Vertex {
|
|
//// position: [gl_rect.max.x, gl_rect.min.y],
|
|
//// tex_position: [uv_rect.max.x, uv_rect.min.y],
|
|
//// color: text.color,
|
|
//// },
|
|
//// Vertex {
|
|
//// position: [gl_rect.max.x, gl_rect.max.y],
|
|
//// tex_position: [uv_rect.max.x, uv_rect.max.y],
|
|
//// color: text.color,
|
|
//// },
|
|
//// Vertex {
|
|
//// position: [gl_rect.min.x, gl_rect.max.y],
|
|
//// tex_position: [uv_rect.min.x, uv_rect.max.y],
|
|
//// color: text.color,
|
|
//// },
|
|
// ).into_iter()
|
|
// }
|
|
// else {
|
|
// vec!().into_iter()
|
|
// }
|
|
// }).collect();
|
|
//
|
|
// let vertex_buffer = CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::all(), vertices.into_iter()).unwrap();
|
|
// command_buffer = command_buffer.draw(self.pipeline.clone(), &DynamicState::none(), vertex_buffer.clone(), set.clone(), ()).unwrap();
|
|
// }
|
|
|
|
command_buffer//.end_render_pass().unwrap()
|
|
}
|
|
|
|
} |