mirror of
https://github.com/lisk77/comet.git
synced 2025-10-23 21:38:50 +00:00
feat: added Font to get glyphs out of ttf files and make a TextureAtlas with them (right now only latin range of Unicode to not explode the atlas) and started trying to incorporate text rendering in ECS and Renderer2D
This commit is contained in:
parent
5430ee0d7e
commit
9e16179df3
12 changed files with 191 additions and 317 deletions
|
|
@ -11,7 +11,7 @@ use comet_colors::LinearRgba;
|
|||
use comet_ecs::{Camera, Camera2D, Component, Position2D, Render, Render2D, Transform2D, Scene};
|
||||
use comet_log::{debug, info};
|
||||
use comet_math::{Point3, Vec2, Vec3};
|
||||
use comet_resources::{texture, graphic_resource_manager::GraphicResorceManager, Texture, Vertex};
|
||||
use comet_resources::{texture, graphic_resource_manager::GraphicResourceManager, Texture, Vertex};
|
||||
use comet_resources::texture_atlas::TextureRegion;
|
||||
use comet_structs::ComponentSet;
|
||||
use crate::camera::{RenderCamera, CameraUniform};
|
||||
|
|
@ -37,7 +37,7 @@ pub struct Renderer2D<'a> {
|
|||
clear_color: Color,
|
||||
diffuse_texture: Texture,
|
||||
diffuse_bind_group: wgpu::BindGroup,
|
||||
graphic_resource_manager: GraphicResorceManager,
|
||||
graphic_resource_manager: GraphicResourceManager,
|
||||
camera: RenderCamera,
|
||||
camera_uniform: CameraUniform,
|
||||
camera_buffer: wgpu::Buffer,
|
||||
|
|
@ -117,7 +117,7 @@ impl<'a> Renderer2D<'a> {
|
|||
|
||||
let num_indices = index_data.len() as u32;
|
||||
|
||||
let graphic_resource_manager = GraphicResorceManager::new();
|
||||
let graphic_resource_manager = GraphicResourceManager::new();
|
||||
|
||||
let diffuse_bytes = include_bytes!(r"../../../resources/textures/comet_icon.png");
|
||||
let diffuse_texture =
|
||||
|
|
@ -540,6 +540,10 @@ impl<'a> Renderer2D<'a> {
|
|||
info!("Applied base shader!");
|
||||
}
|
||||
|
||||
pub fn load_font(&mut self, path: &str, size: f32) {
|
||||
self.graphic_resource_manager.load_font(path, size);
|
||||
}
|
||||
|
||||
/// An interface for getting the location of the texture in the texture atlas.
|
||||
pub fn get_texture_region(&self, texture_path: String) -> &TextureRegion {
|
||||
assert!(self.graphic_resource_manager.texture_atlas().textures().contains_key(&texture_path), "Texture not found in atlas");
|
||||
|
|
@ -741,7 +745,34 @@ impl<'a> Renderer2D<'a> {
|
|||
|
||||
/// A function to draw text at a given position.
|
||||
pub fn draw_text_at(&mut self, text: &str, position: Point3) {
|
||||
todo!()
|
||||
let mut x = position.x();
|
||||
let mut y = position.y();
|
||||
|
||||
for c in text.chars() {
|
||||
let region = self.get_texture_region(c.to_string());
|
||||
let (dim_x, dim_y) = region.dimensions();
|
||||
|
||||
let (bound_x, bound_y) =
|
||||
((dim_x as f32/ self.config.width as f32) * 0.5, (dim_y as f32/ self.config.height as f32) * 0.5);
|
||||
|
||||
let vertices: &mut Vec<Vertex> = &mut vec![
|
||||
Vertex :: new ( [-bound_x + x, bound_y + y, 0.0], [region.x0(), region.y0()], [0.0, 0.0, 0.0, 0.0] ),
|
||||
Vertex :: new ( [-bound_x + x, -bound_y + y, 0.0], [region.x0(), region.y1()], [0.0, 0.0, 0.0, 0.0] ),
|
||||
Vertex :: new ( [ bound_x + x, -bound_y + y, 0.0], [region.x1(), region.y1()], [0.0, 0.0, 0.0, 0.0] ) ,
|
||||
Vertex :: new ( [ bound_x + x, bound_y + y, 0.0], [region.x1(), region.y0()], [0.0, 0.0, 0.0, 0.0] )
|
||||
];
|
||||
|
||||
let buffer_size = self.vertex_data.len() as u16;
|
||||
|
||||
let indices: &mut Vec<u16> = &mut vec![
|
||||
0 + buffer_size, 1 + buffer_size, 3 + buffer_size,
|
||||
1 + buffer_size, 2 + buffer_size, 3 + buffer_size
|
||||
];
|
||||
|
||||
self.push_to_buffers(vertices, indices);
|
||||
|
||||
x += dim_x as f32;
|
||||
}
|
||||
}
|
||||
|
||||
fn find_priority_camera(&self, cameras: Vec<Camera2D>) -> usize {
|
||||
|
|
@ -779,7 +810,7 @@ impl<'a> Renderer2D<'a> {
|
|||
let camera_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Camera Buffer"),
|
||||
contents: bytemuck::cast_slice(&[camera_uniform]),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
|
||||
});
|
||||
|
||||
let camera_bind_group_layout =
|
||||
|
|
|
|||
|
|
@ -1,254 +0,0 @@
|
|||
use anyhow::*;
|
||||
use image::GenericImageView;
|
||||
|
||||
pub struct Texture {
|
||||
#[allow(unused)]
|
||||
pub texture: wgpu::Texture,
|
||||
pub view: wgpu::TextureView,
|
||||
pub sampler: wgpu::Sampler,
|
||||
pub size: wgpu::Extent3d,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
||||
|
||||
pub fn create_depth_texture(
|
||||
device: &wgpu::Device,
|
||||
config: &wgpu::SurfaceConfiguration,
|
||||
label: &str,
|
||||
) -> Self {
|
||||
let size = wgpu::Extent3d {
|
||||
width: config.width.max(1),
|
||||
height: config.height.max(1),
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let desc = wgpu::TextureDescriptor {
|
||||
label: Some(label),
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: Self::DEPTH_FORMAT,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
view_formats: &[Self::DEPTH_FORMAT],
|
||||
};
|
||||
let texture = device.create_texture(&desc);
|
||||
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
compare: Some(wgpu::CompareFunction::LessEqual),
|
||||
lod_min_clamp: 0.0,
|
||||
lod_max_clamp: 100.0,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
Self {
|
||||
texture,
|
||||
view,
|
||||
sampler,
|
||||
size, // NEW!
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn from_bytes(
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
bytes: &[u8],
|
||||
label: &str,
|
||||
is_normal_map: bool,
|
||||
) -> Result<Self> {
|
||||
let img = image::load_from_memory(bytes)?;
|
||||
Self::from_image(device, queue, &img, Some(label), is_normal_map)
|
||||
}
|
||||
|
||||
pub fn from_image(
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
img: &image::DynamicImage,
|
||||
label: Option<&str>,
|
||||
is_normal_map: bool,
|
||||
) -> Result<Self> {
|
||||
let dimensions = img.dimensions();
|
||||
let rgba = img.to_rgba8();
|
||||
|
||||
let format = if is_normal_map {
|
||||
wgpu::TextureFormat::Rgba8Unorm
|
||||
} else {
|
||||
wgpu::TextureFormat::Rgba8UnormSrgb
|
||||
};
|
||||
let usage = wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST;
|
||||
let size = wgpu::Extent3d {
|
||||
width: img.width(),
|
||||
height: img.height(),
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
let texture = Self::create_2d_texture(
|
||||
device,
|
||||
size.width,
|
||||
size.height,
|
||||
format,
|
||||
usage,
|
||||
wgpu::FilterMode::Linear,
|
||||
label,
|
||||
);
|
||||
|
||||
queue.write_texture(
|
||||
wgpu::ImageCopyTexture {
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
texture: &texture.texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
},
|
||||
&rgba,
|
||||
wgpu::ImageDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(4 * dimensions.0),
|
||||
rows_per_image: Some(dimensions.1),
|
||||
},
|
||||
size,
|
||||
);
|
||||
|
||||
Ok(texture)
|
||||
}
|
||||
|
||||
pub(crate) fn create_2d_texture(
|
||||
device: &wgpu::Device,
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: wgpu::TextureFormat,
|
||||
usage: wgpu::TextureUsages,
|
||||
mag_filter: wgpu::FilterMode,
|
||||
label: Option<&str>,
|
||||
) -> Self {
|
||||
let size = wgpu::Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
Self::create_texture(
|
||||
device,
|
||||
label,
|
||||
size,
|
||||
format,
|
||||
usage,
|
||||
wgpu::TextureDimension::D2,
|
||||
mag_filter,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_texture(
|
||||
device: &wgpu::Device,
|
||||
label: Option<&str>,
|
||||
size: wgpu::Extent3d,
|
||||
format: wgpu::TextureFormat,
|
||||
usage: wgpu::TextureUsages,
|
||||
dimension: wgpu::TextureDimension,
|
||||
mag_filter: wgpu::FilterMode,
|
||||
) -> Self {
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label,
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension,
|
||||
format,
|
||||
usage,
|
||||
view_formats: &[],
|
||||
});
|
||||
|
||||
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter,
|
||||
min_filter: wgpu::FilterMode::Nearest,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
Self {
|
||||
texture,
|
||||
view,
|
||||
sampler,
|
||||
size, // NEW!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CubeTexture {
|
||||
texture: wgpu::Texture,
|
||||
sampler: wgpu::Sampler,
|
||||
view: wgpu::TextureView,
|
||||
}
|
||||
|
||||
impl CubeTexture {
|
||||
pub fn create_2d(
|
||||
device: &wgpu::Device,
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: wgpu::TextureFormat,
|
||||
mip_level_count: u32,
|
||||
usage: wgpu::TextureUsages,
|
||||
mag_filter: wgpu::FilterMode,
|
||||
label: Option<&str>,
|
||||
) -> Self {
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label,
|
||||
size: wgpu::Extent3d {
|
||||
width,
|
||||
height,
|
||||
// A cube has 6 sides, so we need 6 layers
|
||||
depth_or_array_layers: 6,
|
||||
},
|
||||
mip_level_count,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format,
|
||||
usage,
|
||||
view_formats: &[],
|
||||
});
|
||||
|
||||
let view = texture.create_view(&wgpu::TextureViewDescriptor {
|
||||
label,
|
||||
dimension: Some(wgpu::TextureViewDimension::Cube),
|
||||
array_layer_count: Some(6),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
label,
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter,
|
||||
min_filter: wgpu::FilterMode::Nearest,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
Self {
|
||||
texture,
|
||||
sampler,
|
||||
view,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn texture(&self) -> &wgpu::Texture {
|
||||
&self.texture
|
||||
}
|
||||
|
||||
pub fn view(&self) -> &wgpu::TextureView {
|
||||
&self.view
|
||||
}
|
||||
|
||||
pub fn sampler(&self) -> &wgpu::Sampler {
|
||||
&self.sampler
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue