summaryrefslogtreecommitdiff
path: root/client/src/ui.rs
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/ui.rs')
-rw-r--r--client/src/ui.rs173
1 files changed, 101 insertions, 72 deletions
diff --git a/client/src/ui.rs b/client/src/ui.rs
index 638978a..3687276 100644
--- a/client/src/ui.rs
+++ b/client/src/ui.rs
@@ -15,26 +15,32 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use egui::{
- Context, TextureId,
+ Context, ImageData, TextureId,
epaint::{Primitive, Vertex},
};
+use glam::Mat4;
+use log::info;
use std::{collections::HashMap, num::NonZeroU64};
use wgpu::{
- BindGroup, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState, Buffer,
- BufferDescriptor, BufferUsages, Color, ColorTargetState, ColorWrites, CommandEncoder,
- CompareFunction, DepthBiasState, DepthStencilState, Device, FragmentState, FrontFace,
- IndexFormat, LoadOp, MultisampleState, Operations, PipelineCompilationOptions,
- PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange,
- Queue, RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline,
- RenderPipelineDescriptor, SamplerBindingType, ShaderStages, StencilState, StoreOp, Texture,
- TextureFormat, TextureSampleType, TextureView, TextureViewDimension, VertexAttribute,
- VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, include_wgsl,
+ BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor,
+ BindGroupLayoutEntry, BindingResource, BindingType, BlendState, Buffer, BufferDescriptor,
+ BufferUsages, Color, ColorTargetState, ColorWrites, CommandEncoder, CompareFunction,
+ DepthBiasState, DepthStencilState, Device, Extent3d, FragmentState, FrontFace, IndexFormat,
+ LoadOp, MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor,
+ PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange, Queue,
+ RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor,
+ SamplerBindingType, SamplerDescriptor, ShaderStages, StencilState, StoreOp, Texture,
+ TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
+ TextureView, TextureViewDescriptor, TextureViewDimension, VertexAttribute, VertexBufferLayout,
+ VertexFormat, VertexState, VertexStepMode, include_wgsl,
+ util::{DeviceExt, TextureDataOrder},
};
pub struct UiRenderer {
ctx: Context,
pipeline: RenderPipeline,
+ bind_group_layout: BindGroupLayout,
index: Buffer,
vertex: Buffer,
@@ -131,13 +137,7 @@ impl UiRenderer {
polygon_mode: PolygonMode::Fill,
..Default::default()
},
- depth_stencil: Some(DepthStencilState {
- depth_compare: CompareFunction::Greater,
- depth_write_enabled: true,
- format: TextureFormat::Depth32Float,
- bias: DepthBiasState::default(),
- stencil: StencilState::default(),
- }),
+ depth_stencil: None,
multisample: MultisampleState::default(),
multiview: None,
cache: None,
@@ -147,60 +147,89 @@ impl UiRenderer {
pipeline,
index,
vertex,
+ bind_group_layout,
textures: HashMap::new(),
}
}
- pub fn create_texture() {
- // let texture = device.create_texture_with_data(
- // &queue,
- // &TextureDescriptor {
- // label: None,
- // size: Extent3d {
- // depth_or_array_layers: 1,
- // width,
- // height,
- // },
- // mip_level_count: 1,
- // sample_count: 1,
- // dimension: TextureDimension::D2,
- // format: TextureFormat::Rgba8UnormSrgb,
- // usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
- // view_formats: &[],
- // },
- // TextureDataOrder::LayerMajor,
- // data,
- // );
- // let textureview = texture.create_view(&TextureViewDescriptor::default());
- // let sampler = device.create_sampler(&SamplerDescriptor {
- // ..Default::default()
- // });
- // let bindgroup = device.create_bind_group(&BindGroupDescriptor {
- // label: None,
- // layout: &bgl,
- // entries: &[
- // BindGroupEntry {
- // binding: 0,
- // resource: BindingResource::TextureView(&textureview),
- // },
- // BindGroupEntry {
- // binding: 1,
- // resource: BindingResource::Sampler(&sampler),
- // },
- // ],
- // });
- }
+ pub fn create_texture() {}
- pub fn draw(&self, queue: &Queue, commands: &mut CommandEncoder, target: &TextureView) {
+ pub fn draw(
+ &mut self,
+ device: &Device,
+ queue: &Queue,
+ commands: &mut CommandEncoder,
+ target: &TextureView,
+ projection: Mat4,
+ ) {
let raw_input = egui::RawInput::default();
let full_output = self.ctx.run(raw_input, |ctx| {
egui::CentralPanel::default().show(&ctx, |ui| {
ui.label("Hello world!");
+ ui.label("I dont think this will ever work...");
ui.button("Click me").clicked();
});
});
- for (texid, delta) in full_output.textures_delta.set {}
+ for (texid, delta) in full_output.textures_delta.set {
+ if let Some((texbg, tex)) = self.textures.get_mut(&texid) {
+ drop((texbg, tex));
+ todo!()
+ } else {
+ assert_eq!(
+ delta.pos, None,
+ "partial update impossible; texture does not yet exist"
+ );
+ info!(
+ "uploading new UI texture: width={}, height={}",
+ delta.image.width(),
+ delta.image.height()
+ );
+ let pixels = match &delta.image {
+ ImageData::Color(color_image) => color_image.pixels.clone(),
+ ImageData::Font(font_image) => font_image.srgba_pixels(None).collect(),
+ };
+
+ let texture = device.create_texture_with_data(
+ &queue,
+ &TextureDescriptor {
+ label: None,
+ size: Extent3d {
+ depth_or_array_layers: 1,
+ width: delta.image.width() as u32,
+ height: delta.image.height() as u32,
+ },
+ mip_level_count: 1,
+ sample_count: 1,
+ dimension: TextureDimension::D2,
+ format: TextureFormat::Rgba8UnormSrgb,
+ usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
+ view_formats: &[],
+ },
+ TextureDataOrder::LayerMajor,
+ bytemuck::cast_slice::<_, u8>(&pixels),
+ );
+ let textureview = texture.create_view(&TextureViewDescriptor::default());
+ let sampler = device.create_sampler(&SamplerDescriptor {
+ ..Default::default()
+ });
+ let bindgroup = device.create_bind_group(&BindGroupDescriptor {
+ label: None,
+ layout: &self.bind_group_layout,
+ entries: &[
+ BindGroupEntry {
+ binding: 0,
+ resource: BindingResource::TextureView(&textureview),
+ },
+ BindGroupEntry {
+ binding: 1,
+ resource: BindingResource::Sampler(&sampler),
+ },
+ ],
+ });
+ self.textures.insert(texid, (bindgroup, texture));
+ }
+ }
let clipped_primitives = self
.ctx
@@ -210,8 +239,8 @@ impl UiRenderer {
let mut vertex_count = 0;
for p in &clipped_primitives {
if let Primitive::Mesh(mesh) = &p.primitive {
+ index_count += mesh.indices.len();
vertex_count += mesh.vertices.len();
- index_count += mesh.vertices.len();
}
}
@@ -237,17 +266,19 @@ impl UiRenderer {
let mut slices = Vec::new();
for p in clipped_primitives {
if let Primitive::Mesh(mesh) = p.primitive {
- mapped_index[index_offset..index_offset + (mesh.indices.len() * size_of::<u32>())]
+ mapped_index[index_offset * size_of::<u32>()
+ ..(index_offset + mesh.indices.len()) * size_of::<u32>()]
.copy_from_slice(bytemuck::cast_slice(&mesh.indices));
- mapped_vertex
- [vertex_offset..vertex_offset + (mesh.vertices.len() * size_of::<Vertex>())]
+ mapped_vertex[vertex_offset * size_of::<Vertex>()
+ ..(vertex_offset + mesh.vertices.len()) * size_of::<Vertex>()]
.copy_from_slice(bytemuck::cast_slice(&mesh.vertices));
- index_offset += mesh.indices.len();
- vertex_offset += mesh.vertices.len();
slices.push((
index_offset as u32..index_offset as u32 + mesh.indices.len() as u32,
vertex_offset as i32,
+ mesh.texture_id,
));
+ index_offset += mesh.indices.len();
+ vertex_offset += mesh.vertices.len();
}
}
@@ -258,22 +289,20 @@ impl UiRenderer {
resolve_target: None,
ops: Operations {
store: StoreOp::Store,
- load: LoadOp::Clear(Color {
- r: 0.01,
- g: 0.01,
- b: 0.01,
- a: 1.,
- }),
+ load: LoadOp::Load,
},
})],
..Default::default()
});
+ let projection = projection.to_cols_array().map(|v| v.to_le_bytes());
+
rpass.set_pipeline(&self.pipeline);
rpass.set_index_buffer(self.index.slice(..), IndexFormat::Uint32);
rpass.set_vertex_buffer(0, self.vertex.slice(..));
- for (index, base_vertex) in slices {
- // rpass.set_bind_group(0, &self.bind_group, &[]);
+ rpass.set_push_constants(ShaderStages::VERTEX, 0, projection.as_flattened());
+ for (index, base_vertex, texid) in slices {
+ rpass.set_bind_group(0, &self.textures.get(&texid).unwrap().0, &[]);
rpass.draw_indexed(index, base_vertex, 0..1);
}
}