1use bevy_math::Mat4;
4use bevy_render::{
5 mesh::morph::MAX_MORPH_WEIGHTS, render_resource::*, renderer::RenderDevice, texture::GpuImage,
6};
7
8use crate::render::skin::MAX_JOINTS;
9
10const MORPH_WEIGHT_SIZE: usize = size_of::<f32>();
11pub const MORPH_BUFFER_SIZE: usize = MAX_MORPH_WEIGHTS * MORPH_WEIGHT_SIZE;
12
13const JOINT_SIZE: usize = size_of::<Mat4>();
14pub(crate) const JOINT_BUFFER_SIZE: usize = MAX_JOINTS * JOINT_SIZE;
15
16mod layout_entry {
18 use super::{JOINT_BUFFER_SIZE, MORPH_BUFFER_SIZE};
19 use crate::MeshUniform;
20 use bevy_render::{
21 render_resource::{
22 binding_types::{sampler, texture_2d, texture_3d, uniform_buffer_sized},
23 BindGroupLayoutEntryBuilder, BufferSize, GpuArrayBuffer, SamplerBindingType,
24 ShaderStages, TextureSampleType,
25 },
26 renderer::RenderDevice,
27 };
28
29 pub(super) fn model(render_device: &RenderDevice) -> BindGroupLayoutEntryBuilder {
30 GpuArrayBuffer::<MeshUniform>::binding_layout(render_device)
31 .visibility(ShaderStages::VERTEX_FRAGMENT)
32 }
33 pub(super) fn skinning() -> BindGroupLayoutEntryBuilder {
34 uniform_buffer_sized(true, BufferSize::new(JOINT_BUFFER_SIZE as u64))
35 }
36 pub(super) fn weights() -> BindGroupLayoutEntryBuilder {
37 uniform_buffer_sized(true, BufferSize::new(MORPH_BUFFER_SIZE as u64))
38 }
39 pub(super) fn targets() -> BindGroupLayoutEntryBuilder {
40 texture_3d(TextureSampleType::Float { filterable: false })
41 }
42 pub(super) fn lightmaps_texture_view() -> BindGroupLayoutEntryBuilder {
43 texture_2d(TextureSampleType::Float { filterable: true }).visibility(ShaderStages::FRAGMENT)
44 }
45 pub(super) fn lightmaps_sampler() -> BindGroupLayoutEntryBuilder {
46 sampler(SamplerBindingType::Filtering).visibility(ShaderStages::FRAGMENT)
47 }
48}
49
50mod entry {
53 use super::{JOINT_BUFFER_SIZE, MORPH_BUFFER_SIZE};
54 use bevy_render::render_resource::{
55 BindGroupEntry, BindingResource, Buffer, BufferBinding, BufferSize, Sampler, TextureView,
56 };
57
58 fn entry(binding: u32, size: u64, buffer: &Buffer) -> BindGroupEntry {
59 BindGroupEntry {
60 binding,
61 resource: BindingResource::Buffer(BufferBinding {
62 buffer,
63 offset: 0,
64 size: Some(BufferSize::new(size).unwrap()),
65 }),
66 }
67 }
68 pub(super) fn model(binding: u32, resource: BindingResource) -> BindGroupEntry {
69 BindGroupEntry { binding, resource }
70 }
71 pub(super) fn skinning(binding: u32, buffer: &Buffer) -> BindGroupEntry {
72 entry(binding, JOINT_BUFFER_SIZE as u64, buffer)
73 }
74 pub(super) fn weights(binding: u32, buffer: &Buffer) -> BindGroupEntry {
75 entry(binding, MORPH_BUFFER_SIZE as u64, buffer)
76 }
77 pub(super) fn targets(binding: u32, texture: &TextureView) -> BindGroupEntry {
78 BindGroupEntry {
79 binding,
80 resource: BindingResource::TextureView(texture),
81 }
82 }
83 pub(super) fn lightmaps_texture_view(binding: u32, texture: &TextureView) -> BindGroupEntry {
84 BindGroupEntry {
85 binding,
86 resource: BindingResource::TextureView(texture),
87 }
88 }
89 pub(super) fn lightmaps_sampler(binding: u32, sampler: &Sampler) -> BindGroupEntry {
90 BindGroupEntry {
91 binding,
92 resource: BindingResource::Sampler(sampler),
93 }
94 }
95}
96
97#[derive(Clone)]
99pub struct MeshLayouts {
100 pub model_only: BindGroupLayout,
102
103 pub lightmapped: BindGroupLayout,
105
106 pub skinned: BindGroupLayout,
108
109 pub skinned_motion: BindGroupLayout,
112
113 pub morphed: BindGroupLayout,
117
118 pub morphed_motion: BindGroupLayout,
121
122 pub morphed_skinned: BindGroupLayout,
127
128 pub morphed_skinned_motion: BindGroupLayout,
132}
133
134impl MeshLayouts {
135 pub fn new(render_device: &RenderDevice) -> Self {
139 MeshLayouts {
140 model_only: Self::model_only_layout(render_device),
141 lightmapped: Self::lightmapped_layout(render_device),
142 skinned: Self::skinned_layout(render_device),
143 skinned_motion: Self::skinned_motion_layout(render_device),
144 morphed: Self::morphed_layout(render_device),
145 morphed_motion: Self::morphed_motion_layout(render_device),
146 morphed_skinned: Self::morphed_skinned_layout(render_device),
147 morphed_skinned_motion: Self::morphed_skinned_motion_layout(render_device),
148 }
149 }
150
151 fn model_only_layout(render_device: &RenderDevice) -> BindGroupLayout {
154 render_device.create_bind_group_layout(
155 "mesh_layout",
156 &BindGroupLayoutEntries::single(
157 ShaderStages::empty(),
158 layout_entry::model(render_device),
159 ),
160 )
161 }
162
163 fn skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
165 render_device.create_bind_group_layout(
166 "skinned_mesh_layout",
167 &BindGroupLayoutEntries::with_indices(
168 ShaderStages::VERTEX,
169 (
170 (0, layout_entry::model(render_device)),
171 (1, layout_entry::skinning()),
173 ),
174 ),
175 )
176 }
177
178 fn skinned_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
181 render_device.create_bind_group_layout(
182 "skinned_motion_mesh_layout",
183 &BindGroupLayoutEntries::with_indices(
184 ShaderStages::VERTEX,
185 (
186 (0, layout_entry::model(render_device)),
187 (1, layout_entry::skinning()),
189 (6, layout_entry::skinning()),
191 ),
192 ),
193 )
194 }
195
196 fn morphed_layout(render_device: &RenderDevice) -> BindGroupLayout {
198 render_device.create_bind_group_layout(
199 "morphed_mesh_layout",
200 &BindGroupLayoutEntries::with_indices(
201 ShaderStages::VERTEX,
202 (
203 (0, layout_entry::model(render_device)),
204 (2, layout_entry::weights()),
206 (3, layout_entry::targets()),
207 ),
208 ),
209 )
210 }
211
212 fn morphed_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
215 render_device.create_bind_group_layout(
216 "morphed_mesh_layout",
217 &BindGroupLayoutEntries::with_indices(
218 ShaderStages::VERTEX,
219 (
220 (0, layout_entry::model(render_device)),
221 (2, layout_entry::weights()),
223 (3, layout_entry::targets()),
224 (7, layout_entry::weights()),
226 ),
227 ),
228 )
229 }
230
231 fn morphed_skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
234 render_device.create_bind_group_layout(
235 "morphed_skinned_mesh_layout",
236 &BindGroupLayoutEntries::with_indices(
237 ShaderStages::VERTEX,
238 (
239 (0, layout_entry::model(render_device)),
240 (1, layout_entry::skinning()),
242 (2, layout_entry::weights()),
244 (3, layout_entry::targets()),
245 ),
246 ),
247 )
248 }
249
250 fn morphed_skinned_motion_layout(render_device: &RenderDevice) -> BindGroupLayout {
253 render_device.create_bind_group_layout(
254 "morphed_skinned_motion_mesh_layout",
255 &BindGroupLayoutEntries::with_indices(
256 ShaderStages::VERTEX,
257 (
258 (0, layout_entry::model(render_device)),
259 (1, layout_entry::skinning()),
261 (2, layout_entry::weights()),
263 (3, layout_entry::targets()),
264 (6, layout_entry::skinning()),
266 (7, layout_entry::weights()),
268 ),
269 ),
270 )
271 }
272
273 fn lightmapped_layout(render_device: &RenderDevice) -> BindGroupLayout {
274 render_device.create_bind_group_layout(
275 "lightmapped_mesh_layout",
276 &BindGroupLayoutEntries::with_indices(
277 ShaderStages::VERTEX,
278 (
279 (0, layout_entry::model(render_device)),
280 (4, layout_entry::lightmaps_texture_view()),
281 (5, layout_entry::lightmaps_sampler()),
282 ),
283 ),
284 )
285 }
286
287 pub fn model_only(&self, render_device: &RenderDevice, model: &BindingResource) -> BindGroup {
290 render_device.create_bind_group(
291 "model_only_mesh_bind_group",
292 &self.model_only,
293 &[entry::model(0, model.clone())],
294 )
295 }
296
297 pub fn lightmapped(
298 &self,
299 render_device: &RenderDevice,
300 model: &BindingResource,
301 lightmap: &GpuImage,
302 ) -> BindGroup {
303 render_device.create_bind_group(
304 "lightmapped_mesh_bind_group",
305 &self.lightmapped,
306 &[
307 entry::model(0, model.clone()),
308 entry::lightmaps_texture_view(4, &lightmap.texture_view),
309 entry::lightmaps_sampler(5, &lightmap.sampler),
310 ],
311 )
312 }
313
314 pub fn skinned(
316 &self,
317 render_device: &RenderDevice,
318 model: &BindingResource,
319 current_skin: &Buffer,
320 ) -> BindGroup {
321 render_device.create_bind_group(
322 "skinned_mesh_bind_group",
323 &self.skinned,
324 &[
325 entry::model(0, model.clone()),
326 entry::skinning(1, current_skin),
327 ],
328 )
329 }
330
331 pub fn skinned_motion(
339 &self,
340 render_device: &RenderDevice,
341 model: &BindingResource,
342 current_skin: &Buffer,
343 prev_skin: &Buffer,
344 ) -> BindGroup {
345 render_device.create_bind_group(
346 "skinned_motion_mesh_bind_group",
347 &self.skinned_motion,
348 &[
349 entry::model(0, model.clone()),
350 entry::skinning(1, current_skin),
351 entry::skinning(6, prev_skin),
352 ],
353 )
354 }
355
356 pub fn morphed(
358 &self,
359 render_device: &RenderDevice,
360 model: &BindingResource,
361 current_weights: &Buffer,
362 targets: &TextureView,
363 ) -> BindGroup {
364 render_device.create_bind_group(
365 "morphed_mesh_bind_group",
366 &self.morphed,
367 &[
368 entry::model(0, model.clone()),
369 entry::weights(2, current_weights),
370 entry::targets(3, targets),
371 ],
372 )
373 }
374
375 pub fn morphed_motion(
383 &self,
384 render_device: &RenderDevice,
385 model: &BindingResource,
386 current_weights: &Buffer,
387 targets: &TextureView,
388 prev_weights: &Buffer,
389 ) -> BindGroup {
390 render_device.create_bind_group(
391 "morphed_motion_mesh_bind_group",
392 &self.morphed_motion,
393 &[
394 entry::model(0, model.clone()),
395 entry::weights(2, current_weights),
396 entry::targets(3, targets),
397 entry::weights(7, prev_weights),
398 ],
399 )
400 }
401
402 #[allow(clippy::too_many_arguments)]
404 pub fn morphed_skinned(
405 &self,
406 render_device: &RenderDevice,
407 model: &BindingResource,
408 current_skin: &Buffer,
409 current_weights: &Buffer,
410 targets: &TextureView,
411 ) -> BindGroup {
412 render_device.create_bind_group(
413 "morphed_skinned_mesh_bind_group",
414 &self.morphed_skinned,
415 &[
416 entry::model(0, model.clone()),
417 entry::skinning(1, current_skin),
418 entry::weights(2, current_weights),
419 entry::targets(3, targets),
420 ],
421 )
422 }
423
424 #[allow(clippy::too_many_arguments)]
432 pub fn morphed_skinned_motion(
433 &self,
434 render_device: &RenderDevice,
435 model: &BindingResource,
436 current_skin: &Buffer,
437 current_weights: &Buffer,
438 targets: &TextureView,
439 prev_skin: &Buffer,
440 prev_weights: &Buffer,
441 ) -> BindGroup {
442 render_device.create_bind_group(
443 "morphed_skinned_motion_mesh_bind_group",
444 &self.morphed_skinned_motion,
445 &[
446 entry::model(0, model.clone()),
447 entry::skinning(1, current_skin),
448 entry::weights(2, current_weights),
449 entry::targets(3, targets),
450 entry::skinning(6, prev_skin),
451 entry::weights(7, prev_weights),
452 ],
453 )
454 }
455}