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.rs6
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke.rs12
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs62
3 files changed, 70 insertions, 10 deletions
diff --git a/adapters/fparkan-render-vulkan/src/asset_mesh.rs b/adapters/fparkan-render-vulkan/src/asset_mesh.rs
index 3249012..e2a8395 100644
--- a/adapters/fparkan-render-vulkan/src/asset_mesh.rs
+++ b/adapters/fparkan-render-vulkan/src/asset_mesh.rs
@@ -1381,6 +1381,7 @@ mod tests {
uv1: None,
indices,
batches,
+ triangle_descriptors: None,
node_names: None,
animation: None,
}
@@ -1446,6 +1447,7 @@ mod tests {
..batch(0, 0, 0)
},
],
+ triangle_descriptors: None,
node_names: None,
animation: None,
};
@@ -1686,6 +1688,7 @@ mod tests {
uv1: None,
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![
@@ -1745,6 +1748,7 @@ mod tests {
uv1: None,
indices: Vec::new(),
batches: Vec::new(),
+ triangle_descriptors: None,
node_names: None,
animation: Some(ModelAnimation {
keys: vec![
@@ -1851,6 +1855,7 @@ mod tests {
uv1: None,
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 {
@@ -1942,6 +1947,7 @@ mod tests {
uv1: None,
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 a2481f7..90bce14 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
@@ -1808,6 +1808,7 @@ impl VulkanSmokeRenderer {
0,
vk::IndexType::UINT32,
);
+ let mut viewport_depth = None;
for &range_index in &self.draw_order {
let range = self.draw_ranges.get(range_index).ok_or(
VulkanSmokeRendererError::InvariantViolation {
@@ -1929,6 +1930,17 @@ impl VulkanSmokeRenderer {
} else {
*material_mode
};
+ let viewport = super::swapchain_resources::draw_viewport(
+ swapchain.report.plan.extent,
+ material_mode,
+ );
+ let next_viewport_depth = [viewport.min_depth, viewport.max_depth];
+ if viewport_depth != Some(next_viewport_depth) {
+ device
+ .device()
+ .cmd_set_viewport(command_buffer, 0, &[viewport]);
+ viewport_depth = Some(next_viewport_depth);
+ }
let material_mode = [material_mode.to_ne_bytes()];
device.device().cmd_push_constants(
command_buffer,
diff --git a/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs b/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
index 89ca43a..05ce927 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
@@ -922,8 +922,17 @@ fn create_texture_descriptor_bundle(
Ok((layout, pool, descriptor_sets, sampler))
}
-fn extent_component_to_f32(value: u32) -> f32 {
- value as f32
+pub(super) fn draw_viewport(extent: (u32, u32), material_mode: f32) -> vk::Viewport {
+ // Ngi32 RVA 0x7170 maps world depth to 0.1..0.99; TL and sky depth bypass it.
+ let explicit_depth = material_mode.round() as u32 & 12 != 0;
+ vk::Viewport {
+ x: 0.0,
+ y: 0.0,
+ width: extent.0 as f32,
+ height: extent.1 as f32,
+ min_depth: if explicit_depth { 0.0 } else { 0.1 },
+ max_depth: if explicit_depth { 1.0 } else { 0.99 },
+ }
}
fn create_graphics_pipeline_cache(
@@ -1033,14 +1042,7 @@ fn create_graphics_pipeline(
let input_assembly_state = vk::PipelineInputAssemblyStateCreateInfo::default()
.topology(vk::PrimitiveTopology::TRIANGLE_LIST)
.primitive_restart_enable(false);
- let viewports = [vk::Viewport {
- x: 0.0,
- y: 0.0,
- width: extent_component_to_f32(extent.0),
- height: extent_component_to_f32(extent.1),
- min_depth: 0.0,
- max_depth: 1.0,
- }];
+ let viewports = [draw_viewport(extent, 0.0)];
let scissors = [vk::Rect2D {
offset: vk::Offset2D { x: 0, y: 0 },
extent: vk::Extent2D {
@@ -1105,6 +1107,9 @@ fn create_graphics_pipeline(
let color_blend_state = vk::PipelineColorBlendStateCreateInfo::default()
.logic_op_enable(false)
.attachments(&color_blend_attachments);
+ let dynamic_states = [vk::DynamicState::VIEWPORT];
+ let dynamic_state =
+ vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&dynamic_states);
let create_info = vk::GraphicsPipelineCreateInfo::default()
.stages(&shader_stages)
.vertex_input_state(&vertex_input_state)
@@ -1114,6 +1119,7 @@ fn create_graphics_pipeline(
.multisample_state(&multisample_state)
.depth_stencil_state(&depth_stencil_state)
.color_blend_state(&color_blend_state)
+ .dynamic_state(&dynamic_state)
.layout(pipeline_layout)
.render_pass(render_pass)
.subpass(0);
@@ -1328,3 +1334,39 @@ fn destroy_partial_swapchain_resources(
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::draw_viewport;
+
+ #[test]
+ fn world_viewport_depth_keeps_distant_geometry_in_front_of_screen_sun() {
+ let projection = fparkan_render::LegacyD3d7Projection {
+ viewport: [0, 0, 1280, 1024],
+ near_plane: 0.5,
+ far_plane: 700.0,
+ field_of_view_radians: 1.04,
+ }
+ .try_direct3d7_projection_row_major()
+ .expect("native projection");
+ for mode in [0.0, 1.0, 2.0, 3.0, 16.0, 17.0] {
+ let viewport = draw_viewport((1280, 1024), mode);
+ assert_eq!([viewport.width, viewport.height], [1280.0, 1024.0]);
+ assert_eq!([viewport.min_depth, viewport.max_depth], [0.1, 0.99]);
+ for distance in [0.5, 100.0, 350.0, 600.0, 700.0] {
+ let clip_z = distance * projection[10] + projection[14];
+ let clip_w = distance * projection[11];
+ let depth = viewport.min_depth
+ + (viewport.max_depth - viewport.min_depth) * (clip_z / clip_w);
+ assert!(
+ depth < 0.999,
+ "mode {mode}, distance {distance}, depth {depth}"
+ );
+ }
+ }
+ for mode in [4.0, 5.0, 6.0, 7.0, 9.0] {
+ let viewport = draw_viewport((640, 480), mode);
+ assert_eq!([viewport.min_depth, viewport.max_depth], [0.0, 1.0]);
+ }
+ }
+}