fix(render): hide native zero-alpha MSH batches
Docs Deploy / Build and Deploy MkDocs (push) Successful in 1m43s

This commit is contained in:
Valentin Popov committed 2026-10-30 23:16:31 +04:00
1 parent eaf5df3ad0
commit 048ad71f5c
9 files changed
+234 -12

No files matched your search

+87 -3
View File
@@ -1053,6 +1053,13 @@ fn native_world_transparent(range: &VulkanStaticDrawRange, diffuse_alpha: f32) -
diffuse_alpha < 1.0 || (range.batch_flags & 0x108) != 0
}
fn native_msh_diffuse_alpha_override(batch_flags: u16, type16_present: bool) -> Option<f32> {
if type16_present || batch_flags & 0x0008 == 0 {
return None;
}
(batch_flags & 0x0040 != 0 && batch_flags & 0x0010 == 0).then_some(0.0)
}
fn native_msh_handedness(transform: LegacyIron3dEulerTransform, scale: [f32; 3]) -> i8 {
let Some(origin) = transform.try_transform_scaled_point([0.0; 3], scale) else {
return 0;
@@ -2273,6 +2280,7 @@ impl EnvironmentGpuScene {
fn new(
mesh: &mut VulkanStaticMesh,
native_handedness_by_range: &mut HashMap<usize, i8>,
type16_present_ranges: &mut HashSet<usize>,
materials: &mut Vec<VulkanStaticMaterial>,
preview_material_animations: &mut Vec<MaterialAnimationBinding>,
sun_occlusion_range_indices: &mut Vec<usize>,
@@ -2700,6 +2708,15 @@ impl EnvironmentGpuScene {
remapped_handedness.insert(new_range_index, handedness);
}
*native_handedness_by_range = remapped_handedness;
let mut remapped_type16_present_ranges =
HashSet::with_capacity(type16_present_ranges.len());
for old_range_index in std::mem::take(type16_present_ranges) {
let new_range_index = remap.get(old_range_index).copied().ok_or_else(|| {
format!("type-16 MSH draw range remap is missing range {old_range_index}")
})?;
remapped_type16_present_ranges.insert(new_range_index);
}
*type16_present_ranges = remapped_type16_present_ranges;
for layer in &mut scene.sky_layers {
layer.range.range_index = *remap
.get(layer.range.range_index)
@@ -3965,6 +3982,7 @@ fn multiply_row_major(left: [f32; 16], right: [f32; 16]) -> [f32; 16] {
struct StaticPreviewScene {
mesh: VulkanStaticMesh,
native_handedness_by_range: HashMap<usize, i8>,
type16_present_ranges: HashSet<usize>,
materials: Vec<VulkanStaticMaterial>,
material_animations: Vec<MaterialAnimationBinding>,
sun_occlusion_range_indices: Vec<usize>,
@@ -4401,6 +4419,7 @@ fn static_preview_mesh_and_materials(
draw_ranges: Vec::new(),
};
let mut native_handedness_by_range = HashMap::new();
let mut type16_present_ranges = HashSet::new();
let mut materials = Vec::new();
let mut material_animations = Vec::new();
let mut sun_occlusion_range_indices = Vec::new();
@@ -4768,6 +4787,9 @@ fn static_preview_mesh_and_materials(
)?;
for range_index in range_start..mesh.draw_ranges.len() {
native_handedness_by_range.insert(range_index, component_handedness);
if model.validated.type16_present {
type16_present_ranges.insert(range_index);
}
}
if root_sun_eligible {
sun_occlusion_range_indices.extend(range_start..mesh.draw_ranges.len());
@@ -4842,6 +4864,7 @@ fn static_preview_mesh_and_materials(
Ok(StaticPreviewScene {
mesh,
native_handedness_by_range,
type16_present_ranges,
materials,
material_animations,
sun_occlusion_range_indices,
@@ -5562,6 +5585,7 @@ fn run_static_vulkan_mode(
Some(EnvironmentGpuScene::new(
&mut preview.mesh,
&mut preview.native_handedness_by_range,
&mut preview.type16_present_ranges,
&mut preview.materials,
&mut preview.material_animations,
&mut preview.sun_occlusion_range_indices,
@@ -5677,6 +5701,7 @@ fn replay_environment_delta_seconds(last_applied_ms: u32, current_ms: u32) -> f3
struct StaticVulkanApp {
mesh: VulkanStaticMesh,
native_handedness_by_range: HashMap<usize, i8>,
type16_present_ranges: HashSet<usize>,
materials: Vec<VulkanStaticMaterial>,
material_animations: Vec<MaterialAnimationBinding>,
sun_occlusion_range_indices: Vec<usize>,
@@ -5765,6 +5790,7 @@ impl StaticVulkanApp {
Self {
mesh: preview.mesh,
native_handedness_by_range: preview.native_handedness_by_range,
type16_present_ranges: preview.type16_present_ranges,
materials: preview.materials,
material_animations: preview.material_animations,
sun_occlusion_range_indices: preview.sun_occlusion_range_indices,
@@ -5832,7 +5858,17 @@ impl StaticVulkanApp {
.materials
.get(usize::from(range.material_index))
.map_or(1.0, |material| material.diffuse_alpha);
let transparent = native_world_transparent(range, alpha);
let alpha_override = native_msh_diffuse_alpha_override(
range.batch_flags,
self.type16_present_ranges.contains(&range_index),
);
let effective_alpha = alpha_override.unwrap_or(alpha);
renderer
.set_draw_range_diffuse_alpha_override(range_index, alpha_override)
.map_err(|error| {
format!("configure world draw range {range_index} alpha: {error}")
})?;
let transparent = native_world_transparent(range, effective_alpha);
renderer
.set_draw_range_transparency(range_index, transparent)
.map_err(|error| format!("configure world draw range {range_index}: {error}"))?;
@@ -5853,7 +5889,7 @@ impl StaticVulkanApp {
&self.mesh,
range,
range.index_count,
alpha,
effective_alpha,
self.view_camera.position,
self.native_handedness_by_range.get(&range_index).copied(),
),
@@ -5869,6 +5905,7 @@ impl StaticVulkanApp {
mesh: &VulkanStaticMesh,
materials: &[VulkanStaticMaterial],
world_range_indices: &[usize],
type16_present_ranges: &HashSet<usize>,
world_range_index_counts: &HashMap<usize, u32>,
native_handedness_by_range: &HashMap<usize, i8>,
eye_world: [f32; 3],
@@ -5881,7 +5918,7 @@ impl StaticVulkanApp {
.get(range_index)
.ok_or_else(|| "world draw range index is out of bounds".to_string())?;
let state = active_materials.get(&range_index);
let alpha = state.map_or_else(
let material_alpha = state.map_or_else(
|| {
materials
.get(usize::from(range.material_index))
@@ -5889,6 +5926,14 @@ impl StaticVulkanApp {
},
|state| state.diffuse_alpha,
);
let alpha_override = native_msh_diffuse_alpha_override(
range.batch_flags,
type16_present_ranges.contains(&range_index),
);
let alpha = alpha_override.unwrap_or(material_alpha);
renderer
.set_draw_range_diffuse_alpha_override(range_index, alpha_override)
.map_err(|error| format!("update world draw range {range_index} alpha: {error}"))?;
renderer
.set_draw_range_transparency(range_index, native_world_transparent(range, alpha))
.map_err(|error| format!("update world draw range {range_index}: {error}"))?;
@@ -6322,6 +6367,7 @@ impl StaticVulkanApp {
&self.mesh,
&self.materials,
&self.world_range_indices,
&self.type16_present_ranges,
&self.world_range_index_counts,
&self.native_handedness_by_range,
frame.camera.position,
@@ -7342,6 +7388,7 @@ mod tests {
normals: None,
uv0: None,
uv1: None,
type16_present: false,
indices: vec![],
batches: vec![],
triangle_descriptors: None,
@@ -7671,6 +7718,7 @@ mod tests {
let preview = StaticPreviewScene {
mesh: initial_mesh.clone(),
native_handedness_by_range: HashMap::new(),
type16_present_ranges: HashSet::new(),
materials: Vec::new(),
material_animations: Vec::new(),
sun_occlusion_range_indices: Vec::new(),
@@ -8241,6 +8289,17 @@ mod tests {
));
}
#[test]
fn native_cpu_shaded_msh_alpha_override_uses_only_the_constant_batch_rule() {
assert_eq!(native_msh_diffuse_alpha_override(0x0148, false), Some(0.0));
assert_eq!(native_msh_diffuse_alpha_override(0x0108, false), None);
assert_eq!(native_msh_diffuse_alpha_override(0x0118, false), None);
assert_eq!(native_msh_diffuse_alpha_override(0x0058, false), None);
assert_eq!(native_msh_diffuse_alpha_override(0x0148, true), None);
assert_eq!(native_msh_diffuse_alpha_override(0x0058, true), None);
assert_eq!(native_msh_diffuse_alpha_override(0x0040, false), None);
}
#[test]
fn material_animation_selects_pipeline_category_with_active_phase() {
let variant = MaterialVariantSet {
@@ -10009,4 +10068,29 @@ mod tests {
original_count
);
}
#[test]
fn world_draw_range_count_clears_and_reapplies_constant_alpha_override() {
let triangle = native_front_triangle();
let (mesh, mut range) = facing_mesh(0x0148, &triangle);
let original_count = range.index_count;
let mut alpha_override = None;
let update = |range: &VulkanStaticDrawRange, alpha_override: &mut Option<f32>| {
*alpha_override = native_msh_diffuse_alpha_override(range.batch_flags, false);
world_draw_range_index_count(
&mesh,
range,
original_count,
alpha_override.unwrap_or(1.0),
[0.0; 3],
None,
)
};
assert_eq!(update(&range, &mut alpha_override), 0);
range.batch_flags = 0x0108;
assert_eq!(update(&range, &mut alpha_override), original_count);
range.batch_flags = 0x0148;
assert_eq!(update(&range, &mut alpha_override), 0);
assert_eq!(original_count, 3);
}
}