summaryrefslogtreecommitdiff
path: root/client/src/scene_prepare.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-22 00:23:58 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-22 00:23:58 +0100
commit0612ce58890741428f10c73a63bcb417dcd43a9f (patch)
treea06a6d180722cc3adc35d6a8e30789773b56d508 /client/src/scene_prepare.rs
parent13eb6abfe0e766e432a2f08d58fa9f5a6c5026e7 (diff)
downloadweareserver-0612ce58890741428f10c73a63bcb417dcd43a9f.tar
weareserver-0612ce58890741428f10c73a63bcb417dcd43a9f.tar.bz2
weareserver-0612ce58890741428f10c73a63bcb417dcd43a9f.tar.zst
generalize pipeline configuration in preparation for skinning
Diffstat (limited to 'client/src/scene_prepare.rs')
-rw-r--r--client/src/scene_prepare.rs158
1 files changed, 152 insertions, 6 deletions
diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs
index 4e57e77..4b298a1 100644
--- a/client/src/scene_prepare.rs
+++ b/client/src/scene_prepare.rs
@@ -15,10 +15,11 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::{
- armature::{self, RArmature},
+ armature::RArmature,
download::Downloader,
meshops::{generate_normals, generate_tangents, generate_texcoords},
scene_render::SceneBgLayouts,
+ shaders::SceneShaders,
};
use anyhow::Result;
use bytemuck::{Pod, Zeroable};
@@ -38,12 +39,17 @@ use std::{
use weareshared::{
Affine3A,
packets::Resource,
- resources::{Armature, Image, MeshPart, Prefab},
+ resources::{Image, MeshPart, Prefab},
};
use wgpu::{
AddressMode, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindingResource,
- Buffer, BufferUsages, Device, Extent3d, FilterMode, Queue, SamplerDescriptor, Texture,
+ BlendState, Buffer, BufferUsages, ColorTargetState, ColorWrites, CompareFunction,
+ DepthBiasState, DepthStencilState, Device, Extent3d, Face, FilterMode, FragmentState,
+ FrontFace, MultisampleState, PipelineCompilationOptions, PipelineLayoutDescriptor, PolygonMode,
+ PrimitiveState, PrimitiveTopology, PushConstantRange, Queue, RenderPipeline,
+ RenderPipelineDescriptor, SamplerDescriptor, ShaderStages, StencilState, Texture,
TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, TextureViewDescriptor,
+ VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode,
util::{BufferInitDescriptor, DeviceExt, TextureDataOrder},
};
@@ -90,6 +96,8 @@ pub struct ScenePreparer {
device: Arc<Device>,
queue: Arc<Queue>,
layouts: SceneBgLayouts,
+ shaders: SceneShaders,
+ render_format: TextureFormat,
textures: DemandMap<(Resource<Image<'static>>, bool), (Arc<Texture>, Arc<BindGroup>)>,
placeholder_textures: DemandMap<TextureIdentityKind, (Arc<Texture>, Arc<BindGroup>)>,
@@ -100,11 +108,20 @@ pub struct ScenePreparer {
generated_texcoord_buffers: DemandMap<TexcoordBufferSpec, Arc<Buffer>>,
mesh_parts: DemandMap<Resource<MeshPart>, Arc<RMeshPart>>,
materials: DemandMap<Material, Arc<BindGroup>>,
+ pipelines: DemandMap<PipelineConfig, Arc<RenderPipeline>>,
pub prefabs: DemandMap<Resource<Prefab>, Arc<RPrefab>>,
}
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct PipelineConfig {
+ format: TextureFormat,
+ skin: bool,
+ backface_culling: bool,
+}
+
pub struct RPrefab(pub Vec<(Affine3A, Arc<RMeshPart>)>);
pub struct RMeshPart {
+ pub pipeline: Arc<RenderPipeline>,
pub index_count: u32,
pub index: Arc<Buffer>,
pub va_position: Arc<Buffer>,
@@ -157,11 +174,13 @@ struct Material {
}
impl ScenePreparer {
- pub fn new(device: Arc<Device>, queue: Arc<Queue>, layouts: SceneBgLayouts) -> Self {
+ pub fn new(device: Arc<Device>, queue: Arc<Queue>, render_format: TextureFormat) -> Self {
Self {
+ render_format,
+ layouts: SceneBgLayouts::load(&device),
+ shaders: SceneShaders::load(&device),
device,
queue,
- layouts,
index_buffers: DemandMap::new(),
vertex_buffers: DemandMap::new(),
mesh_parts: DemandMap::new(),
@@ -172,6 +191,7 @@ impl ScenePreparer {
generated_normal_buffers: DemandMap::new(),
generated_texcoord_buffers: DemandMap::new(),
materials: DemandMap::new(),
+ pipelines: DemandMap::new(),
}
}
pub fn update(&self, dls: &Downloader) -> Result<usize> {
@@ -347,7 +367,7 @@ impl ScenePreparer {
});
let bind_group = self.device.create_bind_group(&BindGroupDescriptor {
label: Some("material"),
- layout: &self.material_bgl,
+ layout: &self.layouts.material,
entries: &[BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
@@ -355,6 +375,13 @@ impl ScenePreparer {
});
self.materials.insert(spec, Arc::new(bind_group), 0);
}
+ for spec in self.pipelines.needed() {
+ self.pipelines.insert(
+ spec.clone(),
+ Arc::new(spec.create(&self.device, &self.layouts, &self.shaders)),
+ 0,
+ );
+ }
for pres in self.mesh_parts.needed() {
let start = Instant::now();
if let Some(part) = dls.try_get(pres.clone())? {
@@ -461,7 +488,14 @@ impl ScenePreparer {
Some(None)
};
+ let pipeline = self.pipelines.try_get(PipelineConfig {
+ format: self.render_format,
+ skin: false,
+ backface_culling: part.g_double_sided.is_none(),
+ });
+
if let (
+ Some(pipeline),
Some((index, index_count)),
Some(va_normal),
Some(va_tangent),
@@ -474,6 +508,7 @@ impl ScenePreparer {
Some(tex_albedo),
Some(material),
) = (
+ pipeline,
index,
normal,
tangent,
@@ -499,6 +534,7 @@ impl ScenePreparer {
self.mesh_parts.insert(
pres,
Arc::new(RMeshPart {
+ pipeline,
index_count,
index,
va_normal,
@@ -582,6 +618,110 @@ fn create_texture(
(Arc::new(texture), Arc::new(bindgroup))
}
+impl PipelineConfig {
+ 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 {
+ 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,
+ })
+ }
+}
+
impl<K, V> Widget for &DemandMap<K, V> {
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
let state = self.inner.read().unwrap();
@@ -618,6 +758,8 @@ impl ScenePreparer {
&self.generated_texcoord_buffers,
);
visit("textures", &self.textures);
+ visit("materials", &self.materials);
+ visit("pipelines", &self.pipelines);
}
}
@@ -644,6 +786,10 @@ impl Widget for &ScenePreparer {
self.generated_texcoord_buffers.ui(ui);
ui.label("textures");
self.textures.ui(ui);
+ ui.label("materials");
+ self.materials.ui(ui);
+ ui.label("pipelines");
+ self.pipelines.ui(ui);
})
.response
}