From 3bbe5ebcdb2a5aa6810dd05576c6ec031efdc1c7 Mon Sep 17 00:00:00 2001 From: Tengu712 Date: Wed, 7 Oct 2026 00:57:01 +0900 Subject: render image --- src/graphics.rs | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-) (limited to 'src/graphics.rs') diff --git a/src/graphics.rs b/src/graphics.rs index bab9f05..92defc2 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,25 +1,31 @@ -use glam::{Vec2, Vec4}; -use std::{borrow::Cow, mem, slice, sync::Arc}; +use glam::{Mat2, Vec2}; +use std::{borrow::Cow, mem, num::NonZeroU32, slice, sync::Arc}; use wgpu::*; use winit::{dpi::PhysicalSize, event_loop::OwnedDisplayHandle, window::Window}; pub mod command; mod font; +pub mod image; mod texture; use command::RenderCommand; use font::CharAtlas; +use image::ImageId; +use texture::TextureWrapper; pub const INSTANCE_MAX_COUNT: u64 = 128; +const IMAGE_SLOT_COUNT: u32 = 5; #[repr(C)] struct InstanceData { + // 拡縮・回転行列 NDCを考慮していること + transform: Mat2, // 中央原点 左→右[-1, 1] 下→上[-1, 1] - position: Vec2, - // 拡大率 (width, height): [0, 1]^2 - scale: Vec2, - // (u, v, width, height): [0, 1]^4 - uv: Vec4, + translation: Vec2, + uv_offset: Vec2, + uv_size: Vec2, + tex_id: u32, + _pad: u32, } pub enum AcquireSurfaceTextureResult { @@ -40,6 +46,7 @@ pub struct Renderer { instances: Buffer, trans_bind_group: BindGroup, char_atlas: CharAtlas, + images: Vec, fixed_bind_group: BindGroup, } @@ -61,7 +68,15 @@ impl Renderer { .await .map_err(|e| e.to_string())?; let (device, queue) = adapter - .request_device(&DeviceDescriptor::default()) + .request_device(&DeviceDescriptor { + required_features: Features::TEXTURE_BINDING_ARRAY + | Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, + required_limits: Limits { + max_binding_array_elements_per_shader_stage: IMAGE_SLOT_COUNT, + ..Default::default() + }, + ..Default::default() + }) .await .map_err(|e| e.to_string())?; @@ -110,6 +125,16 @@ impl Renderer { }, count: None, }, + BindGroupLayoutEntry { + binding: 2, + visibility: ShaderStages::FRAGMENT, + ty: BindingType::Texture { + sample_type: TextureSampleType::Float { filterable: true }, + view_dimension: TextureViewDimension::D2, + multisampled: false, + }, + count: NonZeroU32::new(IMAGE_SLOT_COUNT), + }, ], }); let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { @@ -183,6 +208,8 @@ impl Renderer { }); // NOTE: 文字テクスチャアトラスは使い回すので、ここで1個だけ作成すれば良い。 let char_atlas = CharAtlas::new(scale_factor, &device); + // NOTE: 画像テクスチャ配列は使いまわすので、ここで1個だけ作成すればいい。 + let images = image::create_textures(&device, &queue); let fixed_bind_group = device.create_bind_group(&BindGroupDescriptor { label: None, layout: &fixed_bind_group_layout, @@ -195,6 +222,12 @@ impl Renderer { binding: 1, resource: BindingResource::TextureView(&char_atlas.texture.view), }, + BindGroupEntry { + binding: 2, + resource: BindingResource::TextureViewArray( + &[&images[ImageId::Image as usize].view; IMAGE_SLOT_COUNT as usize], + ), + }, ], }); @@ -209,6 +242,7 @@ impl Renderer { instances, trans_bind_group, char_atlas, + images, fixed_bind_group, }; @@ -282,10 +316,9 @@ impl Renderer { window.scale_factor() as f32, &self.queue, &mut self.char_atlas, + &self.images, &mut instances, ); - // TODO: 今はfont_texしか使わないので1ドローコールで済むが、 - // bind groupを変える必要があればドローコールを切る。 } instances.truncate(INSTANCE_MAX_COUNT as usize); let bytes = unsafe { -- cgit v1.3.1