summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-10 03:11:29 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-10 03:11:29 +0100
commit5d935c26589c014e6dc2941481988abf50e51fdf (patch)
treebc679c9e6ef6783749d3413c0e8368979dbb6b15 /client
parent3ecd4588d4aa85a93a06aa5a1a3a60b918a72557 (diff)
downloadweareserver-5d935c26589c014e6dc2941481988abf50e51fdf.tar
weareserver-5d935c26589c014e6dc2941481988abf50e51fdf.tar.bz2
weareserver-5d935c26589c014e6dc2941481988abf50e51fdf.tar.zst
fix triple inverted projection madness
Diffstat (limited to 'client')
-rw-r--r--client/src/camera.rs8
-rw-r--r--client/src/renderer.rs16
-rw-r--r--client/src/scene_render.rs8
-rw-r--r--client/src/shader.wgsl5
-rw-r--r--client/src/ui.rs173
5 files changed, 125 insertions, 85 deletions
diff --git a/client/src/camera.rs b/client/src/camera.rs
index d7a69c5..f5a911b 100644
--- a/client/src/camera.rs
+++ b/client/src/camera.rs
@@ -33,15 +33,15 @@ impl Camera {
}
}
pub fn update(&mut self, input_move: Vec3, input_rot: Vec2, dt: f32) {
- self.pos += self.rotation_mat() * (-vec3(input_move.z, input_move.y, input_move.x) * dt);
- self.rot.x += input_rot.x * 0.002;
- self.rot.y += input_rot.y * 0.002;
+ self.pos += self.rotation_mat() * (vec3(input_move.z, input_move.y, -input_move.x) * dt);
+ self.rot.x += input_rot.x * -0.002;
+ self.rot.y += input_rot.y * -0.002;
}
pub fn rotation_mat(&self) -> Mat3 {
Mat3::from_euler(EulerRot::YXZ, self.rot.x, self.rot.y, self.rot.z)
}
pub fn to_matrix(&self) -> Mat4 {
- Mat4::perspective_infinite_reverse_rh(self.fov, self.aspect, 0.1)
+ Mat4::perspective_rh(self.fov, self.aspect, 0.1, 100.)
* Mat4::from_mat3(self.rotation_mat().inverse())
* Mat4::from_translation(-self.pos)
}
diff --git a/client/src/renderer.rs b/client/src/renderer.rs
index b1ff227..66f8c5e 100644
--- a/client/src/renderer.rs
+++ b/client/src/renderer.rs
@@ -14,7 +14,9 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::{camera::Camera, scene_prepare::ScenePreparer, scene_render::ScenePipeline};
+use crate::{
+ camera::Camera, scene_prepare::ScenePreparer, scene_render::ScenePipeline, ui::UiRenderer,
+};
use anyhow::{Result, anyhow};
use log::{info, warn};
use pollster::FutureExt;
@@ -33,6 +35,7 @@ pub struct Renderer<'a> {
device: Arc<Device>,
surface_configuration: SurfaceConfiguration,
scene_pipeline: ScenePipeline,
+ ui_renderer: UiRenderer,
pub scene_prepare: ScenePreparer,
surface_needs_reconfigure: bool,
}
@@ -82,6 +85,8 @@ impl<'a> Renderer<'a> {
ScenePipeline::new(&device, surface_configuration.format);
let scene_prepare = ScenePreparer::new(device.clone(), queue.clone(), texture_bgl);
+ let ui_renderer = UiRenderer::new(&device, surface_configuration.format);
+
Ok(Self {
scene_pipeline,
scene_prepare,
@@ -89,6 +94,7 @@ impl<'a> Renderer<'a> {
device,
queue,
surface_configuration,
+ ui_renderer,
surface_needs_reconfigure: false,
})
}
@@ -130,6 +136,14 @@ impl<'a> Renderer<'a> {
projection,
);
+ self.ui_renderer.draw(
+ &self.device,
+ &self.queue,
+ &mut commands,
+ &target_view,
+ projection,
+ );
+
let i = self.queue.submit(Some(commands.finish()));
self.device.poll(MaintainBase::WaitForSubmissionIndex(i));
diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs
index 6ec5f25..9dc14d1 100644
--- a/client/src/scene_render.rs
+++ b/client/src/scene_render.rs
@@ -127,8 +127,8 @@ impl ScenePipeline {
..Default::default()
},
depth_stencil: Some(DepthStencilState {
- depth_compare: CompareFunction::Greater,
depth_write_enabled: true,
+ depth_compare: CompareFunction::Less,
format: TextureFormat::Depth32Float,
bias: DepthBiasState::default(),
stencil: StencilState::default(),
@@ -165,7 +165,7 @@ impl ScenePipeline {
target: &TextureView,
scene: &SceneTree,
prefabs: &mut DemandMap<Resource<Prefab>, Arc<RPrefab>>,
- camera: Mat4,
+ projection: Mat4,
) {
let mut rpass = commands.begin_render_pass(&RenderPassDescriptor {
label: None,
@@ -185,7 +185,7 @@ impl ScenePipeline {
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &self.depth,
depth_ops: Some(Operations {
- load: LoadOp::Clear(0.),
+ load: LoadOp::Clear(1.),
store: StoreOp::Store,
}),
stencil_ops: None,
@@ -194,7 +194,7 @@ impl ScenePipeline {
});
for ob in scene.objects.values() {
- let prefab_projection = camera
+ let prefab_projection = projection
* Mat4::from_mat3(Mat3::from_euler(
EulerRot::YXZ,
ob.rot.x,
diff --git a/client/src/shader.wgsl b/client/src/shader.wgsl
index fddff86..eb5530c 100644
--- a/client/src/shader.wgsl
+++ b/client/src/shader.wgsl
@@ -35,10 +35,7 @@ var<push_constant> project: mat4x4<f32>;
@vertex
fn vs_main(vi: VertexIn) -> VertexOut {
- var clip = project * vec4(vi.x, vi.y, vi.z, -1.);
- clip /= clip.w;
- clip.x *= -1.;
- clip.y *= -1.;
+ var clip = project * vec4(vi.x, vi.y, vi.z, 1.);
let vo = VertexOut(
clip,
vec3(vi.nx, vi.ny, vi.nz),
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);
}
}