diff options
Diffstat (limited to 'adapters')
| -rw-r--r-- | adapters/fparkan-render-vulkan/shaders/triangle.vert | 9 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/shaders/triangle.vert.spv | bin | 20096 -> 20196 bytes | |||
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs | 40 |
3 files changed, 44 insertions, 5 deletions
diff --git a/adapters/fparkan-render-vulkan/shaders/triangle.vert b/adapters/fparkan-render-vulkan/shaders/triangle.vert index d1e2e04..078a0d1 100644 --- a/adapters/fparkan-render-vulkan/shaders/triangle.vert +++ b/adapters/fparkan-render-vulkan/shaders/triangle.vert @@ -130,12 +130,13 @@ float native_specular_power(float cosine, float power) { } float native_fog_factor(vec3 world_position) { - float fog_span = frame.fog_distances.y - frame.fog_distances.x; - float distance_to_camera = distance(world_position, frame.camera_position.xyz); - if (fog_span <= 0.000001 || distance_to_camera <= frame.fog_distances.x) { + float fog_span_squared = frame.fog_distances.w - frame.fog_distances.z; + vec3 to_camera = world_position - frame.camera_position.xyz; + float distance_squared = dot(to_camera, to_camera); + if (fog_span_squared <= 0.000001 || distance_squared <= frame.fog_distances.z) { return 0.0; } - return clamp((distance_to_camera - frame.fog_distances.x) / fog_span, 0.0, 1.0); + return clamp((distance_squared - frame.fog_distances.z) / fog_span_squared, 0.0, 1.0); } vec3 normalized_or(vec3 value, vec3 fallback) { diff --git a/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv b/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv Binary files differindex f74b1f8..4fc9a1b 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_types.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs index 278243b..0996fa1 100644 --- a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs +++ b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs @@ -284,6 +284,9 @@ impl VulkanFrameUniforms { .chain([self.fog_start, self.fog_end]) .chain(self.camera_position) .all(f32::is_finite) + && (self.fog_end <= self.fog_start + || ((self.fog_start * self.fog_start).is_finite() + && (self.fog_end * self.fog_end).is_finite())) } /// Serializes one frame slot in the exact `std140` member order. @@ -344,7 +347,17 @@ impl VulkanFrameUniforms { self.fog_color[2], 0.0, ]); - values[84..88].copy_from_slice(&[self.fog_start, self.fog_end, 0.0, 0.0]); + let squared_fog_range = if self.fog_end > self.fog_start { + [self.fog_start * self.fog_start, self.fog_end * self.fog_end] + } else { + [0.0; 2] + }; + values[84..88].copy_from_slice(&[ + self.fog_start, + self.fog_end, + squared_fog_range[0], + squared_fog_range[1], + ]); values[88..92].copy_from_slice(&[ self.camera_position[0], self.camera_position[1], @@ -875,6 +888,31 @@ mod static_mesh_tests { } #[test] + fn fog_uniforms_match_live_native_squared_distance_range() { + // Terrain ShadeIndexedStrided: far=0x442389e6, far²=0x48d0f1ca; + // distance²=0x47707b04 gives visibility=0x3f5b2b94. + let frame = VulkanFrameUniforms { + fog_start: 0.0, + fog_end: f32::from_bits(0x4423_89e6), + ..Default::default() + }; + assert!(frame.is_finite()); + let bytes = frame.to_ne_bytes(); + let read = |offset| f32::from_ne_bytes(bytes[offset..offset + 4].try_into().unwrap()); + assert_eq!(read(344), 0.0); + assert_eq!(read(348).to_bits(), 0x48d0_f1ca); + let visibility = 1.0 - (f32::from_bits(0x4770_7b04) - read(344)) / (read(348) - read(344)); + assert!((visibility - f32::from_bits(0x3f5b_2b94)).abs() < 1.0e-6); + assert!(VulkanFrameUniforms::default().is_finite()); + assert!(!VulkanFrameUniforms { + fog_start: 0.0, + fog_end: f32::MAX, + ..frame + } + .is_finite()); + } + + #[test] fn static_camera_composes_recovered_d3d7_view_before_projection() { let transform = RawCameraTransform { words: [ |
