summaryrefslogtreecommitdiff
path: root/src/graphics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics.rs')
-rw-r--r--src/graphics.rs61
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
+ }
+}