Build / refresh per-node material bind groups for the scene pipeline. Must be called every frame after `prepare` and before `render`. Only rebuilds when a material changed (mat_dirty).
(&mut self, renderer: &crate::renderer::Renderer)
| 930 | /// pipeline. Must be called every frame after `prepare` and before |
| 931 | /// `render`. Only rebuilds when a material changed (mat_dirty). |
| 932 | pub fn prepare_materials(&mut self, renderer: &crate::renderer::Renderer) { |
| 933 | for (_handle, node) in self.nodes.iter_mut() { |
| 934 | if !node.visible || node.indices.is_empty() { |
| 935 | continue; |
| 936 | } |
| 937 | if node.mat_dirty || node.gpu_material_bg.is_none() { |
| 938 | // Allocate or reuse the per-material uniform buffer. |
| 939 | // (Could be updated in place when factors change, but |
| 940 | // the current path always rebuilds together with the |
| 941 | // bind group — cheap and simpler.) |
| 942 | let uniform = renderer.create_scene_material_uniform( |
| 943 | node.material.metalness, |
| 944 | node.material.roughness, |
| 945 | node.material.emissive, |
| 946 | node.material.metallic_roughness_texture_idx != 0, |
| 947 | // Scene-graph materials don't yet carry an alpha |
| 948 | // mode — user code builds them via setMaterial(), |
| 949 | // not from glTF. Default to OPAQUE. |
| 950 | 0.0, |
| 951 | ); |
| 952 | let bg = renderer.create_scene_material_bg( |
| 953 | node.material.texture_idx, |
| 954 | node.material.normal_texture_idx, |
| 955 | node.material.metallic_roughness_texture_idx, |
| 956 | node.material.emissive_texture_idx, |
| 957 | node.material.occlusion_texture_idx, |
| 958 | &uniform, |
| 959 | ); |
| 960 | node.gpu_material_bg = Some(bg); |
| 961 | node.gpu_material_uniform_buf = Some(uniform); |
| 962 | node.mat_dirty = false; |
| 963 | } |
| 964 | } |
| 965 | } |
| 966 | |
| 967 | /// Render all visible scene nodes into the given render pass. |
| 968 | /// Must be called after prepare() and after the pipeline/lighting/joints are set. |
no test coverage detected