aboutsummaryrefslogtreecommitdiff
path: root/adapters
diff options
context:
space:
mode:
Diffstat (limited to 'adapters')
-rw-r--r--adapters/fparkan-render-vulkan/shaders/triangle.vert9
-rw-r--r--adapters/fparkan-render-vulkan/shaders/triangle.vert.spvbin20096 -> 20196 bytes
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs40
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
index f74b1f8..4fc9a1b 100644
--- a/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv
+++ b/adapters/fparkan-render-vulkan/shaders/triangle.vert.spv
Binary files differ
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: [