diff options
| author | Valentin Popov <valentin@popov.link> | 2026-11-01 06:49:51 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-11-01 06:49:51 +0300 |
| commit | 0f8b14abbf73a43402644c9acd0750bf25a79e98 (patch) | |
| tree | 757099fc012659d54d7124223f823a47064630d7 /adapters/fparkan-render-vulkan | |
| parent | 6d15bc20060cb98ab99351ef1731fc85a84746d9 (diff) | |
| download | fparkan-0f8b14abbf73a43402644c9acd0750bf25a79e98.tar.xz fparkan-0f8b14abbf73a43402644c9acd0750bf25a79e98.zip | |
fix(render): use native shifted water reflection camera
Diffstat (limited to 'adapters/fparkan-render-vulkan')
| -rw-r--r-- | adapters/fparkan-render-vulkan/shaders/triangle.frag | 15 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/shaders/triangle.frag.spv | bin | 14512 -> 14716 bytes | |||
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/ffi/smoke.rs | 28 |
3 files changed, 31 insertions, 12 deletions
diff --git a/adapters/fparkan-render-vulkan/shaders/triangle.frag b/adapters/fparkan-render-vulkan/shaders/triangle.frag index 5d10152..2c71278 100644 --- a/adapters/fparkan-render-vulkan/shaders/triangle.frag +++ b/adapters/fparkan-render-vulkan/shaders/triangle.frag @@ -82,12 +82,15 @@ void main() { vec2 bump_uv = plane_uv * frame.embm_wave.y + frame.embm_wave.x; vec2 duv = max(vec2(-1.0), (texture(embm_bump, bump_uv).rg * 255.0 - 128.0) / 127.0); vec2 displacement = duv * frame.embm_wave.zw; - // shortcut: convert native map-UV displacement to the current mirror projection; - // replace this projection when accepting the original shifted reflection camera. - vec3 displaced_world = in_world_position - vec3(displacement.yx * span, 0.0); - vec4 displaced_clip = frame.clip_from_world * vec4(displaced_world, 1.0); - if (displaced_clip.w > 0.000001) { - reflection_uv = displaced_clip.xy / displaced_clip.w * 0.5 + 0.5; + if ((mode & 128) != 0) { + reflection_uv = plane_uv + displacement; + } else { + // shortcut: non-perspective API cameras retain the projective mirror fallback. + vec3 displaced_world = in_world_position - vec3(displacement.yx * span, 0.0); + vec4 displaced_clip = frame.clip_from_world * vec4(displaced_world, 1.0); + if (displaced_clip.w > 0.000001) { + reflection_uv = displaced_clip.xy / displaced_clip.w * 0.5 + 0.5; + } } vec3 rgb = texture(reflection_color, reflection_uv).rgb * in_base_diffuse + in_base_specular; out_color = vec4(mix(rgb * in_color, frame.fog_color.rgb, in_fog_factor), material.diffuse_alpha); diff --git a/adapters/fparkan-render-vulkan/shaders/triangle.frag.spv b/adapters/fparkan-render-vulkan/shaders/triangle.frag.spv Binary files differindex de3ace6..6deef9d 100644 --- a/adapters/fparkan-render-vulkan/shaders/triangle.frag.spv +++ b/adapters/fparkan-render-vulkan/shaders/triangle.frag.spv diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs index bd745ad..ef19ee8 100644 --- a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs +++ b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs @@ -373,7 +373,7 @@ impl VulkanSmokeRenderer { plane_heights.sort_unstable(); plane_heights.dedup(); if !plane_heights.is_empty() { - eprintln!("render_coverage planar_reflection_shifted_camera_unsupported={} (native bump map and clock; using a projective mirror until shifted-camera mapping is implemented)", plane_heights.len()); + eprintln!("render_coverage planar_reflection_render_context_approx={} (native shifted window and bump UV; main-view depth range, sky/fog/FX and swapchain-sized target remain approximations; non-perspective cameras use mirror fallback)", plane_heights.len()); eprintln!("render_coverage planar_reflection_other_planes_unsupported={} (nearest active plane is reflected)", plane_heights.len().saturating_sub(1)); } if unsupported_nonplanar != 0 { @@ -1564,11 +1564,18 @@ impl VulkanSmokeRenderer { .active_reflection_plane() .map(|height| { let mut frame = self.frame_uniforms; - frame.clip_from_world = + frame.clip_from_world = fparkan_render::water::legacy_embm_reflection_clip( + frame.clip_from_world, + frame.camera_position, + height, + frame.embm_bounds, + ) + .or_else(|| { fparkan_render::reflect_clip_from_world_about_z(frame.clip_from_world, height) - .ok_or(VulkanSmokeRendererError::InvalidStaticCamera { - context: "non-finite reflected clip transform", - })?; + }) + .ok_or(VulkanSmokeRendererError::InvalidStaticCamera { + context: "non-finite reflected clip transform", + })?; frame.camera_position[2] = 2.0 * height - frame.camera_position[2]; if !frame.is_finite() { return Err(VulkanSmokeRendererError::InvalidStaticCamera { @@ -1819,6 +1826,15 @@ impl VulkanSmokeRenderer { self.draw_order_dirty = false; } let reflection_plane = self.active_reflection_plane(); + let shifted_reflection = reflection_plane.is_some_and(|height| { + fparkan_render::water::legacy_embm_reflection_clip( + self.frame_uniforms.clip_from_world, + self.frame_uniforms.camera_position, + height, + self.frame_uniforms.embm_bounds, + ) + .is_some() + }); let device = self.device_ref()?; let swapchain = self.swapchain_ref()?; let resources = self.resources_ref()?; @@ -2053,7 +2069,7 @@ impl VulkanSmokeRenderer { && reflection_plane.is_some() && self.reflection_planes[range_index] == reflection_plane { - 64 + 64 | if shifted_reflection { 128 } else { 0 } } else { 0 }) as f32; |
