+use std::fmt::Write;
use std::path::Path;
use std::time::{Duration, Instant};
use narcissus_maths::{
clamp, perlin_noise3, sin_pi_f32, vec3, Affine3, Deg, HalfTurn, Mat3, Mat4, Point3, Vec3,
};
-use pipelines::{BasicPipeline, BasicUniforms, PrimitiveInstance, PrimitiveVertex, TextPipeline};
+use pipelines::{BasicPipeline, BasicUniforms, PrimitiveInstance, PrimitiveVertex, UiPipeline};
use spring::simple_spring_damper_exact;
mod fonts;
scale: f32,
fonts: &'a Fonts<'a>,
glyph_cache: GlyphCache<'a, Fonts<'a>>,
+
+ tmp_string: String,
+
primitive_instances: Vec<PrimitiveInstance>,
primitive_vertices: Vec<PrimitiveVertex>,
}
scale,
fonts,
glyph_cache,
+ tmp_string: default(),
primitive_instances: vec![],
primitive_vertices: vec![],
}
}
- fn text(&mut self, mut x: f32, y: f32, font_family: FontFamily, font_size_px: f32, text: &str) {
+ fn text_fmt(
+ &mut self,
+ mut x: f32,
+ y: f32,
+ font_family: FontFamily,
+ font_size_px: f32,
+ args: std::fmt::Arguments,
+ ) {
let font = self.fonts.font(font_family);
let font_size_px = font_size_px * self.scale;
let scale = font.scale_for_size_px(font_size_px);
let mut prev_index = None;
- for c in text.chars() {
+ self.tmp_string.clear();
+ self.tmp_string.write_fmt(args).unwrap();
+
+ for c in self.tmp_string.chars() {
let glyph_index = font
.glyph_index(c)
.unwrap_or_else(|| font.glyph_index('□').unwrap());
gpu: &'device Gpu,
basic_pipeline: BasicPipeline,
- text_pipeline: TextPipeline,
+ ui_pipeline: UiPipeline,
width: u32,
height: u32,
impl<'device> DrawState<'device> {
fn new(gpu: &'device Gpu, thread_token: &ThreadToken) -> Self {
let basic_pipeline = BasicPipeline::new(gpu);
- let text_pipeline = TextPipeline::new(gpu);
+ let ui_pipeline = UiPipeline::new(gpu);
let models = load_models(gpu);
let images = load_images(gpu, thread_token);
Self {
gpu,
basic_pipeline,
- text_pipeline,
+ ui_pipeline,
width: 0,
height: 0,
depth_image: default(),
// We're done with you now!
self.transforms.clear();
+ }
- // Render text stuff.
- self.text_pipeline.bind(
- gpu,
+ // Render UI stuff.
+ {
+ let ui_uniforms = &pipelines::UiUniforms {
+ screen_width: width,
+ screen_height: height,
+ atlas_width,
+ atlas_height,
+ };
+ let primitive_vertices = ui_state.primitive_vertices.as_slice();
+ let primitive_instances = ui_state.primitive_instances.as_slice();
+ let uniforms_buffer = gpu.request_transient_buffer_with_data(
frame,
thread_token,
- cmd_encoder,
- &pipelines::TextUniforms {
- screen_width: width,
- screen_height: height,
- atlas_width,
- atlas_height,
- },
- ui_state.primitive_vertices.as_slice(),
+ BufferUsageFlags::UNIFORM,
+ ui_uniforms,
+ );
+ let primitive_vertex_buffer = gpu.request_transient_buffer_with_data(
+ frame,
+ thread_token,
+ BufferUsageFlags::STORAGE,
+ primitive_vertices,
+ );
+ let cached_glyphs_buffer = gpu.request_transient_buffer_with_data(
+ frame,
+ thread_token,
+ BufferUsageFlags::STORAGE,
touched_glyphs,
- ui_state.primitive_instances.as_slice(),
- self.glyph_atlas_image,
+ );
+ let glyph_instance_buffer = gpu.request_transient_buffer_with_data(
+ frame,
+ thread_token,
+ BufferUsageFlags::STORAGE,
+ primitive_instances,
);
+ {
+ gpu.cmd_set_pipeline(cmd_encoder, self.ui_pipeline.pipeline);
+ gpu.cmd_set_bind_group(
+ frame,
+ cmd_encoder,
+ self.ui_pipeline.bind_group_layout,
+ 0,
+ &[
+ Bind {
+ binding: 0,
+ array_element: 0,
+ typed: TypedBind::UniformBuffer(&[uniforms_buffer.to_arg()]),
+ },
+ Bind {
+ binding: 1,
+ array_element: 0,
+ typed: TypedBind::StorageBuffer(
+ &[primitive_vertex_buffer.to_arg()],
+ ),
+ },
+ Bind {
+ binding: 2,
+ array_element: 0,
+ typed: TypedBind::StorageBuffer(&[cached_glyphs_buffer.to_arg()]),
+ },
+ Bind {
+ binding: 3,
+ array_element: 0,
+ typed: TypedBind::StorageBuffer(&[glyph_instance_buffer.to_arg()]),
+ },
+ Bind {
+ binding: 4,
+ array_element: 0,
+ typed: TypedBind::Sampler(&[self.ui_pipeline.sampler]),
+ },
+ Bind {
+ binding: 5,
+ array_element: 0,
+ typed: TypedBind::Image(&[(
+ ImageLayout::Optimal,
+ self.glyph_atlas_image,
+ )]),
+ },
+ ],
+ );
+ };
+
gpu.cmd_draw(
cmd_encoder,
ui_state.primitive_vertices.len() as u32,
ui_state.primitive_instances.clear();
ui_state.primitive_vertices.clear();
- };
+ }
gpu.cmd_end_rendering(cmd_encoder);
}
let tick_duration = Instant::now() - tick_start;
- ui_state.text(
+ ui_state.text_fmt(
5.0,
30.0,
FontFamily::RobotoRegular,
22.0,
- format!("tick: {:?}", tick_duration).as_str(),
+ format_args!("tick: {:?}", tick_duration),
);
- ui_state.text(5.0, 60.0, FontFamily::NotoSansJapanese, 22.0, "お握り");
+ ui_state.text_fmt(
+ 5.0,
+ 60.0,
+ FontFamily::NotoSansJapanese,
+ 18.0,
+ format_args!("お握り The Quick Brown Fox Jumped Over The Lazy Dog"),
+ );
draw_state.draw(
thread_token,
use narcissus_core::default;
-use narcissus_font::{TouchedGlyph, TouchedGlyphIndex};
+use narcissus_font::TouchedGlyphIndex;
use narcissus_gpu::{
- Bind, BindGroupLayout, BindGroupLayoutDesc, BindGroupLayoutEntryDesc, BindingType, BlendMode,
- BufferUsageFlags, CmdEncoder, CompareOp, CullingMode, DeviceExt, Frame, FrontFace,
- GraphicsPipelineDesc, GraphicsPipelineLayout, Image, ImageFormat, ImageLayout, Pipeline,
- PolygonMode, Sampler, SamplerAddressMode, SamplerDesc, SamplerFilter, ShaderDesc,
- ShaderStageFlags, ThreadToken, Topology, TypedBind,
+ BindGroupLayout, BindGroupLayoutDesc, BindGroupLayoutEntryDesc, BindingType, BlendMode,
+ CompareOp, CullingMode, FrontFace, GraphicsPipelineDesc, GraphicsPipelineLayout, ImageFormat,
+ Pipeline, PolygonMode, Sampler, SamplerAddressMode, SamplerDesc, SamplerFilter, ShaderDesc,
+ ShaderStageFlags, Topology,
};
use crate::Gpu;
#[allow(unused)]
#[repr(C)]
-pub struct TextUniforms {
+pub struct UiUniforms {
pub screen_width: u32,
pub screen_height: u32,
pub atlas_width: u32,
pub color: u32,
}
-pub struct TextPipeline {
- bind_group_layout: BindGroupLayout,
- sampler: Sampler,
- pipeline: Pipeline,
+pub struct UiPipeline {
+ pub bind_group_layout: BindGroupLayout,
+ pub sampler: Sampler,
+ pub pipeline: Pipeline,
}
-impl TextPipeline {
+impl UiPipeline {
pub fn new(gpu: &Gpu) -> Self {
let bind_group_layout = gpu.create_bind_group_layout(&BindGroupLayoutDesc {
entries: &[
let pipeline = gpu.create_graphics_pipeline(&GraphicsPipelineDesc {
vertex_shader: ShaderDesc {
entry: c"main",
- code: shark_shaders::TEXT_VERT_SPV,
+ code: shark_shaders::UI_VERT_SPV,
},
fragment_shader: ShaderDesc {
entry: c"main",
- code: shark_shaders::TEXT_FRAG_SPV,
+ code: shark_shaders::UI_FRAG_SPV,
},
bind_group_layouts: &[bind_group_layout],
layout: GraphicsPipelineLayout {
pipeline,
}
}
-
- pub fn bind(
- &self,
- gpu: &Gpu,
- frame: &Frame,
- thread_token: &ThreadToken,
- cmd_encoder: &mut CmdEncoder,
- text_uniforms: &TextUniforms,
- primitive_vertices: &[PrimitiveVertex],
- touched_glyphs: &[TouchedGlyph],
- primitive_instances: &[PrimitiveInstance],
- glyph_atlas_image: Image,
- ) {
- let uniforms_buffer = gpu.request_transient_buffer_with_data(
- frame,
- thread_token,
- BufferUsageFlags::UNIFORM,
- text_uniforms,
- );
- let primitive_vertex_buffer = gpu.request_transient_buffer_with_data(
- frame,
- thread_token,
- BufferUsageFlags::STORAGE,
- primitive_vertices,
- );
- let cached_glyphs_buffer = gpu.request_transient_buffer_with_data(
- frame,
- thread_token,
- BufferUsageFlags::STORAGE,
- touched_glyphs,
- );
- let glyph_instance_buffer = gpu.request_transient_buffer_with_data(
- frame,
- thread_token,
- BufferUsageFlags::STORAGE,
- primitive_instances,
- );
-
- gpu.cmd_set_pipeline(cmd_encoder, self.pipeline);
- gpu.cmd_set_bind_group(
- frame,
- cmd_encoder,
- self.bind_group_layout,
- 0,
- &[
- Bind {
- binding: 0,
- array_element: 0,
- typed: TypedBind::UniformBuffer(&[uniforms_buffer.to_arg()]),
- },
- Bind {
- binding: 1,
- array_element: 0,
- typed: TypedBind::StorageBuffer(&[primitive_vertex_buffer.to_arg()]),
- },
- Bind {
- binding: 2,
- array_element: 0,
- typed: TypedBind::StorageBuffer(&[cached_glyphs_buffer.to_arg()]),
- },
- Bind {
- binding: 3,
- array_element: 0,
- typed: TypedBind::StorageBuffer(&[glyph_instance_buffer.to_arg()]),
- },
- Bind {
- binding: 4,
- array_element: 0,
- typed: TypedBind::Sampler(&[self.sampler]),
- },
- Bind {
- binding: 5,
- array_element: 0,
- typed: TypedBind::Image(&[(ImageLayout::Optimal, glyph_atlas_image)]),
- },
- ],
- );
- }
}