Skip to content

fix(VR): underwater mask while partially submerged#2062

Merged
davo0411 merged 6 commits into
community-shaders:devfrom
alandtse:underwater_mask
Apr 6, 2026
Merged

fix(VR): underwater mask while partially submerged#2062
davo0411 merged 6 commits into
community-shaders:devfrom
alandtse:underwater_mask

Conversation

@alandtse
Copy link
Copy Markdown
Collaborator

@alandtse alandtse commented Apr 5, 2026

closes #620

Does not fix it where there's no water data (so whiterun/caves will have vanilla broken behavior).

Summary by CodeRabbit

  • New Features

    • Improved VR underwater rendering with per-eye, depth-aware masking for more consistent stereo visuals.
  • Bug Fixes

    • Reduced mismatched underwater masking between eyes; better handling near geometry and sky/unrendered pixels while preserving fallback behavior.
  • Chores

    • Upscaling shader package version bumped.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds VR-aware per-eye underwater mask upscaling: reconstructs per-eye positions from SceneDepth, queries per-eye water height, computes underwater status per-pixel, updates SharedData::GetWaterData to accept an eye index, and adjusts upscaling depth SRV binding/copy timing and shader build defines. (≤50 words)

Changes

Cohort / File(s) Summary
VR Underwater Mask Upscaling
features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl
Adds a VR-only branch: derive eyeIndex from input.TexCoord.x, unpack side-by-side stereo UVs to per-eye UVs, read SceneDepth (t1), reconstruct camera-relative position using FrameBuffer::CameraViewProjInverse[eyeIndex], query per-eye water height, and compute per-pixel UnderwaterMask; falls back to original UnderwaterMask.SampleLevel(...) when no nearby water tile.
Shared Water Data & Call Sites
package/Shaders/Common/SharedData.hlsli, package/Shaders/Lighting.hlsl
Change SharedData::GetWaterData signature to GetWaterData(float3 worldPosition, uint eyeIndex = 0) and adjust returned waterData.w for non-zero eyes using FrameBuffer::CameraPosAdjust[eyeIndex].z. Update Lighting.hlsl to pass eyeIndex for per-eye water lookups.
Upscaling Pipeline & Build
src/Features/Upscaling.cpp, features/Upscaling/Shaders/Features/Upscaling.ini
Compile underwater-mask PS with "VR" define when VR enabled. Bind original pre-upscale depth SRV (depthCopy.depthSRV) into the underwater mask draw and move the VR-only depth copy to after that draw so downstream passes see the upscaled depth. Bump shader version to 1-3-1.
Math Constants
package/Shaders/Common/Math.hlsli
Add #define WATER_HEIGHT_NO_TILE_SENTINEL -1e9f and document sentinel semantics for detecting absence of nearby water tiles.

Sequence Diagram

sequenceDiagram
    participant VS as VS / Input UV
    participant PS as UnderwaterMaskUpscalePS
    participant SceneDepth as SceneDepth SRV (t1)
    participant Camera as FrameBuffer (CameraViewProjInverse, CameraPosAdjust)
    participant Shared as SharedData::GetWaterData
    participant RT as UnderwaterMask RT

    VS->>PS: provide TexCoord (contains stereo UV)
    PS->>PS: extract eyeIndex from TexCoord.x and unpack per-eye UV
    PS->>SceneDepth: Load depth at per-eye UV
    SceneDepth-->>PS: depth
    PS->>Camera: read CameraViewProjInverse[eyeIndex] & CameraPosAdjust[eyeIndex]
    Camera-->>PS: matrices & per-eye adjust
    PS->>PS: reconstruct world position or ray direction
    PS->>Shared: GetWaterData(worldPos, eyeIndex)
    Shared-->>PS: waterData (adjusted per-eye)
    PS->>PS: evaluate underwater test (depth & ray logic)
    PS-->>RT: write per-eye UnderwaterMask
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • doodlum
  • jiayev

"I hop and map each watery line,
Two eyes aligned, each mask divine.
Depth I probe with tiny paws,
Per-eye waves meet measured laws.
Hare's small cheer for clearer shores!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: fixing VR underwater mask rendering during partial submersion, which directly addresses the main objective.
Linked Issues check ✅ Passed Changes implement both defect fixes: analytical mask reconstruction per-eye addresses stereo-awareness [#620], and depth-based comparison fixes angle mismatch to match water surface. Non-VR and no-water-data cases retain original behavior as intended.
Out of Scope Changes check ✅ Passed All modifications are in-scope VR underwater mask fixes. Version bump and sentinel constant are supporting changes. No unrelated refactoring or out-of-scope functionality detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 5, 2026

No actionable suggestions for changed features.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl`:
- Around line 59-103: The VR branch is using raw input.TexCoord for depth
sampling and unprojection, causing TAA jitter to shift the waterline; reapply
the same de-jitter (jitter-compensated) UV used elsewhere before calling
SharedData::ConvertUVToSampleCoord and before building ndc/worldPos.
Specifically, compute the de-jittered eyeUV (using the same jitter removal logic
applied in the non-VR path) and use that de-jittered eyeUV for
SceneDepth.Load(SharedData::ConvertUVToSampleCoord(...)) and when computing ndc
and the mul with FrameBuffer::CameraViewProjInverse[eyeIndex] so
psout.UnderwaterMask is computed from the de-jittered position.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8dcbc4d9-5b31-42d5-93cf-c8e16d6e9215

📥 Commits

Reviewing files that changed from the base of the PR and between 554d425 and fc8a13f.

📒 Files selected for processing (4)
  • features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/Lighting.hlsl
  • src/Features/Upscaling.cpp

Comment thread features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 5, 2026

✅ A pre-release build is available for this PR:
Download

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl (1)

68-76: ⚠️ Potential issue | 🟠 Major

Unproject from the same de-jittered UV you use for depth.

SceneDepth is fetched from de-jittered uv, but eyeUV/ndc still come from raw input.TexCoord. That leaves depth sampling and world-position reconstruction out of phase, so the waterline will still shimmer with TAA jitter.

🎯 Minimal fix
-		// Unpack from side-by-side stereo layout to per-eye UV [0, 1]
-		float2 eyeUV = float2(input.TexCoord.x * 2.0 - (float)eyeIndex, input.TexCoord.y);
+		// Unpack the same de-jittered stereo UV into per-eye UV [0, 1]
+		float2 eyeUV = float2(uv.x * 2.0 - (float)eyeIndex, uv.y);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl` around
lines 68 - 76, eyeUV and ndc are computed from raw input.TexCoord while
SceneDepth is sampled from the de-jittered uv, causing Z and reconstructed world
position to be out-of-sync; update the eyeUV/ndc computation to derive from the
same de-jittered stereo UV (uv) used for depth sampling (respect stereo
side-by-side layout and SharedData::BufferDim) so that eyeUV, ndc, and the
SceneDepth.Load(int3(uv * SharedData::BufferDim.xy, 0)).x all use the same
de-jittered coordinates (adjust the math that creates eyeUV and ndc to use uv
instead of input.TexCoord).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl`:
- Around line 68-76: eyeUV and ndc are computed from raw input.TexCoord while
SceneDepth is sampled from the de-jittered uv, causing Z and reconstructed world
position to be out-of-sync; update the eyeUV/ndc computation to derive from the
same de-jittered stereo UV (uv) used for depth sampling (respect stereo
side-by-side layout and SharedData::BufferDim) so that eyeUV, ndc, and the
SceneDepth.Load(int3(uv * SharedData::BufferDim.xy, 0)).x all use the same
de-jittered coordinates (adjust the math that creates eyeUV and ndc to use uv
instead of input.TexCoord).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff3e6257-4dfc-46dc-a260-7bfa328d830a

📥 Commits

Reviewing files that changed from the base of the PR and between eb2f03e and a21fa4c.

📒 Files selected for processing (6)
  • features/Upscaling/Shaders/Features/Upscaling.ini
  • features/Upscaling/Shaders/Upscaling/UnderwaterMaskUpscalePS.hlsl
  • package/Shaders/Common/Math.hlsli
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/Lighting.hlsl
  • src/Features/Upscaling.cpp
✅ Files skipped from review due to trivial changes (2)
  • package/Shaders/Common/Math.hlsli
  • features/Upscaling/Shaders/Features/Upscaling.ini
🚧 Files skipped from review as they are similar to previous changes (1)
  • package/Shaders/Common/SharedData.hlsli

Comment thread src/Features/Upscaling.cpp Outdated
@davo0411 davo0411 merged commit b4abab7 into community-shaders:dev Apr 6, 2026
6 of 7 checks passed
ParticleTroned pushed a commit to ParticleTroned/skyrim-community-shaders that referenced this pull request May 2, 2026
…#2062)

Co-authored-by: davo0411 <davidkehoe0411@outlook.com>
(cherry picked from commit b4abab7)
ParticleTroned added a commit to ParticleTroned/skyrim-community-shaders that referenced this pull request May 5, 2026
Adds a VR diagnostics switch to bypass the community-shaders#2062/community-shaders#2075 underwater mask changes for in-game A/B testing.

The toggle disables the analytical underwater mask shader path, the TESWaterSystem fallback height, and the shared VR water-height eye correction while preserving SRV unbind safety.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VR underwater mask is incorrect

3 participants