summaryrefslogtreecommitdiff
path: root/client/src/render/scene/pipelines.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/pipelines.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/pipelines.rs')
-rw-r--r--client/src/render/scene/pipelines.rs196
1 files changed, 196 insertions, 0 deletions
diff --git a/client/src/render/scene/pipelines.rs b/client/src/render/scene/pipelines.rs
new file mode 100644
index 0000000..3b6758e
--- /dev/null
+++ b/client/src/render/scene/pipelines.rs
@@ -0,0 +1,196 @@
+/*
+ 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 wgpu::{
+ BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState,
+ BufferBindingType, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
+ DepthStencilState, Device, Face, FragmentState, FrontFace, MultisampleState,
+ PipelineCompilationOptions, PipelineLayoutDescriptor, PolygonMode, PrimitiveState,
+ PrimitiveTopology, PushConstantRange, RenderPipeline, RenderPipelineDescriptor,
+ SamplerBindingType, ShaderStages, StencilState, TextureFormat, TextureSampleType,
+ TextureViewDimension, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState,
+ VertexStepMode,
+};
+
+use crate::shaders::SceneShaders;
+
+use super::PipelineSpec;
+
+pub struct SceneBgLayouts {
+ pub texture: BindGroupLayout,
+ pub material: BindGroupLayout,
+ pub joints: BindGroupLayout,
+}
+
+impl SceneBgLayouts {
+ pub fn load(device: &Device) -> Self {
+ Self {
+ texture: device.create_bind_group_layout(&BindGroupLayoutDescriptor {
+ entries: &[
+ BindGroupLayoutEntry {
+ binding: 0,
+ count: None,
+ visibility: ShaderStages::FRAGMENT,
+ ty: BindingType::Texture {
+ sample_type: TextureSampleType::Float { filterable: true },
+ view_dimension: TextureViewDimension::D2,
+ multisampled: false,
+ },
+ },
+ BindGroupLayoutEntry {
+ binding: 1,
+ count: None,
+ visibility: ShaderStages::FRAGMENT,
+ ty: BindingType::Sampler(SamplerBindingType::Filtering),
+ },
+ ],
+ label: None,
+ }),
+ material: device.create_bind_group_layout(&BindGroupLayoutDescriptor {
+ entries: &[BindGroupLayoutEntry {
+ binding: 0,
+ count: None,
+ visibility: ShaderStages::FRAGMENT,
+ ty: BindingType::Buffer {
+ ty: BufferBindingType::Uniform,
+ has_dynamic_offset: false,
+ min_binding_size: None,
+ },
+ }],
+ label: None,
+ }),
+ joints: device.create_bind_group_layout(&BindGroupLayoutDescriptor {
+ entries: &[BindGroupLayoutEntry {
+ binding: 0,
+ count: None,
+ visibility: ShaderStages::VERTEX,
+ ty: BindingType::Buffer {
+ ty: BufferBindingType::Uniform,
+ has_dynamic_offset: false,
+ min_binding_size: None,
+ },
+ }],
+ label: None,
+ }),
+ }
+ }
+}
+
+impl PipelineSpec {
+ pub fn create(
+ &self,
+ device: &Device,
+ layouts: &SceneBgLayouts,
+ shaders: &SceneShaders,
+ ) -> RenderPipeline {
+ let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
+ label: None,
+ bind_group_layouts: &[&layouts.texture, &layouts.texture, &layouts.material],
+ push_constant_ranges: &[PushConstantRange {
+ // 4x4 view projections
+ // 3x3(+1 pad) model basis
+ range: 0..((4 * 4 + 3 * 4) * size_of::<f32>() as u32),
+ stages: ShaderStages::VERTEX,
+ }],
+ });
+ device.create_render_pipeline(&RenderPipelineDescriptor {
+ label: None,
+ layout: Some(&pipeline_layout),
+ fragment: Some(FragmentState {
+ module: &shaders.fragment_pbr,
+ entry_point: Some("main"),
+ targets: &[Some(ColorTargetState {
+ blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING),
+ format: self.format,
+ write_mask: ColorWrites::all(),
+ })],
+ compilation_options: PipelineCompilationOptions::default(),
+ }),
+ vertex: VertexState {
+ module: if self.skin {
+ &shaders.vertex_world_skin
+ } else {
+ &shaders.vertex_world
+ },
+ entry_point: Some("main"),
+ buffers: &[
+ // position
+ VertexBufferLayout {
+ step_mode: VertexStepMode::Vertex,
+ array_stride: 3 * size_of::<f32>() as u64,
+ attributes: &[VertexAttribute {
+ format: VertexFormat::Float32x3,
+ offset: 0,
+ shader_location: 0,
+ }],
+ },
+ // normal
+ VertexBufferLayout {
+ step_mode: VertexStepMode::Vertex,
+ array_stride: 3 * size_of::<f32>() as u64,
+ attributes: &[VertexAttribute {
+ format: VertexFormat::Float32x3,
+ offset: 0,
+ shader_location: 1,
+ }],
+ },
+ // tangent
+ VertexBufferLayout {
+ step_mode: VertexStepMode::Vertex,
+ array_stride: 3 * size_of::<f32>() as u64,
+ attributes: &[VertexAttribute {
+ format: VertexFormat::Float32x3,
+ offset: 0,
+ shader_location: 2,
+ }],
+ },
+ // texcoord
+ VertexBufferLayout {
+ step_mode: VertexStepMode::Vertex,
+ array_stride: 2 * size_of::<f32>() as u64,
+ attributes: &[VertexAttribute {
+ format: VertexFormat::Float32x2,
+ offset: 0,
+ shader_location: 3,
+ }],
+ },
+ ],
+ compilation_options: PipelineCompilationOptions::default(),
+ },
+ primitive: PrimitiveState {
+ topology: PrimitiveTopology::TriangleList,
+ front_face: FrontFace::Ccw,
+ cull_mode: if self.backface_culling {
+ Some(Face::Back)
+ } else {
+ None
+ },
+ polygon_mode: PolygonMode::Fill,
+ ..Default::default()
+ },
+ depth_stencil: Some(DepthStencilState {
+ depth_write_enabled: true,
+ depth_compare: CompareFunction::Less,
+ format: TextureFormat::Depth32Float,
+ bias: DepthBiasState::default(),
+ stencil: StencilState::default(),
+ }),
+ multisample: MultisampleState::default(),
+ multiview: None,
+ cache: None,
+ })
+ }
+}