summaryrefslogtreecommitdiff
path: root/client/src/render/scene/draw.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-23 22:45:35 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-23 22:45:35 +0100
commit3344eb2d678f9c5973c8e38083760254b54c20fc (patch)
tree793678d4230dd012285169ba34005064690c7af0 /client/src/render/scene/draw.rs
parentdd40803458695abcd4100fffb874cc25a71ea758 (diff)
downloadweareserver-3344eb2d678f9c5973c8e38083760254b54c20fc.tar
weareserver-3344eb2d678f9c5973c8e38083760254b54c20fc.tar.bz2
weareserver-3344eb2d678f9c5973c8e38083760254b54c20fc.tar.zst
split scene_prepare to many files
Diffstat (limited to 'client/src/render/scene/draw.rs')
-rw-r--r--client/src/render/scene/draw.rs104
1 files changed, 104 insertions, 0 deletions
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 <https://www.gnu.org/licenses/>.
+*/
+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<Resource<Prefab>, Arc<RPrefab>>,
+ 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);
+ }
+ }
+ }
+ }
+}