summaryrefslogtreecommitdiff
path: root/client/src/renderer.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-04 23:32:43 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-04 23:32:43 +0100
commit72c23eb57070ab859ffde4f989aa85f7f2eedcf8 (patch)
tree963a0b346d8ddb8baa8cacdec31784b3f442eadc /client/src/renderer.rs
parent2707f03617478e2a5e521961c46c9c6511d5088d (diff)
downloadweareserver-72c23eb57070ab859ffde4f989aa85f7f2eedcf8.tar
weareserver-72c23eb57070ab859ffde4f989aa85f7f2eedcf8.tar.bz2
weareserver-72c23eb57070ab859ffde4f989aa85f7f2eedcf8.tar.zst
tri
Diffstat (limited to 'client/src/renderer.rs')
-rw-r--r--client/src/renderer.rs158
1 files changed, 158 insertions, 0 deletions
diff --git a/client/src/renderer.rs b/client/src/renderer.rs
new file mode 100644
index 0000000..b21c139
--- /dev/null
+++ b/client/src/renderer.rs
@@ -0,0 +1,158 @@
+use anyhow::{Result, anyhow};
+use pollster::FutureExt;
+use wgpu::{
+ Backends, BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Color,
+ ColorTargetState, ColorWrites, CommandEncoderDescriptor, Device, DeviceDescriptor, Features,
+ FragmentState, FrontFace, Instance, InstanceDescriptor, Limits, LoadOp, MaintainBase,
+ MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor,
+ PolygonMode, PowerPreference, PrimitiveState, PrimitiveTopology, Queue,
+ RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor,
+ RequestAdapterOptions, StoreOp, Surface, SurfaceConfiguration, TextureViewDescriptor,
+ VertexState, include_wgsl,
+};
+use winit::window::Window;
+
+pub struct Renderer<'a> {
+ surface: Surface<'a>,
+ pipeline: RenderPipeline,
+ bind_group: BindGroup,
+ queue: Queue,
+ device: Device,
+ surface_configuration: SurfaceConfiguration,
+}
+impl<'a> Renderer<'a> {
+ pub fn new(window: &'a Window) -> Result<Self> {
+ let instance = Instance::new(InstanceDescriptor {
+ backends: Backends::all(),
+ ..Default::default()
+ });
+
+ let surface = instance.create_surface(window)?;
+ let adapter = instance
+ .request_adapter(&RequestAdapterOptions {
+ compatible_surface: Some(&surface),
+ power_preference: PowerPreference::HighPerformance,
+ ..Default::default()
+ })
+ .block_on()
+ .ok_or(anyhow!("no adapter found"))?;
+
+ let (device, queue) = adapter
+ .request_device(
+ &DeviceDescriptor {
+ required_features: Features::default(),
+ required_limits: Limits::downlevel_defaults(),
+ ..Default::default()
+ },
+ None,
+ )
+ .block_on()?;
+
+ let surface_configuration = surface
+ .get_default_config(&adapter, 256, 256)
+ .ok_or(anyhow!("no default config"))?;
+
+ let module = device.create_shader_module(include_wgsl!("shader.wgsl"));
+
+ let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
+ entries: &[],
+ label: None,
+ });
+ let bind_group = device.create_bind_group(&BindGroupDescriptor {
+ label: None,
+ layout: &bind_group_layout,
+ entries: &[],
+ });
+ let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
+ label: None,
+ bind_group_layouts: &[&bind_group_layout],
+ push_constant_ranges: &[],
+ });
+ let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor {
+ label: None,
+ layout: Some(&pipeline_layout),
+ fragment: Some(FragmentState {
+ module: &module,
+ entry_point: Some("fs_main"),
+ targets: &[Some(ColorTargetState {
+ blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING),
+ format: surface_configuration.format,
+ write_mask: ColorWrites::all(),
+ })],
+ compilation_options: PipelineCompilationOptions::default(),
+ }),
+ vertex: VertexState {
+ module: &module,
+ entry_point: Some("vs_main"),
+ buffers: &[],
+ compilation_options: PipelineCompilationOptions::default(),
+ },
+ primitive: PrimitiveState {
+ topology: PrimitiveTopology::TriangleList,
+ front_face: FrontFace::Ccw,
+ cull_mode: None, //Some(Face::Back),
+ polygon_mode: PolygonMode::Fill,
+ ..Default::default()
+ },
+ depth_stencil: Default::default(),
+ multisample: MultisampleState::default(),
+ multiview: None,
+ cache: None,
+ });
+
+ surface.configure(&device, &surface_configuration);
+
+ Ok(Self {
+ surface,
+ pipeline,
+ bind_group,
+ device,
+ queue,
+ surface_configuration,
+ })
+ }
+
+ pub fn resize(&mut self, width: u32, height: u32) {
+ self.surface_configuration.width = width;
+ self.surface_configuration.height = height;
+ self.surface
+ .configure(&self.device, &self.surface_configuration);
+ }
+
+ pub fn draw(&mut self) -> Result<()> {
+ let target = self.surface.get_current_texture()?;
+ let target_view = target
+ .texture
+ .create_view(&TextureViewDescriptor::default());
+
+ let mut commands = self
+ .device
+ .create_command_encoder(&CommandEncoderDescriptor { label: None });
+
+ {
+ let mut rpass = commands.begin_render_pass(&RenderPassDescriptor {
+ label: None,
+ color_attachments: &[Some(RenderPassColorAttachment {
+ view: &target_view,
+ resolve_target: None,
+ ops: Operations {
+ store: StoreOp::Store,
+ load: LoadOp::Clear(Color::BLUE),
+ },
+ })],
+ ..Default::default()
+ });
+
+ rpass.set_bind_group(0, &self.bind_group, &[]);
+ rpass.set_pipeline(&self.pipeline);
+ rpass.draw(0..3, 0..1);
+ }
+
+ let i = self.queue.submit(Some(commands.finish()));
+ self.device.poll(MaintainBase::WaitForSubmissionIndex(i));
+
+ target.present();
+
+ Ok(())
+ }
+}