From 3344eb2d678f9c5973c8e38083760254b54c20fc Mon Sep 17 00:00:00 2001 From: metamuffin Date: Thu, 23 Jan 2025 22:45:35 +0100 Subject: split scene_prepare to many files --- client/src/render/scene/draw.rs | 104 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 client/src/render/scene/draw.rs (limited to 'client/src/render/scene/draw.rs') diff --git a/client/src/render/scene/draw.rs b/client/src/render/scene/draw.rs new file mode 100644 index 0000000..dabb9cd --- /dev/null +++ b/client/src/render/scene/draw.rs @@ -0,0 +1,104 @@ +/* + wearechat - generic multiplayer game with voip + Copyright (C) 2025 metamuffin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License only. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ +use super::{DemandMap, RPrefab}; +use glam::{EulerRot, Mat3, Mat4}; +use std::sync::Arc; +use weareshared::{packets::Resource, resources::Prefab, tree::SceneTree}; +use wgpu::{ + Color, CommandEncoder, IndexFormat, LoadOp, Operations, RenderPassColorAttachment, + RenderPassDepthStencilAttachment, RenderPassDescriptor, ShaderStages, StoreOp, TextureView, +}; + +pub struct ScenePipeline; + +impl ScenePipeline { + pub fn draw( + &mut self, + commands: &mut CommandEncoder, + target: &TextureView, + depth: &TextureView, + scene: &SceneTree, + prefabs: &DemandMap, Arc>, + projection: Mat4, + ) { + let mut rpass = commands.begin_render_pass(&RenderPassDescriptor { + label: None, + color_attachments: &[Some(RenderPassColorAttachment { + view: target, + resolve_target: None, + ops: Operations { + store: StoreOp::Store, + load: LoadOp::Clear(Color { + r: 0.01, + g: 0.01, + b: 0.01, + a: 1., + }), + }, + })], + depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { + view: &depth, + depth_ops: Some(Operations { + load: LoadOp::Clear(1.), + store: StoreOp::Store, + }), + stencil_ops: None, + }), + ..Default::default() + }); + + for ob in scene.objects.values() { + let prefab_projection = projection + * Mat4::from_translation(ob.pos.into()) + * Mat4::from_mat3(Mat3::from_euler( + EulerRot::YXZ, + ob.rot.x, + ob.rot.y, + ob.rot.z, + )); + if let Some(prefab) = prefabs.try_get(ob.res.clone()) { + for (affine, part) in &prefab.0 { + let part_projection = prefab_projection + * Mat4::from_translation(affine.translation.into()) + * Mat4::from_mat3a(affine.matrix3); + let projection = part_projection.to_cols_array().map(|v| v.to_le_bytes()); + let mb = affine.matrix3.to_cols_array(); // TODO apply object rotation + // add padding for gpu mat3x3 repr + let model_basis = [ + mb[0], mb[1], mb[2], 0., // + mb[3], mb[4], mb[5], 0., // + mb[6], mb[7], mb[8], 0., // + ]; + let model_basis = bytemuck::cast_slice(&model_basis); + + rpass.set_pipeline(&part.pipeline); + rpass.set_bind_group(0, &*part.tex_albedo, &[]); + rpass.set_bind_group(1, &*part.tex_normal, &[]); + rpass.set_bind_group(2, &*part.material, &[]); + rpass.set_push_constants(ShaderStages::VERTEX, 0, projection.as_flattened()); + rpass.set_push_constants(ShaderStages::VERTEX, 64, model_basis); + rpass.set_index_buffer(part.index.slice(..), IndexFormat::Uint32); + rpass.set_vertex_buffer(0, part.va_position.slice(..)); + rpass.set_vertex_buffer(1, part.va_normal.slice(..)); + rpass.set_vertex_buffer(2, part.va_tangent.slice(..)); + rpass.set_vertex_buffer(3, part.va_texcoord.slice(..)); + rpass.draw_indexed(0..part.index_count, 0, 0..1); + } + } + } + } +} -- cgit v1.2.3-70-g09d2