diff options
| author | Tengu712 <genreihoutengu@gmail.com> | 2026-09-27 03:51:41 +0900 |
|---|---|---|
| committer | Tengu712 <genreihoutengu@gmail.com> | 2026-09-27 03:51:41 +0900 |
| commit | e3835c956011c217e498b272490005dca457d402 (patch) | |
| tree | 2285879dfc515dee2d6e3fddcf71f81b77d6829c /src/graphics.rs | |
| parent | f6d058be6639c8e052c5a38dea4f33d6b26ae20c (diff) | |
render font
Diffstat (limited to 'src/graphics.rs')
| -rw-r--r-- | src/graphics.rs | 61 |
1 files changed, 33 insertions, 28 deletions
diff --git a/src/graphics.rs b/src/graphics.rs index bbe07df..2b96a7a 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -2,9 +2,10 @@ use std::{borrow::Cow, sync::Arc}; use wgpu::*; use winit::{dpi::PhysicalSize, event_loop::OwnedDisplayHandle, window::Window}; +mod font; mod texture; -use texture::TextureWrapper; +use font::CharAtlas; pub enum AcquireSurfaceTextureResult { Ok(SurfaceTexture), @@ -21,7 +22,7 @@ pub struct Renderer { present_mode: PresentMode, pipeline: RenderPipeline, - font_tex: TextureWrapper, + char_atlas: CharAtlas, fixed_bind_group: BindGroup, } @@ -31,10 +32,10 @@ impl Renderer { window: Arc<Window>, ) -> Result<Self, String> { let size = window.inner_size(); + let scale_factor = window.scale_factor() as f32; let instance = Instance::new(InstanceDescriptor::new_with_display_handle(display)); let surface = instance.create_surface(window).map_err(|e| e.to_string())?; - let adapter = instance .request_adapter(&RequestAdapterOptions { compatible_surface: Some(&surface), @@ -53,20 +54,7 @@ impl Renderer { } let (surface_format, view_format) = decide_surface_and_view_format(&adapter, &surface_cap); - - // REVIEW: 高負荷なので素直にFIFOにして垂直同期で回す方が良いかもしれない。 - let present_mode = if surface_cap.present_modes.contains(&PresentMode::Mailbox) { - // 垂直同期を待つフレーム上書きモード - PresentMode::Mailbox - } else if surface_cap.present_modes.contains(&PresentMode::Immediate) { - // 垂直同期を待たないフレーム上書きモード - PresentMode::Immediate - } else { - // 垂直同期を待つフレーム保守モード - // NOTE: 殆どすべての環境でサポートされていることを期待して良い。 - // https://wgpu.rs/doc/wgpu/enum.PresentMode.html - PresentMode::Fifo - }; + let present_mode = decide_presentation_mode(&surface_cap); let shader = device.create_shader_module(ShaderModuleDescriptor { label: None, @@ -112,7 +100,11 @@ impl Renderer { module: &shader, entry_point: Some("fs_main"), compilation_options: Default::default(), - targets: &[Some(view_format.into())], + targets: &[Some(ColorTargetState { + format: view_format, + blend: Some(BlendState::ALPHA_BLENDING), + write_mask: ColorWrites::ALL, + })], }), primitive: PrimitiveState { topology: PrimitiveTopology::TriangleStrip, @@ -137,13 +129,7 @@ impl Renderer { ..Default::default() }); // NOTE: 文字テクスチャアトラスは使い回すので、ここで1個だけ作成すれば良い。 - let font_tex = TextureWrapper::new( - &device, - 128, - 128, - TextureFormat::R8Unorm, - TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST, - ); + let char_atlas = CharAtlas::new(scale_factor, &device); let fixed_bind_group = device.create_bind_group(&BindGroupDescriptor { label: None, layout: &fixed_bind_group_layout, @@ -154,7 +140,7 @@ impl Renderer { }, BindGroupEntry { binding: 1, - resource: BindingResource::TextureView(&font_tex.view), + resource: BindingResource::TextureView(&char_atlas.texture.view), }, ], }); @@ -167,7 +153,7 @@ impl Renderer { view_format, present_mode, pipeline, - font_tex, + char_atlas, fixed_bind_group, }; @@ -199,7 +185,7 @@ impl Renderer { } } - pub fn render(&self, window: &Window, current_texture: SurfaceTexture) { + pub fn render(&mut self, window: &Window, current_texture: SurfaceTexture) { let surface_texture_view = current_texture.texture.create_view(&TextureViewDescriptor { format: Some(self.view_format), ..Default::default() @@ -289,6 +275,7 @@ fn decide_surface_and_view_format( // sRGBがサポートされていない・かつテクスチャとビューのフォーマットが一致しなくて良いなら // テクスチャを`formats[0]`・ビューをsRGB + // // NOTE: ビューのフォーマットに従って色変換が行われるので、 // テクスチャの実際のフォーマットが違うだけでsRGBと同様の結果になる。 if can_srgb_view { @@ -296,9 +283,27 @@ fn decide_surface_and_view_format( } // sRGBがサポートされていない・かつテクスチャとビューのフォーマットが一致する必要があるなら // テクスチャもビューも`formats[0]` + // // NOTE: 色変換が行われないので中間色が暗くなる。 // シェーダで自力補正してやれば解決するが、まあ余力があったらね。 else { (format, format) } } + +fn decide_presentation_mode(cap: &SurfaceCapabilities) -> PresentMode { + // REVIEW: 高負荷なので素直にFIFOにして垂直同期で回す方が良いかもしれない。 + if cap.present_modes.contains(&PresentMode::Mailbox) { + // 垂直同期を待つフレーム上書きモード + PresentMode::Mailbox + } else if cap.present_modes.contains(&PresentMode::Immediate) { + // 垂直同期を待たないフレーム上書きモード + PresentMode::Immediate + } else { + // 垂直同期を待つフレーム保守モード + // + // NOTE: 殆どすべての環境でサポートされていることを期待して良い。 + // https://wgpu.rs/doc/wgpu/enum.PresentMode.html + PresentMode::Fifo + } +} |
