use super::super::types::MaterialTextures;
use super::{MaterialBindGroupContext, MeshPass};
impl MeshPass {
pub(in super::super) fn create_material_bind_group(
device: &wgpu::Device,
material_id: u32,
cache_key: &MaterialTextures,
ctx: &MaterialBindGroupContext,
) -> (wgpu::BindGroup, MaterialTextures) {
let mut found_textures = MaterialTextures::default();
let (base_texture_view, base_sampler) = if let Some(ref name) = cache_key.base_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.base_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_white_view, ctx.dummy_sampler)
};
let (emissive_texture_view, emissive_sampler) = if let Some(ref name) =
cache_key.emissive_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.emissive_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_black_view, ctx.dummy_sampler)
};
let (normal_texture_view, normal_sampler) = if let Some(ref name) = cache_key.normal_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.normal_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_normal_view, ctx.dummy_sampler)
};
let (metallic_roughness_texture_view, metallic_roughness_sampler) = if let Some(ref name) =
cache_key.metallic_roughness_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.metallic_roughness_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_white_view, ctx.dummy_sampler)
};
let (occlusion_texture_view, occlusion_sampler) = if let Some(ref name) =
cache_key.occlusion_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.occlusion_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_white_view, ctx.dummy_sampler)
};
let (transmission_texture_view, transmission_sampler) = if let Some(ref name) =
cache_key.transmission_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.transmission_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_white_view, ctx.dummy_sampler)
};
let (thickness_texture_view, thickness_sampler) = if let Some(ref name) =
cache_key.thickness_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.thickness_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_white_view, ctx.dummy_sampler)
};
let (specular_texture_view, specular_sampler) = if let Some(ref name) =
cache_key.specular_texture
&& let Some((view, sampler)) = ctx.registered_textures.get(name)
{
found_textures.specular_texture = Some(name.clone());
(view, sampler)
} else {
(ctx.dummy_white_view, ctx.dummy_sampler)
};
let bind_group_entries = vec![
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(base_texture_view),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(base_sampler),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::TextureView(emissive_texture_view),
},
wgpu::BindGroupEntry {
binding: 3,
resource: wgpu::BindingResource::Sampler(emissive_sampler),
},
wgpu::BindGroupEntry {
binding: 4,
resource: wgpu::BindingResource::TextureView(normal_texture_view),
},
wgpu::BindGroupEntry {
binding: 5,
resource: wgpu::BindingResource::Sampler(normal_sampler),
},
wgpu::BindGroupEntry {
binding: 6,
resource: wgpu::BindingResource::TextureView(metallic_roughness_texture_view),
},
wgpu::BindGroupEntry {
binding: 7,
resource: wgpu::BindingResource::Sampler(metallic_roughness_sampler),
},
wgpu::BindGroupEntry {
binding: 8,
resource: wgpu::BindingResource::TextureView(occlusion_texture_view),
},
wgpu::BindGroupEntry {
binding: 9,
resource: wgpu::BindingResource::Sampler(occlusion_sampler),
},
wgpu::BindGroupEntry {
binding: 10,
resource: wgpu::BindingResource::TextureView(transmission_texture_view),
},
wgpu::BindGroupEntry {
binding: 11,
resource: wgpu::BindingResource::Sampler(transmission_sampler),
},
wgpu::BindGroupEntry {
binding: 12,
resource: wgpu::BindingResource::TextureView(thickness_texture_view),
},
wgpu::BindGroupEntry {
binding: 13,
resource: wgpu::BindingResource::Sampler(thickness_sampler),
},
wgpu::BindGroupEntry {
binding: 14,
resource: wgpu::BindingResource::TextureView(specular_texture_view),
},
wgpu::BindGroupEntry {
binding: 15,
resource: wgpu::BindingResource::Sampler(specular_sampler),
},
];
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some(&format!("Material {} Texture Bind Group", material_id)),
layout: ctx.texture_bind_group_layout,
entries: &bind_group_entries,
});
(bind_group, found_textures)
}
pub(in super::super) fn refresh_material_bind_groups_for_world(
&mut self,
device: &wgpu::Device,
) {
let world_state = match self.world_states.get(&self.current_world_id) {
Some(state) => state,
None => return,
};
if world_state.material_bind_group_cache_key.is_empty() {
return;
}
let material_ids_to_refresh: Vec<u32> = world_state
.material_bind_group_cache_key
.iter()
.filter(|&(&material_id, cache_key)| {
let prev_found = world_state
.material_bind_group_found_textures
.get(&material_id)
.cloned()
.unwrap_or_default();
cache_key.has_newly_available_textures(&prev_found, &self.registered_textures)
})
.map(|(&id, _)| id)
.collect();
if material_ids_to_refresh.is_empty() {
return;
}
let ctx = MaterialBindGroupContext {
registered_textures: &self.registered_textures,
dummy_white_view: &self.dummy_white_view,
dummy_black_view: &self.dummy_black_view,
dummy_normal_view: &self.dummy_normal_view,
dummy_sampler: &self.dummy_sampler,
texture_bind_group_layout: &self.texture_bind_group_layout,
};
let world_state = self.world_states.get_mut(&self.current_world_id).unwrap();
for material_id in material_ids_to_refresh {
let cache_key = world_state
.material_bind_group_cache_key
.get(&material_id)
.cloned()
.unwrap();
let (bind_group, found_textures) =
Self::create_material_bind_group(device, material_id, &cache_key, &ctx);
world_state
.material_bind_groups
.insert(material_id, bind_group);
world_state
.material_bind_group_found_textures
.insert(material_id, found_textures);
}
}
}