Skip to content

fix(terrain-blending): transparency of landscapes#2082

Merged
alandtse merged 2 commits into
community-shaders:devfrom
InTheBottle:terrain-blending-fix2
Apr 10, 2026
Merged

fix(terrain-blending): transparency of landscapes#2082
alandtse merged 2 commits into
community-shaders:devfrom
InTheBottle:terrain-blending-fix2

Conversation

@InTheBottle
Copy link
Copy Markdown
Contributor

@InTheBottle InTheBottle commented Apr 9, 2026

closes #2080
Addresses the issue seen here. Confirmed fixed in flatrim, will likely need testing in VR.

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved VR depth correction handling in stereo rendering scenarios to ensure more accurate visual representation in immersive environments.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Modified the VR stereo reprojection depth correction payload in Lighting.hlsl. Changed psout.Reflectance.w assignment logic to use psout.Diffuse.w instead of hardcoded 0.0 values in two code paths, affecting stereo rendering calculations.

Changes

Cohort / File(s) Summary
Shader Lighting Logic
package/Shaders/Lighting.hlsl
Modified VR stereo reprojection payload handling: changed psout.Reflectance.w from constant 0.0 to psout.Diffuse.w fallback when pixelOffset <= 0 in guarded VR path; also updated non-matching conditions branch to use psout.Diffuse.w instead of 0.0 for the same component.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • alandtse
  • doodlum

Poem

🐰 A shader hops through stereo light,
Where depths now dance left and right,
Reflectance borrowed from diffuse glow,
VR vision gains a deeper show!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title refers to terrain-blending and transparency of landscapes, which aligns with the shader changes affecting landscape rendering and the reflectance payload used for depth correction in deferred shading.

✏️ 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 9, 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
package/Shaders/Lighting.hlsl (1)

3203-3211: ⚠️ Potential issue | 🔴 Critical

VR stereo reprojection compatibility issue: non-POM surfaces may receive unintended depth correction.

Per StereoBlendCS.hlsl (lines 151, 222), non-POM pixels are expected to store 0.0 in ReflectanceTexture.w to distinguish them from POM-displaced surfaces using the > 1e-2 threshold.

With this change, surfaces without parallax displacement now store psout.Diffuse.w instead. For opaque surfaces where alpha ≈ 1.0, this exceeds the threshold, causing StereoBlendCS to apply the depth correction formula (0.5 - pomOffset) * POMDepthScale—pushing non-POM geometry depth farther away and introducing visual artifacts in stereo reprojection.

This breaks the documented contract that non-POM pixels store 0.0. Ensure VR stereo rendering is tested with opaque/alpha-blended terrain to confirm the change does not degrade depth accuracy in stereo modes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/Shaders/Lighting.hlsl` around lines 3203 - 3211, The VR branch
currently writes psout.Reflectance.w = psout.Diffuse.w for non-POM pixels which
breaks the StereoBlendCS contract expecting 0.0 for non-POM; change the
assignment so psout.Reflectance = float4(indirectLobeWeights.specular,
(pixelOffset > 1e-2) ? saturate(pixelOffset) : 0.0) (or equivalent test using
pixelOffset) so only POM-displaced pixels store a positive w and non-POM pixels
store 0.0; keep the check in the VR block and ensure compatibility with
StereoBlendCS's >1e-2 threshold.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@package/Shaders/Lighting.hlsl`:
- Around line 3203-3211: The VR branch currently writes psout.Reflectance.w =
psout.Diffuse.w for non-POM pixels which breaks the StereoBlendCS contract
expecting 0.0 for non-POM; change the assignment so psout.Reflectance =
float4(indirectLobeWeights.specular, (pixelOffset > 1e-2) ?
saturate(pixelOffset) : 0.0) (or equivalent test using pixelOffset) so only
POM-displaced pixels store a positive w and non-POM pixels store 0.0; keep the
check in the VR block and ensure compatibility with StereoBlendCS's >1e-2
threshold.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3ebdb716-bd13-45ae-a889-5fca162705f3

📥 Commits

Reviewing files that changed from the base of the PR and between bed2317 and ce8c8a3.

📒 Files selected for processing (1)
  • package/Shaders/Lighting.hlsl

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

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

@alandtse
Copy link
Copy Markdown
Collaborator

@coderabbitai can you identify the history for the changed code before and determine what pr changed it and why?

@alandtse alandtse changed the title fix(terrain-blending): addresses issue #2080 fix(terrain-blending): fix transparency of landscapes Apr 10, 2026
@alandtse alandtse changed the title fix(terrain-blending): fix transparency of landscapes fix(terrain-blending): transparency of landscapes Apr 10, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find git history for the changed lines in package/Shaders/Lighting.hlsl
git log --oneline --follow -- package/Shaders/Lighting.hlsl | head -30

echo "---"
# Get blame for recent changes near the VR stereo reprojection path with Reflectance.w
git log --all --oneline --follow -S "psout.Reflectance.w = 0.0" -- package/Shaders/Lighting.hlsl | head -20

echo "---"
# Look at the diff for the changed lines
git log --all --oneline --follow -S "Reflectance.w" -- package/Shaders/Lighting.hlsl | head -20

Unrecoverable error: Request timed out after 300000ms (requestId=ed310f8f-3677-440d-ad71-f468f0ed588a)


Let me try a lighter approach and also search GitHub for the relevant history.


🏁 Script executed:

#!/bin/bash
# Quick log, no -S, no --follow
git log --oneline -20 -- package/Shaders/Lighting.hlsl

echo "==="
# Search for the relevant lines in the current file
grep -n "Reflectance.w" package/Shaders/Lighting.hlsl | head -30

Length of output: 1071


🌐 Web query:

skyrim-community-shaders Lighting.hlsl "Reflectance.w" StereoBlend VR PR site:github.com

💡 Result:

In doodlum/skyrim-community-shaders (branch dev), package/Shaders/Lighting.hlsl defines a deferred G-Buffer output named Reflectance as a full float4 render target (SV_Target5)—but the literal string Reflectance.w does not appear anywhere in that file. (github.com)

Lighting.hlsl does contain VR stereo plumbing (e.g., per-eye constant-buffer array sizing under #if defined(VR) and stereo eye selection via Stereo::GetEyeIndexVS(...)). (github.com)

Also, the literal string StereoBlend does not appear in Lighting.hlsl. (github.com)

If you’re chasing “StereoBlend” in a VR PR, PR #1507 (“feat(VR): enable upscaling”) explicitly removed VR stereo-eye sampling/blending from package/Shaders/DeferredCompositeCS.hlsl (SSGI path), which is the likely place where a “stereo blend” step previously lived. (github.com)

Citations:


🏁 Script executed:

#!/bin/bash
# Show the diff of commit 2017125 for Lighting.hlsl (the feat(vr): reproject stereo PR `#2002`)
git show 2017125 -- package/Shaders/Lighting.hlsl | grep -A 20 -B 5 "Reflectance.w"

echo "==="
# Also show a broader context of the VR stereo block in the current file
grep -n "pixelOffset\|Reflectance\|psout.Diffuse.w\|StereoBlend\|stereo\|pixelPosition\|indirectLobe" package/Shaders/Lighting.hlsl | head -60

echo "==="
# Show the fix commit diff
git show d1704fa -- package/Shaders/Lighting.hlsl | head -100

Length of output: 5167


🏁 Script executed:

#!/bin/bash
# Check commit e9190e6 (HDR rendering `#1692`) for Reflectance lines
git show e9190e6 -- package/Shaders/Lighting.hlsl | grep -A 10 -B 5 "Reflectance"

echo "==="
# Check commit 2017125 (feat(vr): reproject stereo `#2002`) for Reflectance lines
git show 2017125 -- package/Shaders/Lighting.hlsl | grep -A 10 -B 5 "Reflectance"

echo "==="
# Check b4abab7 (fix(VR): underwater mask `#2062`) for Reflectance lines
git show b4abab7 -- package/Shaders/Lighting.hlsl | grep -A 10 -B 5 "Reflectance"

Length of output: 936


@alandtse: Here's the full history for the changed code:


Origin: PR #2002feat(vr): reproject stereo (commit 2017125)

Before PR #2002, the line in Lighting.hlsl was simply:

psout.Reflectance = float4(indirectLobeWeights.specular, psout.Diffuse.w);

PR #2002 replaced it with a new #if defined(VR) && ... block specifically to pack the POM parallax offset into Reflectance.w so that StereoBlendCS could use it for right-eye reprojection depth correction at POM-displaced surfaces. The comment in the code describes the intent:

// VR: store POM parallax amount for stereo reprojection depth correction.
// Read by StereoBlendCS to adjust Eye 1 (right eye) reprojection depth
// at POM-displaced surfaces. Not consumed on flat (SE/AE).
psout.Reflectance = float4(indirectLobeWeights.specular,
    (pixelOffset > 0.0) ? saturate(pixelOffset) : 0.0);  // ← fallback: 0.0 instead of Diffuse.w
`#else`
psout.Reflectance = float4(indirectLobeWeights.specular, 0.0);  // ← 0.0 instead of Diffuse.w
`#endif`

The Bug

When PR #2002 introduced this block, it used 0.0 as the fallback value in both branches — dropping psout.Diffuse.w (the alpha channel). The alpha channel carries terrain blending weights and alpha test data that downstream passes (including terrain blending, referenced in issue #2080) depend on. Zeroing it out breaks those passes.

This PR's Fix (PR #2082, commit d1704fa)

PR #2082 restores psout.Diffuse.w in the two fallback paths, while still correctly packing saturate(pixelOffset) when actual POM displacement is present (pixelOffset > 0.0):

// Before (broken):  (pixelOffset > 0.0) ? saturate(pixelOffset) : 0.0
// After  (fixed):   (pixelOffset > 0.0) ? saturate(pixelOffset) : psout.Diffuse.w

// Before (broken):  float4(indirectLobeWeights.specular, 0.0)
// After  (fixed):   float4(indirectLobeWeights.specular, psout.Diffuse.w)

This restores the original pre-#2002 semantics for the non-POM case, while keeping the VR stereo depth correction intact when POM displacement is actually present.


🧠 Learnings used
Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 2000
File: src/WeatherEditor/EditorWindow.cpp:1271-1274
Timestamp: 2026-03-22T18:40:49.633Z
Learning: Repo: doodlum/skyrim-community-shaders — Maintainer preference (PR `#2000` on 2026-03-22): In src/WeatherEditor/EditorWindow.cpp within EditorWindow::RenderUI, keep `resetLayout = false;` at the end of the frame (after PaletteWindow::Draw). The reset is intentionally one-shot for windows rendered that frame; closed windows are allowed to reopen with their previous geometry. Do not move the clear later or broadcast resets to closed windows.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 1950
File: package/Shaders/Lighting.hlsl:2008-2012
Timestamp: 2026-03-07T00:53:21.267Z
Learning: In doodlum/skyrim-community-shaders PR `#1950`, the maintainer (Dlizzio) confirmed that per-axis normal reorientation for triplanar-projected normals/detail in package/Shaders/Lighting.hlsl is not required for their use case; the current approach intentionally mixes samples without axis-specific swizzle/sign correction.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 2003
File: features/Upscaling/Shaders/Upscaling/DepthUpscalePS.hlsl:55-61
Timestamp: 2026-03-24T04:30:32.809Z
Learning: In `features/Upscaling/Shaders/Upscaling/DepthUpscalePS.hlsl` (doodlum/skyrim-community-shaders PR `#2003`), the shader is dispatched per-eye using per-eye dimensions (DstWidth/DstHeight). The UV (`input.TexCoord`) is derived from `dispatchID / DstDim`, which is already eye-local — not full SBS/packed stereo coordinates. The per-eye UV clamping logic (isRight, halfScale) operates entirely in eye-local space, and there is no stereo seam issue. Do not flag SBS seam concerns for this shader.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 1982
File: package/Shaders/Lighting.hlsl:3089-3095
Timestamp: 2026-03-16T13:13:11.490Z
Learning: In `package/Shaders/Lighting.hlsl` (doodlum/skyrim-community-shaders), the `TREE_ANIM` alpha test path intentionally uses a hardcoded `0.1` floor check (`if (alpha < 0.1) discard;`) and `AlphaTestRefRS` rather than `SharedData::VRAlphaTestThreshold`. `VRAlphaTestThreshold` is wired into `DistantTree.hlsl` and `RunGrass.hlsl` only. The threshold wiring for `Lighting.hlsl`'s `TREE_ANIM` path is deferred to a separate VR foliage PR.

Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-07-05T05:20:45.823Z
Learning: In the skyrim-community-shaders repository, file deletion error handling improvements that replace existence checks and try-catch blocks with std::filesystem::remove error-code-based approaches are considered bug fixes rather than refactoring, as they address inadequate error handling and misleading log messages.

Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 1947
File: package/Shaders/DeferredCompositeCS.hlsl:234-243
Timestamp: 2026-03-14T08:35:42.651Z
Learning: In `package/Shaders/DeferredCompositeCS.hlsl` (doodlum/skyrim-community-shaders), the fallback non-IBL SKYLIGHTING specular path intentionally double-weights with `skylightingSpecular`: `dalcScaled` is computed as `IrradianceToGamma(IrradianceToLinear(directionalAmbientColorSpecular) * skylightingSpecular)`, and the final `finalIrradiance` is then `lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular)`. This is original engine logic preserved from before PR `#1947` and should not be flagged as a double-attenuation bug.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 2000
File: src/WeatherEditor/EditorWindow.cpp:1239-1244
Timestamp: 2026-03-22T18:32:22.461Z
Learning: In doodlum/skyrim-community-shaders (PR `#2000`, 2026-03-22), maintainer preference: keep the default browser width logic in src/WeatherEditor/EditorWindow.cpp within EditorWindow::RenderUI — browserWidth = min(availableWidth * 0.5f, 960.0f * Util::GetUIScale()) is applied unconditionally (before checking settings.showViewport) to preserve a consistent left-rail width on first-use/reset. Do not change this to fill full width when the viewport is hidden.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 1982
File: src/Features/VR/StereoBlend.cpp:98-109
Timestamp: 2026-03-16T13:13:31.383Z
Learning: In `src/Features/VR/StereoBlend.cpp` (doodlum/skyrim-community-shaders), debug modes 4/5 ("Overwrite", "Overwrite Eye1") in the `StereoBlendDebugMode` selector are NOT separate shader variants. They use the same `stereoBlendOverwriteCS` shader with different cbuffer parameters. When `vrStereoOptActive` is true, `stereoBlendOverwriteCS` is always selected unconditionally and `StereoBlendDebugMode` values 4/5 do not map to any distinct code path.

Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 1941
File: package/Shaders/Common/ShadowSampling.hlsli:160-163
Timestamp: 2026-04-03T01:48:34.867Z
Learning: In `package/Shaders/Common/ShadowSampling.hlsli` (doodlum/skyrim-community-shaders PR `#1941`), the directional shadow fade in `GetLightingShadow` is intentionally computed as `fadeStart = shadow.EndSplitDistances.y * (1.0 - FadeWindow)` where `FadeWindow = 0.1`. This anchors the fade to the last 10% of the absolute far-cascade distance (`EndSplitDistances.y`), not to the cascade span. The narrow window is deliberate so shadows dissolve only at the hard far-cutoff without prematurely fading across the whole cascade range. Do not suggest using `lerp(StartSplitDistances.y, EndSplitDistances.y, 1.0 - FadeWindow)` as a fix.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 1966
File: package/Shaders/ISVolumetricLightingGenerateCS.hlsl:0-0
Timestamp: 2026-03-11T08:05:10.801Z
Learning: In doodlum/skyrim-community-shaders, the `sqrt()` applied to `CloudShadows::GetCloudShadowMult()` in `package/Shaders/ISVolumetricLightingGenerateCS.hlsl` is intentional. The maintainer (Dlizzio) confirmed it is used to increase cloud shadow strength at harsh angles for volumetric lighting, and should not be removed or replaced with a direct linear multiply.

@alandtse alandtse merged commit 362456b into community-shaders:dev Apr 10, 2026
23 checks passed
@alandtse
Copy link
Copy Markdown
Collaborator

@coderabbitai VR is also reporting that terrain blending is broken where the landscape is partially transparent. Are there any other locations where #2082 may have caused the issue given the info from this PR?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find and show StereoBlendCS shader
fd -e hlsl -e hlsli "StereoBlend" --exec echo {}
fd -e hlsl -e hlsli -i "stereoblend" --exec cat {}

echo "=== Lighting.hlsl Reflectance.w block ==="
grep -n "Reflectance\|pixelOffset\|indirectLobeWeights\|Diffuse.w\|LANDSCAPE\|PARALLAX\|EMAT\|TRUE_PBR" package/Shaders/Lighting.hlsl | grep -A2 -B2 "Reflectance" | head -80

echo "=== Full VR stereo block context ==="
grep -n "psout.Reflectance" package/Shaders/Lighting.hlsl

Length of output: 17623


@alandtse: Yes — the VR terrain blending breakage has a clear cause traceable directly to PR #2082, rooted in the interaction with StereoBlendCS.hlsl.


The Problem: Sentinel Value Collision

StereoBlendCS.hlsl uses a > 1e-2 threshold to detect POM pixels from Reflectance.w:

// Eye 1 reprojection path:
float pomOffset = ReflectanceTexture[r.otherPx].w;
if (pomOffset > 1e-2) {
    // apply POM depth correction to reprojection
}

// FULL_BLEND path:
float pomOffsetFB = ReflectanceTexture[dtid].w;
if (pomOffsetFB > 1e-2 && POMDepthScale > 0) {
    // apply POM depth correction
}

The original PR #2002 deliberately used 0.0 as the "no POM" sentinel value so StereoBlendCS could distinguish POM pixels (> 1e-2) from non-POM pixels (≈ 0).


What PR #2082 Changed in the VR Branch

The VR #if guard (line 3203) includes LANDSCAPE:

`#if` defined(VR) && (defined(EMAT) || defined(TRUE_PBR)) && \
    (defined(PARALLAX) || defined(LANDSCAPE) || defined(EMAT_ENVMAP) || defined(TRUE_PBR))

PR #2082 changed the fallback from 0.0psout.Diffuse.w:

// Before (`#2002`, correct sentinel for StereoBlendCS):
psout.Reflectance = float4(indirectLobeWeights.specular,
    (pixelOffset > 0.0) ? saturate(pixelOffset) : 0.0);

// After (`#2082`, breaks sentinel):
psout.Reflectance = float4(indirectLobeWeights.specular,
    (pixelOffset > 0.0) ? saturate(pixelOffset) : psout.Diffuse.w);  // ← terrain alpha leaks in

For VR + LANDSCAPE: pixelOffset is typically ≤ 0 (no parallax displacement on terrain), so the fallback is always taken. psout.Diffuse.w carries the terrain blending alpha, which for partially transparent landscape is some value in (0, 1). Since terrainAlpha > 1e-2, StereoBlendCS misidentifies every semi-transparent terrain pixel as a POM surface and applies incorrect depth reprojection — breaking VR terrain blending visually.


The Two Conflicting Requirements

Branch Needs Why
#else (SE/AE) psout.Diffuse.w Terrain alpha must flow through for downstream passes
#if (VR) 0.0 sentinel for non-POM StereoBlendCS uses > 1e-2 to gate POM depth correction

PR #2082 correctly fixed the #else branch but also changed the VR branch fallback, breaking the StereoBlendCS sentinel contract.


Proposed Fix Direction

The VR block needs to keep 0.0 as the no-POM sentinel. One option is to narrow the #if guard to exclude LANDSCAPE from the VR POM path (since terrain doesn't use POM parallax displacement):

// Only enter VR POM path for actual POM-capable shader types, not LANDSCAPE
`#if` defined(VR) && (defined(EMAT) || defined(TRUE_PBR)) && \
    (defined(PARALLAX) || defined(EMAT_ENVMAP))  // removed LANDSCAPE and bare TRUE_PBR
    psout.Reflectance = float4(indirectLobeWeights.specular,
        (pixelOffset > 0.0) ? saturate(pixelOffset) : 0.0);
`#else`
    psout.Reflectance = float4(indirectLobeWeights.specular, psout.Diffuse.w);
`#endif`

This way:

  • VR + PARALLAX/EMAT_ENVMAP: packs POM offset as sentinel (StereoBlendCS works correctly)
  • VR + LANDSCAPE: falls to #else, stores psout.Diffuse.w (terrain alpha flows through, and psout.Diffuse.w being non-zero won't break VR stereo as long as StereoBlendCS doesn't read it — but it will, which means this approach still has the same problem)

The deeper fix may be that the VR + LANDSCAPE case needs Reflectance.w = 0.0 explicitly to preserve the StereoBlendCS sentinel, accepting that terrain alpha doesn't flow through Reflectance.w in VR (if that's acceptable for the VR terrain blending pipeline). That would mean a three-way split:

`#if` defined(VR) && (defined(EMAT) || defined(TRUE_PBR)) && \
    (defined(PARALLAX) || defined(LANDSCAPE) || defined(EMAT_ENVMAP) || defined(TRUE_PBR))
#   if defined(LANDSCAPE)
    // VR + LANDSCAPE: no POM, must keep 0.0 sentinel for StereoBlendCS
    psout.Reflectance = float4(indirectLobeWeights.specular, 0.0);
#   else
    // VR + POM-capable: pack parallax offset
    psout.Reflectance = float4(indirectLobeWeights.specular,
        (pixelOffset > 0.0) ? saturate(pixelOffset) : 0.0);
#   endif
`#else`
    // SE/AE: terrain alpha flows through normally
    psout.Reflectance = float4(indirectLobeWeights.specular, psout.Diffuse.w);
`#endif`

The key question for @InTheBottle is: does VR terrain blending (outside of StereoBlendCS) depend on Reflectance.w = psout.Diffuse.w? If not, 0.0 in VR+LANDSCAPE is safe and the above three-way split is the fix. If it does, then a different channel or approach is needed in VR to carry terrain alpha without colliding with the POM sentinel.


🧠 Learnings used
Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 1982
File: package/Shaders/Lighting.hlsl:3089-3095
Timestamp: 2026-03-16T13:13:11.490Z
Learning: In `package/Shaders/Lighting.hlsl` (doodlum/skyrim-community-shaders), the `TREE_ANIM` alpha test path intentionally uses a hardcoded `0.1` floor check (`if (alpha < 0.1) discard;`) and `AlphaTestRefRS` rather than `SharedData::VRAlphaTestThreshold`. `VRAlphaTestThreshold` is wired into `DistantTree.hlsl` and `RunGrass.hlsl` only. The threshold wiring for `Lighting.hlsl`'s `TREE_ANIM` path is deferred to a separate VR foliage PR.

Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 1947
File: package/Shaders/DeferredCompositeCS.hlsl:234-243
Timestamp: 2026-03-14T08:35:42.651Z
Learning: In `package/Shaders/DeferredCompositeCS.hlsl` (doodlum/skyrim-community-shaders), the fallback non-IBL SKYLIGHTING specular path intentionally double-weights with `skylightingSpecular`: `dalcScaled` is computed as `IrradianceToGamma(IrradianceToLinear(directionalAmbientColorSpecular) * skylightingSpecular)`, and the final `finalIrradiance` is then `lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular)`. This is original engine logic preserved from before PR `#1947` and should not be flagged as a double-attenuation bug.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 1982
File: src/Features/VR/StereoBlend.cpp:98-109
Timestamp: 2026-03-16T13:13:31.383Z
Learning: In `src/Features/VR/StereoBlend.cpp` (doodlum/skyrim-community-shaders), debug modes 4/5 ("Overwrite", "Overwrite Eye1") in the `StereoBlendDebugMode` selector are NOT separate shader variants. They use the same `stereoBlendOverwriteCS` shader with different cbuffer parameters. When `vrStereoOptActive` is true, `stereoBlendOverwriteCS` is always selected unconditionally and `StereoBlendDebugMode` values 4/5 do not map to any distinct code path.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 2003
File: features/Upscaling/Shaders/Upscaling/DepthUpscalePS.hlsl:55-61
Timestamp: 2026-03-24T04:30:32.809Z
Learning: In `features/Upscaling/Shaders/Upscaling/DepthUpscalePS.hlsl` (doodlum/skyrim-community-shaders PR `#2003`), the shader is dispatched per-eye using per-eye dimensions (DstWidth/DstHeight). The UV (`input.TexCoord`) is derived from `dispatchID / DstDim`, which is already eye-local — not full SBS/packed stereo coordinates. The per-eye UV clamping logic (isRight, halfScale) operates entirely in eye-local space, and there is no stereo seam issue. Do not flag SBS seam concerns for this shader.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 1966
File: package/Shaders/ISVolumetricLightingGenerateCS.hlsl:0-0
Timestamp: 2026-03-11T08:05:10.801Z
Learning: In doodlum/skyrim-community-shaders, the `sqrt()` applied to `CloudShadows::GetCloudShadowMult()` in `package/Shaders/ISVolumetricLightingGenerateCS.hlsl` is intentional. The maintainer (Dlizzio) confirmed it is used to increase cloud shadow strength at harsh angles for volumetric lighting, and should not be removed or replaced with a direct linear multiply.

Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 2084
File: src/ShaderCache.cpp:1646-1649
Timestamp: 2026-04-10T07:34:24.381Z
Learning: In `src/ShaderCache.cpp` (doodlum/skyrim-community-shaders PR `#2084`), `GetImagespaceShaderDescriptor` intentionally returns `false` for VR when a shader is not reverse-engineered. Returning `false` causes `ResolveImageSpaceDescriptor` to return `false`, which makes all callers (GetVertexShader, GetPixelShader, GetComputeShader, CompileShader) skip custom shader handling and defer to the vanilla shader. This is the correct pattern for un-RE'd imagespace shaders on VR — do not flag it as "skipping all custom VR handling" or suggest gating on HDR feature state.

Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 1941
File: package/Shaders/Common/ShadowSampling.hlsli:160-163
Timestamp: 2026-04-03T01:48:34.867Z
Learning: In `package/Shaders/Common/ShadowSampling.hlsli` (doodlum/skyrim-community-shaders PR `#1941`), the directional shadow fade in `GetLightingShadow` is intentionally computed as `fadeStart = shadow.EndSplitDistances.y * (1.0 - FadeWindow)` where `FadeWindow = 0.1`. This anchors the fade to the last 10% of the absolute far-cascade distance (`EndSplitDistances.y`), not to the cascade span. The narrow window is deliberate so shadows dissolve only at the hard far-cutoff without prematurely fading across the whole cascade range. Do not suggest using `lerp(StartSplitDistances.y, EndSplitDistances.y, 1.0 - FadeWindow)` as a fix.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 2000
File: src/WeatherEditor/EditorWindow.cpp:1271-1274
Timestamp: 2026-03-22T18:40:49.633Z
Learning: Repo: doodlum/skyrim-community-shaders — Maintainer preference (PR `#2000` on 2026-03-22): In src/WeatherEditor/EditorWindow.cpp within EditorWindow::RenderUI, keep `resetLayout = false;` at the end of the frame (after PaletteWindow::Draw). The reset is intentionally one-shot for windows rendered that frame; closed windows are allowed to reopen with their previous geometry. Do not move the clear later or broadcast resets to closed windows.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 1950
File: package/Shaders/Lighting.hlsl:2008-2012
Timestamp: 2026-03-07T00:53:21.267Z
Learning: In doodlum/skyrim-community-shaders PR `#1950`, the maintainer (Dlizzio) confirmed that per-axis normal reorientation for triplanar-projected normals/detail in package/Shaders/Lighting.hlsl is not required for their use case; the current approach intentionally mixes samples without axis-specific swizzle/sign correction.

Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 1947
File: features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubemaps.hlsli:107-115
Timestamp: 2026-03-14T08:35:02.326Z
Learning: In `features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubemaps.hlsli`, the pattern of scaling `directionalAmbientColorSpecular` by `skylightingSpecular` (via `dalcScaled`) before the final `lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular)` is intentional pre-existing behavior preserved from the original implementation. Do not flag this as double-attenuation; the combined attenuation is by design.

Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-07-05T05:20:45.823Z
Learning: In the skyrim-community-shaders repository, file deletion error handling improvements that replace existence checks and try-catch blocks with std::filesystem::remove error-code-based approaches are considered bug fixes rather than refactoring, as they address inadequate error handling and misleading log messages.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 2000
File: src/WeatherEditor/EditorWindow.cpp:1239-1244
Timestamp: 2026-03-22T18:32:22.461Z
Learning: In doodlum/skyrim-community-shaders (PR `#2000`, 2026-03-22), maintainer preference: keep the default browser width logic in src/WeatherEditor/EditorWindow.cpp within EditorWindow::RenderUI — browserWidth = min(availableWidth * 0.5f, 960.0f * Util::GetUIScale()) is applied unconditionally (before checking settings.showViewport) to preserve a consistent left-rail width on first-use/reset. Do not change this to fill full width when the viewport is hidden.

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.

Terrain Blending(dev): broken transparency

3 participants