diff options
| author | Valentin Popov <valentin@popov.link> | 2026-10-18 06:28:16 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-10-18 06:28:16 +0300 |
| commit | c77c078efee9ece70c3f82793ed002f82a95eb85 (patch) | |
| tree | 2e12bd0f82dcf2a1b728b3a00e8477414d6fb90f /adapters/fparkan-render-vulkan | |
| parent | d97c8d40bfbae097435f10e46ecad5431504c729 (diff) | |
| download | fparkan-c77c078efee9ece70c3f82793ed002f82a95eb85.tar.xz fparkan-c77c078efee9ece70c3f82793ed002f82a95eb85.zip | |
fix: preserve native sky sprite screen depth
Diffstat (limited to 'adapters/fparkan-render-vulkan')
| -rw-r--r-- | adapters/fparkan-render-vulkan/shaders/triangle.vert | 9 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/shaders/triangle.vert.spv | bin | 18580 -> 19136 bytes | |||
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/ffi/smoke.rs | 15 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs | 38 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/ffi/tests.rs | 2 |
5 files changed, 47 insertions, 17 deletions
diff --git a/adapters/fparkan-render-vulkan/shaders/triangle.vert b/adapters/fparkan-render-vulkan/shaders/triangle.vert index 201c31a..83a1751 100644 --- a/adapters/fparkan-render-vulkan/shaders/triangle.vert +++ b/adapters/fparkan-render-vulkan/shaders/triangle.vert @@ -232,9 +232,10 @@ void main() { out_uv = in_uv; out_detail_uv = in_detail_uv; out_overlay_alpha = in_overlay_alpha; - out_fog_factor = native_fog_factor(in_position); int mode = int(round(material.material_mode)); int combiner_mode = mode & 3; + bool screen_tl = (mode & 8) != 0; + out_fog_factor = screen_tl ? 0.0 : native_fog_factor(in_position); if (combiner_mode == 0) { LightingTerms base_terms = native_material_lighting( in_position, @@ -262,12 +263,14 @@ void main() { out_overlay_diffuse = vec3(1.0); out_overlay_specular = vec3(0.0); } - vec4 clip_position = frame.clip_from_world * vec4(in_position, 1.0); + vec4 clip_position = screen_tl + ? vec4(in_position, 1.0) + : frame.clip_from_world * vec4(in_position, 1.0); // Sky far-depth is a Vulkan projection choice for layers authored around // the camera. Keep world positions, normals, and UVs intact while placing // the resulting primitive at the far depth; this does not assert native // D3D depth-bit equivalence. - if ((mode & 4) != 0) { + if ((mode & 4) != 0 && !screen_tl) { clip_position.z = clip_position.w; } gl_Position = clip_position; diff --git a/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv b/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv Binary files differindex 9574e1c..535bde0 100644 --- a/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv +++ b/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs index c9de5ba..ac359c2 100644 --- a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs +++ b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs @@ -3,7 +3,7 @@ use ash::vk; use fparkan_render::{LegacyDepthMode, LegacyPipelineState}; -use super::smoke_types::resolve_draw_texture_indices; +use super::smoke_types::{resolve_draw_texture_indices, VulkanStaticMaterial}; use super::update_material_texture_descriptor; use super::{ create_command_pool, create_frame_sync, create_index_buffer, create_static_mesh_index_buffer, @@ -361,18 +361,7 @@ impl VulkanSmokeRenderer { create_info .materials .iter() - .map(|material| { - let combiner_mode = if material.lightmap_mode { - 3.0 - } else if material.sky_nebula_stars { - 2.0 - } else if material.unlit { - 1.0 - } else { - 0.0 - }; - combiner_mode + if material.sky_far_depth { 4.0 } else { 0.0 } - }) + .map(VulkanStaticMaterial::encoded_material_mode) .collect() }; let material_specular = if create_info.materials.is_empty() { diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs index f628e23..7a8837d 100644 --- a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs +++ b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs @@ -505,6 +505,33 @@ pub struct VulkanStaticMaterial { /// renderer projection choice; it is not a claim about the original D3D /// depth-bit encoding. pub sky_far_depth: bool, + /// Push material mode bit 8 and treat positions as Vulkan clip-space + /// `XYZRHW` vertices. Their x/y coordinates are converted from viewport + /// pixels by the caller and z retains the native `0.999` depth. + pub screen_tl: bool, +} + +impl VulkanStaticMaterial { + pub(crate) fn encoded_material_mode(&self) -> f32 { + let combiner_mode = if self.screen_tl { + 1.0 + } else if self.lightmap_mode { + 3.0 + } else if self.sky_nebula_stars { + 2.0 + } else if self.unlit { + 1.0 + } else { + 0.0 + }; + combiner_mode + + if self.sky_far_depth && !self.screen_tl { + 4.0 + } else { + 0.0 + } + + if self.screen_tl { 8.0 } else { 0.0 } + } } /// One authored RGBA8 mip level accepted by the Vulkan texture upload path. @@ -1028,6 +1055,7 @@ mod static_mesh_tests { sky_nebula_stars: false, lightmap_mode: false, sky_far_depth: false, + screen_tl: false, }, VulkanStaticMaterial { material_index: 7, @@ -1054,9 +1082,19 @@ mod static_mesh_tests { sky_nebula_stars: false, lightmap_mode: false, sky_far_depth: false, + screen_tl: false, }, ]; + let mut screen_tl = materials[0].clone(); + screen_tl.screen_tl = true; + screen_tl.sky_far_depth = true; + assert_eq!(screen_tl.encoded_material_mode(), 9.0); + let mut far_sky = materials[0].clone(); + far_sky.unlit = true; + far_sky.sky_far_depth = true; + assert_eq!(far_sky.encoded_material_mode(), 5.0); + assert_eq!( resolve_draw_texture_indices(&ranges, &materials), Ok(vec![1, 0]) diff --git a/adapters/fparkan-render-vulkan/src/ffi/tests.rs b/adapters/fparkan-render-vulkan/src/ffi/tests.rs index b8a3d71..4ed61f7 100644 --- a/adapters/fparkan-render-vulkan/src/ffi/tests.rs +++ b/adapters/fparkan-render-vulkan/src/ffi/tests.rs @@ -533,7 +533,7 @@ fn native_specular_reference_uses_squared_power_and_total_overflow_curve() { fn shader_computes_radial_fog_per_vertex_and_interpolates_it() { let vertex = include_str!("../../shaders/triangle.vert"); let fragment = include_str!("../../shaders/triangle.frag"); - assert!(vertex.contains("out_fog_factor = native_fog_factor(in_position);")); + assert!(vertex.contains("out_fog_factor = screen_tl ? 0.0 : native_fog_factor(in_position);")); assert!(fragment.contains("layout(location = 4) in float in_fog_factor;")); assert!(!fragment.contains("distance(in_world_position")); assert!(!fragment.contains("float fog_factor()")); |
