diff options
Diffstat (limited to 'apps/fparkan-game/src/main.rs')
| -rw-r--r-- | apps/fparkan-game/src/main.rs | 91 |
1 files changed, 88 insertions, 3 deletions
diff --git a/apps/fparkan-game/src/main.rs b/apps/fparkan-game/src/main.rs index 02d9a1b..61c2d1e 100644 --- a/apps/fparkan-game/src/main.rs +++ b/apps/fparkan-game/src/main.rs @@ -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,8 +7388,10 @@ mod tests { normals: None, uv0: None, uv1: None, + type16_present: false, indices: vec![], batches: vec![], + triangle_descriptors: None, node_names: None, animation: Some(fparkan_msh::ModelAnimation { keys: vec![ @@ -7670,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 +8290,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 { phase_material_indices: vec![10, 11], @@ -10008,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); + } } |
