aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-render-vulkan/src')
-rw-r--r--adapters/fparkan-render-vulkan/src/asset_mesh.rs12
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke.rs73
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs3
3 files changed, 79 insertions, 9 deletions
diff --git a/adapters/fparkan-render-vulkan/src/asset_mesh.rs b/adapters/fparkan-render-vulkan/src/asset_mesh.rs
index 3249012..f691b34 100644
--- a/adapters/fparkan-render-vulkan/src/asset_mesh.rs
+++ b/adapters/fparkan-render-vulkan/src/asset_mesh.rs
@@ -1379,8 +1379,10 @@ mod tests {
normals: None,
uv0: None,
uv1: None,
+ type16_present: false,
indices,
batches,
+ triangle_descriptors: None,
node_names: None,
animation: None,
}
@@ -1438,6 +1440,7 @@ mod tests {
normals: None,
uv0: None,
uv1: None,
+ type16_present: false,
indices: Vec::new(),
batches: vec![
batch(0, 0, 0),
@@ -1446,6 +1449,7 @@ mod tests {
..batch(0, 0, 0)
},
],
+ triangle_descriptors: None,
node_names: None,
animation: None,
};
@@ -1684,8 +1688,10 @@ mod tests {
normals: None,
uv0: None,
uv1: None,
+ type16_present: false,
indices: vec![0, 1, 2, 0, 1, 2],
batches: vec![batch(0, 3, 0), batch(3, 3, 0)],
+ triangle_descriptors: None,
node_names: None,
animation: Some(ModelAnimation {
keys: vec![
@@ -1743,8 +1749,10 @@ mod tests {
normals: None,
uv0: None,
uv1: None,
+ type16_present: false,
indices: Vec::new(),
batches: Vec::new(),
+ triangle_descriptors: None,
node_names: None,
animation: Some(ModelAnimation {
keys: vec![
@@ -1849,8 +1857,10 @@ mod tests {
normals: None,
uv0: None,
uv1: None,
+ type16_present: false,
indices: vec![0, 1, 2, 0, 1, 2],
batches: vec![batch(0, 3, 0), batch(3, 3, 0)],
+ triangle_descriptors: None,
node_names: None,
animation: Some(ModelAnimation {
keys: vec![AnimKey24 {
@@ -1940,8 +1950,10 @@ mod tests {
normals: None,
uv0: None,
uv1: None,
+ type16_present: false,
indices: vec![0, 1, 2],
batches: vec![batch(0, 3, 0)],
+ triangle_descriptors: None,
node_names: None,
animation: Some(ModelAnimation {
keys: vec![AnimKey24 {
diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
index 90bce14..522f95f 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
@@ -423,6 +423,7 @@ impl VulkanSmokeRenderer {
draw_range_sort_keys: vec![None; create_info.mesh.draw_ranges.len()],
draw_order_dirty: false,
draw_range_world_queue: vec![None; create_info.mesh.draw_ranges.len()],
+ draw_range_diffuse_alpha_overrides: vec![None; create_info.mesh.draw_ranges.len()],
world_transparent_background_ranges: Vec::new(),
draw_range_base_pipeline_states: create_info
.mesh
@@ -901,6 +902,27 @@ impl VulkanSmokeRenderer {
Ok(())
}
+ /// Overrides one draw's diffuse alpha without changing its shared material.
+ pub fn set_draw_range_diffuse_alpha_override(
+ &mut self,
+ range_index: usize,
+ diffuse_alpha: Option<f32>,
+ ) -> Result<(), VulkanSmokeRendererError> {
+ if diffuse_alpha.is_some_and(|alpha| !alpha.is_finite() || !(0.0..=1.0).contains(&alpha)) {
+ return Err(VulkanSmokeRendererError::InvalidStaticMesh {
+ context: "dynamic draw-range diffuse alpha must be finite and 0..1",
+ });
+ }
+ let alpha_override = self
+ .draw_range_diffuse_alpha_overrides
+ .get_mut(range_index)
+ .ok_or(VulkanSmokeRendererError::InvalidStaticMesh {
+ context: "dynamic draw-range alpha index is out of bounds",
+ })?;
+ *alpha_override = diffuse_alpha;
+ Ok(())
+ }
+
/// Sets the native per-range alpha reference in legacy 0..=255 units.
///
/// Zero remains an explicit value; use the native-default constant when
@@ -1874,11 +1896,16 @@ impl VulkanSmokeRenderer {
context: "static material alpha",
},
)?;
- let material_alphas = [
- material_alpha[0].to_ne_bytes(),
- material_alpha[1].to_ne_bytes(),
- ]
- .concat();
+ let diffuse_alpha_override = self
+ .draw_range_diffuse_alpha_overrides
+ .get(range_index)
+ .ok_or(VulkanSmokeRendererError::InvariantViolation {
+ context: "draw-range diffuse-alpha override",
+ })?;
+ let material_alphas =
+ draw_material_alphas(*material_alpha, *diffuse_alpha_override)
+ .map(f32::to_ne_bytes)
+ .concat();
device.device().cmd_push_constants(
command_buffer,
resources.pipeline_layout,
@@ -2368,6 +2395,16 @@ fn apply_world_transparency(
}
}
+fn draw_material_alphas(
+ material_alphas: [f32; 2],
+ diffuse_alpha_override: Option<f32>,
+) -> [f32; 2] {
+ [
+ diffuse_alpha_override.unwrap_or(material_alphas[0]),
+ material_alphas[1],
+ ]
+}
+
fn world_material_pipeline_states(
original: LegacyPipelineState,
category: u8,
@@ -2535,10 +2572,10 @@ mod tests {
use super::super::{VulkanDynamicDrawRange, VulkanStaticDrawRange, VulkanStaticMesh};
use super::{
apply_geometry_range_updates, apply_world_transparency, completed_readback_buffer_index,
- mark_draw_order_dirty_on_activity_change, set_and_mark_dirty_if_changed,
- sorted_world_draw_order, take_runtime_children_with_validation_snapshot,
- take_runtime_owners_in_dependency_order, validate_geometry_upload,
- world_material_pipeline_states, RollbackOnDrop,
+ draw_material_alphas, mark_draw_order_dirty_on_activity_change,
+ set_and_mark_dirty_if_changed, sorted_world_draw_order,
+ take_runtime_children_with_validation_snapshot, take_runtime_owners_in_dependency_order,
+ validate_geometry_upload, world_material_pipeline_states, RollbackOnDrop,
};
use fparkan_render::{LegacyBlendMode, LegacyCullMode, LegacyDepthMode, LegacyPipelineState};
use std::cell::RefCell;
@@ -3141,4 +3178,22 @@ mod tests {
assert!(world_material_pipeline_states(original, 5, Some(false)).is_none());
assert!(world_material_pipeline_states(fixed_state, 5, None).is_none());
}
+
+ #[test]
+ fn draw_alpha_override_is_per_range_and_none_restores_material_alpha() {
+ let shared_material = [0.25, 0.5];
+
+ assert_eq!(draw_material_alphas(shared_material, Some(0.0)), [0.0, 0.5]);
+ assert_eq!(draw_material_alphas(shared_material, None), shared_material);
+
+ let updated_material = [0.75, 0.125];
+ assert_eq!(
+ draw_material_alphas(updated_material, None),
+ updated_material
+ );
+ assert_eq!(
+ draw_material_alphas(updated_material, Some(0.0)),
+ [0.0, 0.125]
+ );
+ }
}
diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
index 51f8384..f004cb2 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
@@ -1456,6 +1456,9 @@ pub struct VulkanSmokeRenderer {
/// a fixed screen/sky/weather pass; `Some(false)` is world opaque and
/// `Some(true)` is world transparent.
pub(super) draw_range_world_queue: Vec<Option<bool>>,
+ /// Optional diffuse-alpha override for each draw range, independent of
+ /// the shared material record.
+ pub(super) draw_range_diffuse_alpha_overrides: Vec<Option<f32>>,
/// Fixed sky background ranges placed between world opaque and transparent.
pub(super) world_transparent_background_ranges: Vec<usize>,
/// Pipeline state before transparent queue depth policy is applied.