gloss_renderer/forward_renderer/render_passes/
prepass.rs

1extern crate nalgebra as na;
2
3use crate::{
4    camera::Camera,
5    components::{
6        Colors, DiffuseTex, Edges, EnvironmentMapGpu, Faces, LightEmit, ModelMatrix, Name, NormalTex, Normals, Renderable, RoughnessTex,
7        ShadowCaster, ShadowMap, Tangents, UVs, Verts, VisLines, VisMesh, VisNormals, VisOutline, VisPoints, VisWireframe,
8    },
9    config::Config,
10    scene::Scene,
11};
12use easy_wgpu::{
13    gpu::Gpu,
14    texture::{TexParams, Texture},
15};
16use gloss_geometry::geom::{self, PerVertexNormalsWeightingType};
17use gloss_hecs::{Changed, CommandBuffer, Entity};
18use gloss_utils::{
19    bshare::{ToBurn, ToNalgebraFloat, ToNalgebraInt},
20    tensor::{DynamicTensorFloat2D, DynamicTensorInt2D, DynamicTensorOps},
21};
22use log::{debug, warn};
23/// Makes sure that the meshes are all with with correct components. Add model
24/// matrices to the ones that will be rendered and dummy textures so that we can
25/// use the same pipeline for all of them
26pub struct PrePass {
27    command_buffer: CommandBuffer, //defer insertions and deletion of scene entities for whenever we apply this command buffer
28}
29impl Default for PrePass {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34impl PrePass {
35    pub fn new() -> Self {
36        let command_buffer = CommandBuffer::new();
37        Self { command_buffer }
38    }
39
40    pub fn add_auto_components(&mut self, gpu: &Gpu, scene: &mut Scene) {
41        //this adds a lot of components automatically if they are needed
42        self.add_model_matrix(scene);
43        self.add_vertex_normals(scene);
44        self.command_buffer.run_on(&mut scene.world); //run the command buffer so now all entities actually have Normals, this is
45                                                      // necessary so that the add_tangents correctly computes tangents for all
46                                                      // entities which have Verts,Faces,Normals and UVs
47        self.add_tangents(scene); //keep before adding dummy uvs so if we don't have uvs we just add some dumym
48                                  // tangents
49        self.add_dummy_uvs(scene);
50        self.add_dummy_colors(scene);
51
52        self.add_dummy_diffuse_tex(scene, gpu);
53        self.add_dummy_normal_tex(scene, gpu);
54        self.add_dummy_roughness_tex(scene, gpu);
55        self.add_dummy_environment_map(scene, gpu);
56
57        //auto vis options depending on the components
58        self.add_vis_lines(scene);
59        self.add_vis_wireframe(scene);
60        self.add_vis_normals(scene);
61        self.add_vis_points(scene);
62        self.add_vis_mesh(scene);
63        self.add_vis_outline(scene);
64        self.command_buffer.run_on(&mut scene.world); //in order to actually
65                                                      // create the model matrix
66                                                      // so that adding lights
67                                                      // works
68    }
69
70    pub fn run(
71        &mut self,
72        gpu: &Gpu,
73        camera: &mut Camera,
74        scene: &mut Scene,
75        // width: u32,
76        // height: u32,
77        config: &mut Config,
78    ) {
79        self.begin_pass();
80
81        //sanity checks
82        self.check_entity_names(scene); //checks that all entities have names
83
84        //automatic camera and lights only on first render
85
86        //this adds a lot of components automatically if they are needed
87        self.add_auto_components(gpu, scene);
88
89        //if we have objects in the scene, make the config objects that were set to
90        // auto, to a value that is concrete
91        if !config.is_concrete() && scene.nr_renderables() != 0 {
92            scene.make_concrete_config(config);
93        }
94        if config.is_concrete() && !config.is_consumed() {
95            let (width, height) = camera.get_target_res(scene);
96            scene.from_config(config, width, height);
97            self.add_auto_components(gpu, scene); //whatever we now added in
98                                                  // the scene like lights,etc
99                                                  // might also need auto
100                                                  // components
101        }
102
103        //add new objects the first time we render like the floor and lights
104        //requires that the objects already have model_matrix
105        // if scene.get_lights(false).is_empty() && scene.get_renderables(false).len()
106        // != 0 {     scene.add_auto_lights();
107        // }
108        self.add_shadow_maps(scene, gpu);
109
110        // if !scene.has_floor() && scene.get_renderables(false).len() != 0 {
111        //     scene.add_floor();
112        // }
113
114        // //setup camera
115        // if !scene.world.has::<PosLookat>(camera.entity).unwrap()
116        //     && scene.get_renderables(false).len() != 0
117        // {
118        //     self.set_auto_cam(camera, scene);
119        // }
120
121        self.end_pass_sanity_check(scene);
122
123        self.end_pass(scene);
124    }
125
126    fn begin_pass(&self) {}
127
128    fn end_pass(&mut self, scene: &mut Scene) {
129        self.command_buffer.run_on(&mut scene.world);
130    }
131
132    fn check_entity_names(&mut self, scene: &mut Scene) {
133        let mut query = scene.world.query::<()>().without::<&Name>();
134        for (_entity, _comp) in query.iter() {
135            warn!("Entity does not have a name, please assign name to all of them");
136        }
137    }
138
139    fn add_vis_lines(&mut self, scene: &mut Scene) {
140        let mut query = scene.world.query::<Option<&Faces>>().with::<(&Verts, &Edges)>().without::<&VisLines>();
141        for (entity, faces) in query.iter() {
142            //we automatically enable vis_lines if we don't have faces so we have only
143            // edges component
144            let show_lines = faces.is_none();
145
146            self.command_buffer.insert_one(
147                entity,
148                VisLines {
149                    added_automatically: true,
150                    show_lines,
151                    ..Default::default()
152                },
153            );
154        }
155    }
156
157    fn add_vis_wireframe(&mut self, scene: &mut Scene) {
158        let mut query = scene.world.query::<()>().with::<(&Verts, &Faces)>().without::<&VisWireframe>();
159        for (entity, _comp) in query.iter() {
160            self.command_buffer.insert_one(
161                entity,
162                VisWireframe {
163                    added_automatically: true,
164                    ..Default::default()
165                },
166            );
167        }
168    }
169
170    fn add_vis_normals(&mut self, scene: &mut Scene) {
171        let mut query = scene.world.query::<()>().with::<(&Verts, &Normals)>().without::<&VisNormals>();
172        for (entity, _comp) in query.iter() {
173            self.command_buffer.insert_one(
174                entity,
175                VisNormals {
176                    added_automatically: true,
177                    ..Default::default()
178                },
179            );
180        }
181    }
182
183    fn add_vis_points(&mut self, scene: &mut Scene) {
184        let mut query = scene
185            .world
186            .query::<(Option<&Faces>, Option<&Edges>)>()
187            .with::<&Verts>()
188            .without::<&VisPoints>();
189        for (entity, (faces, edges)) in query.iter() {
190            //we automatically enable vis_points if we don't have faces or edges component
191            // and we have only verts
192            let show_points = faces.is_none() && edges.is_none();
193
194            self.command_buffer.insert_one(
195                entity,
196                VisPoints {
197                    added_automatically: true,
198                    show_points,
199                    ..Default::default()
200                },
201            );
202        }
203    }
204
205    fn add_vis_mesh(&mut self, scene: &mut Scene) {
206        let mut query = scene.world.query::<()>().with::<(&Verts, &Faces)>().without::<&VisMesh>();
207        for (entity, _comp) in query.iter() {
208            self.command_buffer.insert_one(
209                entity,
210                VisMesh {
211                    added_automatically: true,
212                    ..Default::default()
213                },
214            );
215        }
216    }
217
218    fn add_vis_outline(&mut self, scene: &mut Scene) {
219        let mut query = scene.world.query::<&Name>().with::<(&Verts, &Faces)>().without::<&VisOutline>();
220        for (entity, name) in query.iter() {
221            // don't add outline to floor
222            if name.0 == "floor" {
223                continue;
224            }
225            self.command_buffer.insert_one(
226                entity,
227                VisOutline {
228                    added_automatically: true,
229                    ..Default::default()
230                },
231            );
232        }
233    }
234
235    fn add_model_matrix(&mut self, scene: &mut Scene) {
236        let mut query = scene.world.query::<()>().with::<&Renderable>().without::<&ModelMatrix>();
237        for (entity, _comp) in query.iter() {
238            self.command_buffer.insert_one(entity, ModelMatrix::default());
239        }
240    }
241
242    fn add_vertex_normals(&mut self, scene: &mut Scene) {
243        // We panic if prepass sees Wgpu backend tensors for now and if faces and verts
244        // are on different backends
245        let insert_normals = |entity: Entity, verts: &Verts, faces: &Faces, command_buffer: &mut CommandBuffer| {
246            match (&verts.0, &faces.0) {
247                // Handle both NdArray variants
248                (DynamicTensorFloat2D::NdArray(verts_tensor), DynamicTensorInt2D::NdArray(faces_tensor)) => {
249                    let normals = geom::compute_per_vertex_normals(
250                        &verts_tensor.to_nalgebra(),
251                        &faces_tensor.to_nalgebra(),
252                        &PerVertexNormalsWeightingType::Area,
253                    );
254                    let normals_tensor = DynamicTensorFloat2D::NdArray(normals.into_burn(&verts_tensor.device()));
255                    command_buffer.insert_one(entity, Normals(normals_tensor));
256                }
257                // Let prepass support only NdArray since we dont really do any parallel computations
258                // Handle both Candle variants
259                (DynamicTensorFloat2D::Candle(verts_tensor), DynamicTensorInt2D::Candle(faces_tensor)) => {
260                    let normals = geom::compute_per_vertex_normals_burn(verts_tensor, faces_tensor, &PerVertexNormalsWeightingType::Area);
261                    let normals_tensor = DynamicTensorFloat2D::Candle(normals);
262                    command_buffer.insert_one(entity, Normals(normals_tensor));
263                }
264                // Panic for unsupported Wgpu backend
265                (DynamicTensorFloat2D::Wgpu(_), _) | (_, DynamicTensorInt2D::Wgpu(_)) => {
266                    panic!("Wgpu backend is not supported for the prepass! Make sure normals are being added in smpl-rs");
267                }
268                // Handle mismatched backends (e.g., one is NdArray and the other is Candle)
269                _ => {
270                    panic!(
271                        "Mismatched backends between verts and faces tensors! Faces - {:?} Verts - {:?}",
272                        &verts.0, &faces.0
273                    );
274                }
275            }
276        };
277
278        //add normals to all entities that have verts and faces but don't have Normals
279        let mut query = scene.world.query::<(&Verts, &Faces)>().with::<&Renderable>().without::<&Normals>();
280        for (entity, (verts, faces)) in query.iter() {
281            insert_normals(entity, verts, faces, &mut self.command_buffer);
282        }
283
284        //also all the entities that have verts,faces AND normals but the normals don't
285        // correspond in size to the verts this can happen when we update a
286        // entity with a different Verts and Faces but don't update the Normals for some
287        // reason
288        let mut query = scene.world.query::<(&Verts, &Faces, &Normals)>().with::<&Renderable>();
289        for (entity, (verts, faces, normals)) in query.iter() {
290            if verts.0.nrows() != normals.0.nrows() {
291                insert_normals(entity, verts, faces, &mut self.command_buffer);
292            }
293        }
294    }
295    #[allow(clippy::too_many_lines)]
296    fn add_tangents(&mut self, scene: &mut Scene) {
297        let insert_tangents = |entity: Entity, verts: &Verts, faces: &Faces, normals: &Normals, uvs: &UVs, command_buffer: &mut CommandBuffer| {
298            match (&verts.0, &faces.0, &normals.0, &uvs.0) {
299                // Handle both NdArray and dynamic backends
300                (
301                    DynamicTensorFloat2D::NdArray(verts_tensor),
302                    DynamicTensorInt2D::NdArray(faces_tensor),
303                    DynamicTensorFloat2D::NdArray(normals_tensor),
304                    DynamicTensorFloat2D::NdArray(uvs_tensor),
305                ) => {
306                    // Compute tangents for NdArray backend
307                    let tangents = geom::compute_tangents(
308                        &verts_tensor.to_nalgebra(),
309                        &faces_tensor.to_nalgebra(),
310                        &normals_tensor.to_nalgebra(),
311                        &uvs_tensor.to_nalgebra(),
312                    );
313                    let tangents_tensor = DynamicTensorFloat2D::NdArray(tangents.into_burn(&verts_tensor.device()));
314                    command_buffer.insert_one(entity, Tangents(tangents_tensor));
315                }
316                // Let prepass support only NdArray since we dont really do any parallel computations
317                // (
318                //     DynamicTensorFloat2D::Candle(verts_tensor),
319                //     DynamicTensorInt2D::Candle(faces_tensor),
320                //     DynamicTensorFloat2D::Candle(normals_tensor),
321                //     DynamicTensorFloat2D::Candle(uvs_tensor),
322                // ) => {
323                //     // Compute tangents for Candle backend
324                //     let tangents = geom::compute_tangents_burn(
325                //         verts_tensor,
326                //         faces_tensor,
327                //         normals_tensor,
328                //         uvs_tensor,
329                //     );
330                //     let tangents_tensor = DynamicTensorFloat2D::Candle(tangents);
331                //     command_buffer.insert_one(entity, Tangents(tangents_tensor));
332                // }
333                _ => {
334                    panic!("Unsupported backend combination for tangents calculation!");
335                }
336            }
337        };
338
339        //all the entities that have verts, faces, normals and uvs but NO tangents
340        let mut query = scene
341            .world
342            .query::<(&Verts, &Faces, &Normals, &UVs)>()
343            .with::<&Renderable>()
344            .without::<&Tangents>();
345        for (entity, (verts, faces, normals, uvs)) in query.iter() {
346            insert_tangents(entity, verts, faces, normals, uvs, &mut self.command_buffer);
347        }
348
349        //also all the entities that have verts,faces, normals,uvs AND tangents but the
350        // tangents don't correspond in size to the verts this can happen when
351        // we update a entity with a different Verts and Faces but don't update the
352        // Tangents for some reason
353        let mut query = scene.world.query::<(&Verts, &Faces, &Normals, &UVs, &Tangents)>().with::<&Renderable>();
354        for (entity, (verts, faces, normals, uvs, tangents)) in query.iter() {
355            if verts.0.nrows() != tangents.0.nrows() {
356                insert_tangents(entity, verts, faces, normals, uvs, &mut self.command_buffer);
357            }
358        }
359
360        //if we don't have real uvs then we add dummy tangents and the next function
361        // will also just add dummy uvs
362        let mut query = scene.world.query::<(&Verts, &Faces)>().with::<&Renderable>().without::<&UVs>();
363        for (entity, (verts, _faces)) in query.iter() {
364            // Match the backend of verts
365            match &verts.0 {
366                DynamicTensorFloat2D::NdArray(verts_tensor) => {
367                    // Compute tangents using the NdArray backend
368                    let tangents = geom::compute_dummy_tangents(verts_tensor.dims()[0], &verts_tensor.device());
369                    let tangents_tensor = DynamicTensorFloat2D::NdArray(tangents);
370                    self.command_buffer.insert_one(entity, Tangents(tangents_tensor));
371                }
372                DynamicTensorFloat2D::Candle(verts_tensor) => {
373                    // Compute tangents using the Candle backend
374                    let tangents = geom::compute_dummy_tangents(verts_tensor.dims()[0], &verts_tensor.device());
375                    let tangents_tensor = DynamicTensorFloat2D::Candle(tangents);
376                    self.command_buffer.insert_one(entity, Tangents(tangents_tensor));
377                }
378                DynamicTensorFloat2D::Wgpu(verts_tensor) => {
379                    // Compute tangents using the Wgpu backend
380                    let tangents = geom::compute_dummy_tangents(verts_tensor.dims()[0], &verts_tensor.device());
381                    let tangents_tensor = DynamicTensorFloat2D::Wgpu(tangents);
382                    self.command_buffer.insert_one(entity, Tangents(tangents_tensor));
383                }
384            }
385        }
386
387        // If we have verts, faces, NO uvs but we do have tangents, make sure the
388        // tangents have the same size as verts
389        let mut query = scene.world.query::<(&Verts, &Faces, &Tangents)>().with::<&Renderable>().without::<&UVs>();
390
391        for (entity, (verts, _faces, tangents)) in query.iter() {
392            if verts.0.nrows() != tangents.0.nrows() {
393                match &verts.0 {
394                    DynamicTensorFloat2D::NdArray(verts_tensor) => {
395                        // Compute tangents using the NdArray backend
396                        let tangents = geom::compute_dummy_tangents(verts_tensor.dims()[0], &verts_tensor.device());
397                        let tangents_tensor = DynamicTensorFloat2D::NdArray(tangents);
398                        self.command_buffer.insert_one(entity, Tangents(tangents_tensor));
399                    }
400                    DynamicTensorFloat2D::Candle(verts_tensor) => {
401                        // Compute tangents using the Candle backend
402                        let tangents = geom::compute_dummy_tangents(verts_tensor.dims()[0], &verts_tensor.device());
403                        let tangents_tensor = DynamicTensorFloat2D::Candle(tangents);
404                        self.command_buffer.insert_one(entity, Tangents(tangents_tensor));
405                    }
406                    DynamicTensorFloat2D::Wgpu(verts_tensor) => {
407                        // Compute tangents using the Wgpu backend
408                        let tangents = geom::compute_dummy_tangents(verts_tensor.dims()[0], &verts_tensor.device());
409                        let tangents_tensor = DynamicTensorFloat2D::Wgpu(tangents);
410                        self.command_buffer.insert_one(entity, Tangents(tangents_tensor));
411                    }
412                }
413            }
414        }
415    }
416
417    // fn add_dummy_uvs(&mut self, scene: &mut Scene) {
418    //     //add dummy uvs if we don't have them
419    //     let mut query = scene
420    //         .world
421    //         .query::<(&Verts, &Faces)>()
422    //         .with::<&Renderable>()
423    //         .without::<&UVs>();
424    //     for (entity, (verts, _faces)) in query.iter() {
425    //         let uvs = geom::compute_dummy_uvs(verts.0.nrows());
426    //         let uvs_tensor = DynamicTensorFloat2D::NdArray(uvs);
427    //         self.command_buffer.insert_one(entity, UVs(uvs_tensor));
428    //     }
429
430    //     //if we do have uvs, we make sure that they are the same size
431    //     let mut query = scene
432    //         .world
433    //         .query::<(&Verts, &Faces, &UVs)>()
434    //         .with::<&Renderable>();
435    //     for (entity, (verts, _faces, uvs)) in query.iter() {
436    //         if verts.0.nrows() != uvs.0.nrows() {
437    //             let uvs = geom::compute_dummy_uvs(verts.0.nrows());
438    //             let uvs_tensor = DynamicTensorFloat2D::NdArray(uvs);
439    //             self.command_buffer.insert_one(entity, UVs(uvs_tensor));
440    //         }
441    //     }
442    // }
443    fn add_dummy_uvs(&mut self, scene: &mut Scene) {
444        // Add dummy uvs if we don't have them
445        let mut query = scene.world.query::<(&Verts, &Faces)>().with::<&Renderable>().without::<&UVs>();
446
447        for (entity, (verts, _faces)) in query.iter() {
448            match &verts.0 {
449                DynamicTensorFloat2D::NdArray(verts_tensor) => {
450                    // Compute dummy uvs for NdArray backend
451                    let uvs = geom::compute_dummy_uvs(verts_tensor.dims()[0], &verts_tensor.device());
452                    let uvs_tensor = DynamicTensorFloat2D::NdArray(uvs);
453                    self.command_buffer.insert_one(entity, UVs(uvs_tensor));
454                }
455                DynamicTensorFloat2D::Candle(verts_tensor) => {
456                    // Compute dummy uvs for Candle backend
457                    let uvs = geom::compute_dummy_uvs(verts_tensor.dims()[0], &verts_tensor.device());
458                    let uvs_tensor = DynamicTensorFloat2D::Candle(uvs);
459                    self.command_buffer.insert_one(entity, UVs(uvs_tensor));
460                }
461                DynamicTensorFloat2D::Wgpu(verts_tensor) => {
462                    // Compute dummy uvs for Wgpu backend
463                    let uvs = geom::compute_dummy_uvs(verts_tensor.dims()[0], &verts_tensor.device());
464                    let uvs_tensor = DynamicTensorFloat2D::Wgpu(uvs);
465                    self.command_buffer.insert_one(entity, UVs(uvs_tensor));
466                }
467            }
468        }
469
470        // If we do have uvs, make sure that they are the same size
471        let mut query = scene.world.query::<(&Verts, &Faces, &UVs)>().with::<&Renderable>();
472
473        for (entity, (verts, _faces, uvs)) in query.iter() {
474            if verts.0.nrows() != uvs.0.nrows() {
475                match &verts.0 {
476                    DynamicTensorFloat2D::NdArray(verts_tensor) => {
477                        // Recompute uvs for NdArray backend
478                        let uvs = geom::compute_dummy_uvs(verts_tensor.dims()[0], &verts_tensor.device());
479                        let uvs_tensor = DynamicTensorFloat2D::NdArray(uvs);
480                        self.command_buffer.insert_one(entity, UVs(uvs_tensor));
481                    }
482                    DynamicTensorFloat2D::Candle(verts_tensor) => {
483                        // Recompute uvs for Candle backend
484                        let uvs = geom::compute_dummy_uvs(verts_tensor.dims()[0], &verts_tensor.device());
485                        let uvs_tensor = DynamicTensorFloat2D::Candle(uvs);
486                        self.command_buffer.insert_one(entity, UVs(uvs_tensor));
487                    }
488                    DynamicTensorFloat2D::Wgpu(verts_tensor) => {
489                        // Recompute uvs for Wgpu backend
490                        let uvs = geom::compute_dummy_uvs(verts_tensor.dims()[0], &verts_tensor.device());
491                        let uvs_tensor = DynamicTensorFloat2D::Wgpu(uvs);
492                        self.command_buffer.insert_one(entity, UVs(uvs_tensor));
493                    }
494                }
495            }
496        }
497    }
498
499    // fn add_dummy_colors(&mut self, scene: &mut Scene) {
500    //     //we add dummy colors if we don't have them
501    //     let mut query = scene
502    //         .world
503    //         .query::<&Verts>()
504    //         .with::<&Renderable>()
505    //         .without::<&Colors>();
506    //     for (entity, verts) in query.iter() {
507    //         let colors = geom::compute_dummy_colors(verts.0.nrows());
508    //         let colors_tensor = DynamicTensorFloat2D::NdArray(colors);
509    //         self.command_buffer
510    //             .insert_one(entity, Colors(colors_tensor));
511    //     }
512    //     //if we do have colors, we make sure they are the same size as verts
513    //     let mut query = scene
514    //         .world
515    //         .query::<(&Verts, &Colors)>()
516    //         .with::<&Renderable>();
517    //     for (entity, (verts, colors)) in query.iter() {
518    //         if verts.0.nrows() != colors.0.nrows() {
519    //             let colors = geom::compute_dummy_colors(verts.0.nrows());
520    //             let colors_tensor = DynamicTensorFloat2D::NdArray(colors);
521    //             self.command_buffer
522    //                 .insert_one(entity, Colors(colors_tensor));
523    //         }
524    //     }
525    // }
526    fn add_dummy_colors(&mut self, scene: &mut Scene) {
527        // We add dummy colors if we don't have them
528        let mut query = scene.world.query::<&Verts>().with::<&Renderable>().without::<&Colors>();
529
530        for (entity, verts) in query.iter() {
531            match &verts.0 {
532                DynamicTensorFloat2D::NdArray(verts_tensor) => {
533                    // Compute dummy colors for NdArray backend
534                    let colors = geom::compute_dummy_colors(verts_tensor.dims()[0], &verts_tensor.device());
535                    let colors_tensor = DynamicTensorFloat2D::NdArray(colors);
536                    self.command_buffer.insert_one(entity, Colors(colors_tensor));
537                }
538                DynamicTensorFloat2D::Candle(verts_tensor) => {
539                    // Compute dummy colors for Candle backend
540                    let colors = geom::compute_dummy_colors(verts_tensor.dims()[0], &verts_tensor.device());
541                    let colors_tensor = DynamicTensorFloat2D::Candle(colors);
542                    self.command_buffer.insert_one(entity, Colors(colors_tensor));
543                }
544                DynamicTensorFloat2D::Wgpu(verts_tensor) => {
545                    // Compute dummy colors for Wgpu backend
546                    let colors = geom::compute_dummy_colors(verts_tensor.dims()[0], &verts_tensor.device());
547                    let colors_tensor = DynamicTensorFloat2D::Wgpu(colors);
548                    self.command_buffer.insert_one(entity, Colors(colors_tensor));
549                }
550            }
551        }
552
553        // If we do have colors, make sure they are the same size as verts
554        let mut query = scene.world.query::<(&Verts, &Colors)>().with::<&Renderable>();
555
556        for (entity, (verts, colors)) in query.iter() {
557            if verts.0.nrows() != colors.0.nrows() {
558                match &verts.0 {
559                    DynamicTensorFloat2D::NdArray(verts_tensor) => {
560                        // Recompute colors for NdArray backend
561                        let colors = geom::compute_dummy_colors(verts_tensor.dims()[0], &verts_tensor.device());
562                        let colors_tensor = DynamicTensorFloat2D::NdArray(colors);
563                        self.command_buffer.insert_one(entity, Colors(colors_tensor));
564                    }
565                    DynamicTensorFloat2D::Candle(verts_tensor) => {
566                        // Recompute colors for Candle backend
567                        let colors = geom::compute_dummy_colors(verts_tensor.dims()[0], &verts_tensor.device());
568                        let colors_tensor = DynamicTensorFloat2D::Candle(colors);
569                        self.command_buffer.insert_one(entity, Colors(colors_tensor));
570                    }
571                    DynamicTensorFloat2D::Wgpu(verts_tensor) => {
572                        // Recompute colors for Wgpu backend
573                        let colors = geom::compute_dummy_colors(verts_tensor.dims()[0], &verts_tensor.device());
574                        let colors_tensor = DynamicTensorFloat2D::Wgpu(colors);
575                        self.command_buffer.insert_one(entity, Colors(colors_tensor));
576                    }
577                }
578            }
579        }
580    }
581
582    fn add_dummy_diffuse_tex(&mut self, scene: &mut Scene, gpu: &Gpu) {
583        let mut query = scene.world.query::<()>().with::<&Renderable>().without::<&DiffuseTex>();
584        for (entity, _comp) in query.iter() {
585            let tex = Texture::create_default_texture(gpu.device(), gpu.queue());
586            self.command_buffer.insert_one(entity, DiffuseTex(tex));
587        }
588    }
589
590    fn add_dummy_normal_tex(&mut self, scene: &mut Scene, gpu: &Gpu) {
591        let mut query = scene.world.query::<()>().with::<&Renderable>().without::<&NormalTex>();
592        for (entity, _comp) in query.iter() {
593            let tex = Texture::create_default_texture(gpu.device(), gpu.queue());
594            self.command_buffer.insert_one(entity, NormalTex(tex));
595        }
596    }
597
598    fn add_dummy_roughness_tex(&mut self, scene: &mut Scene, gpu: &Gpu) {
599        let mut query = scene.world.query::<()>().with::<&Renderable>().without::<&RoughnessTex>();
600        for (entity, _comp) in query.iter() {
601            let tex = Texture::create_default_texture(gpu.device(), gpu.queue());
602            self.command_buffer.insert_one(entity, RoughnessTex(tex));
603        }
604    }
605
606    fn add_dummy_environment_map(&mut self, scene: &mut Scene, gpu: &Gpu) {
607        //environment map
608        if !scene.has_resource::<EnvironmentMapGpu>() {
609            let env = EnvironmentMapGpu::new_dummy(gpu.device(), gpu.queue());
610            scene.add_resource(env);
611        }
612    }
613
614    //creates a new shadow map for all the lights that have the shadowcasting
615    // component
616    fn add_shadow_maps(&mut self, scene: &mut Scene, gpu: &Gpu) {
617        let mut query = scene
618            .world
619            .query::<(&ShadowCaster, Changed<ShadowCaster>, Option<&ShadowMap>)>()
620            .with::<&LightEmit>();
621
622        for (entity, (shadow_caster, is_shadow_changed, shadow_map)) in query.iter() {
623            if is_shadow_changed || shadow_map.is_none() {
624                debug!(
625                    "creating shadow map, because is_shadow_changed {} or shadow_map.is_none() {}",
626                    is_shadow_changed,
627                    shadow_map.is_none()
628                );
629                let tex_depth = easy_wgpu::texture::Texture::new(
630                    gpu.device(),
631                    shadow_caster.shadow_res,
632                    shadow_caster.shadow_res,
633                    wgpu::TextureFormat::Depth32Float,
634                    wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
635                    TexParams::default(),
636                );
637                // let tex_depth_moments = easy_wgpu::texture::Texture::new(
638                //     gpu.device(),
639                //     shadow_caster.shadow_res,
640                //     shadow_caster.shadow_res,
641                //     wgpu::TextureFormat::Rg32Float,
642                //     wgpu::TextureUsages::RENDER_ATTACHMENT |
643                // wgpu::TextureUsages::TEXTURE_BINDING, );
644                self.command_buffer.insert_one(
645                    entity,
646                    ShadowMap {
647                        tex_depth,
648                        // tex_depth_moments,
649                    },
650                );
651            }
652        }
653    }
654
655    fn end_pass_sanity_check(&mut self, scene: &mut Scene) {
656        //check that entities that have verts and colors, have the same number of
657        // vertices and colors
658        let mut query = scene.world.query::<(&Verts, &Colors)>();
659        for (_entity, (verts, colors)) in query.iter() {
660            assert!(
661                verts.0.shape() == colors.0.shape(),
662                "verts is {:?} and colors is{:?}",
663                verts.0.shape(),
664                colors.0.shape()
665            );
666        }
667    }
668
669    // fn set_auto_cam(&mut self, cam: &mut Camera, scene: &mut Scene) {
670    //     let scale = scene.get_scale();
671    //     let centroid = scene.get_centroid();
672
673    //     //get all the automatic values we can get
674    //     let position = centroid
675    //         + na::Vector3::z_axis().scale(2.0 * scale)
676    //         + na::Vector3::y_axis().scale(0.5 * scale);
677    //     let near = (centroid - position).norm() * 0.01;
678    //     let far = (centroid - position).norm() * 1000.0; //far plane can be quite
679    // big. The near plane shouldn't be too tiny because it make the depth have very
680    // little precision
681
682    //     //add a pos lookat
683    //     scene
684    //         .world
685    //         .insert(cam.entity, (PosLookat::new(position, centroid),))
686    //         .unwrap();
687    //     //modify also the near and far
688    //     let mut cam_proj = scene.world.get::<&mut
689    // Projection>(cam.entity).unwrap();     cam_proj.near = near;
690    //     cam_proj.far = far;
691    // }
692}