Skip to content

perf: terrain variation & parallax - #2220

Open
davo0411 wants to merge 72 commits into
community-shaders:devfrom
davo0411:tv-perf-3
Open

perf: terrain variation & parallax#2220
davo0411 wants to merge 72 commits into
community-shaders:devfrom
davo0411:tv-perf-3

Conversation

@davo0411

@davo0411 davo0411 commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator
  1. refactor to lighting landscape layers to facilitate small compiler wins for tv & pbr not having so many branches inside lighting.hlsl
  2. adopted Alexander (bad_emperor)'s ideas on secant stepping instead of linear, per graphics discord. nice perf bump on parallax.
  3. full terrain variation rework, now just takes 2 samples always, no artifacts.
  4. contains like a billion magic number fixes and general comment/code clean up.
image image

Summary by CodeRabbit

  • New Features

    • Tuned parallax and soft-shadow sampling for terrain for cleaner, more consistent shadows and quality-driven tap counts.
    • Terrain feature metadata version bumped.
  • Refactor

    • Mip selection made deterministic for steadier LOD behavior.
    • Terrain sampling simplified to a 2-sample stochastic model and centralized per-layer landscape blending for more consistent lighting.
  • Chores

    • Removed "Extend Shadows" option; terrain tiling fix is now always enabled in the UI.

@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

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

Refactors terrain/landscape parallax and stochastic sampling: splits ExtendedMaterials into parallax core and terrain headers, reduces TerrainVariation sampling from 3→2 samples, removes stochastic mip noise from GetMipLevel, adds parallax/shadow tunables and terrain shadow helpers, consolidates per-layer blending, and removes the CPU ExtendShadows setting and its UI wiring.

Changes

Extended Terrain & Parallax Refactor

Layer / File(s) Summary
Data Shape & Constants
features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli, package/Shaders/Common/SharedData.hlsli, src/Features/ExtendedMaterials.h, src/Features/ExtendedMaterials.cpp, src/Features/TerrainVariation.h, src/Features/TerrainVariation.cpp, features/Terrain Variation/Shaders/Features/TerrainVariation.ini
Adds parallax/shadow constants and ParallaxShadowTapCount; bumps TerrainVariation feature version; removes CPMSettings::ExtendShadows and TerrainVariationSettings::enableTilingFix; adjusts padding/field types and CPU settings/UI serialization.
Terrain Variation Core Sampling
features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli
Replaces 3-sample barycentric hashing with top-2-corner 2-sample approach; introduces StochasticCorner, jitter/LOD helpers, ComputeStochasticOffsetsLOD, StochasticSampleLODJitter, StochasticHeightFadeFromMip, SampleTerrain; changes StochasticEffect/StochasticEffectParallax/StochasticSampleLOD signatures to remove ddx/ddy and use jitter/mip-bias.
GetMipLevel Change
features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli
Removes screenNoise parameter and stochastic selection; new deterministic gradient-based mip computation applying PARALLAX/TRUE_PBR/VR adjustments and returning floored mip level.
Parallax Core Implementation
features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsParallaxCore.hlsli
Adds ray-marching/parallax-refinement core: GetParallaxCoords overloads (LANDSCAPE and non-LANDSCAPE), secant refinement, outputs pixelOffset/hasPOM; non-LANDSCAPE GetParallaxSoftShadowMultiplier.
Terrain Height & Shadow Helpers
features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli
New terrain include: initialize per-layer mip levels, TerrainParallaxTexSample, ProcessTerrainHeightWeights, FinishTerrainHeightQuadBlend, GetTerrainHeight/GetTerrainHeightQuadRayMarch (PBR and legacy), displacement/blend detection, max-weighted scale, tap-count mapping, and terrain parallax shadow base/soft/directional evaluation helpers.
Lighting Integration & Wiring
package/Shaders/Common/LightingLandscape.hlsli, package/Shaders/Lighting.hlsl
Adds LightingLandscape X-macros and per-layer blend macros; Lighting.hlsl includes the new header for LANDSCAPE, tightens parallax-shadow gating to EnableShadows && parallaxShadowQuality > 0.0, updates GetMipLevel/GetParallaxCoords call-sites, initializes/clamps terrain mip levels, computes shared stochastic offsets, caches directional terrain parallax shadow, and replaces explicit 6-layer blending with macro-driven per-layer blends.
CPU Settings / UI / Serialization
src/Features/ExtendedMaterials.h, src/Features/ExtendedMaterials.cpp, src/Features/TerrainVariation.h, src/Features/TerrainVariation.cpp
Removes ExtendShadows from ExtendedMaterials settings and JSON mapping/UI; TerrainVariation drops enableTilingFix and exposes enableLODTerrainTilingFix (uint/aligned), deletes UpdateShaderSettings() and removes shader-wiring calls that marked vertex-descriptor dirty.
Metadata / Cleanups
features/Terrain Variation/Shaders/Features/TerrainVariation.ini, package/Shaders/*, package/Shaders/Common/*
Feature version bump to 1-1-0; EMAT-only macro undef cleanup in Lighting.hlsl; restructured includes to split parallax core and terrain helpers.

Sequence Diagram(s)

sequenceDiagram
  participant PS as PixelShader (EMAT)
  participant EM as ExtendedMaterials Parallax Core
  participant ET as ExtendedMaterials Terrain
  participant TV as TerrainVariation (stochastic offsets)
  participant Tex as Terrain Textures
  participant CPU as CPU Settings

  PS->>EM: GetMipLevel(uv, parallaxTex)
  EM-->>PS: mipLevel (deterministic)
  PS->>TV: ComputeStochasticOffsets(sharedUV) [if TERRAIN_VARIATION]
  TV-->>PS: sharedOffset
  PS->>ET: InitializeTerrainMipLevels(coords)
  ET-->>PS: mipLevels[6]
  PS->>EM: GetParallaxCoords(..., mipLevels, viewDir, tbn, noise, params, sharedOffset)
  EM->>Tex: sample displacement/color (stochastic or SampleLevel)
  Tex-->>EM: height samples
  EM->>EM: ray-march & secant refine -> pixelOffset, parallax UV
  EM-->>PS: parallax UV, pixelOffset, hasPOM
  PS->>ET: ComputeTerrainParallaxShadowBaseHeight(..., sharedOffset)
  ET->>Tex: sample heights along light dir
  Tex-->>ET: shadow samples
  ET-->>PS: terrain parallax shadow multiplier
  CPU->>PS: shared settings (parallax/shadow quality, EnableShadows)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • alandtse
  • doodlum
  • jiayev

Poem

🐇 Two samples now hop where three once leapt away,
Golden jitter nudges LOD through dusk and day,
Rays march then sharpen, secant finds the line,
Layers blend and shadows sip their quiet wine,
A rabbit cheers: tidy shaders, carrots and hay.

🚥 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 'perf: terrain variation & parallax' clearly summarizes the main objective: performance improvements to terrain variation and parallax systems through the substantial refactoring shown in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

Automated formatting by clang-format, prettier, and other hooks.
See https://pre-commit.ci for details.
@github-actions

github-actions Bot commented Apr 27, 2026

Copy link
Copy Markdown

No actionable suggestions for changed features.

davo0411 and others added 8 commits April 27, 2026 22:37
@davo0411
davo0411 marked this pull request as ready for review April 28, 2026 05:23
Copilot AI review requested due to automatic review settings April 28, 2026 05:23

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
package/Shaders/Common/LightingLandscape.hlsli (1)

126-126: Align closing header-guard comment with macro name

The closing comment references __LANDSCAPE_LAYERS_HLSLI__, but the actual guard is __LIGHTING_LANDSCAPE_HLSLI__. Consider syncing for clarity.

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

In `@package/Shaders/Common/LightingLandscape.hlsli` at line 126, The closing
header-guard comment is mismatched: update the comment after `#endif` to match the
actual macro __LIGHTING_LANDSCAPE_HLSLI__ (replace __LANDSCAPE_LAYERS_HLSLI__
with __LIGHTING_LANDSCAPE_HLSLI__), ensuring the comment aligns with the guard
macro used at the top of this file.
features/Terrain Variation/Shaders/Features/TerrainVariation.ini (1)

1-2: Consider adding a linked issue keyword in the PR description

If this PR implements tracked perf/feature work, add a reference like Addresses #<id> for traceability.

As per coding guidelines, feature PRs should include issue references using keywords such as “Addresses #123” / “Implements #123”.

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

In `@features/Terrain` Variation/Shaders/Features/TerrainVariation.ini around
lines 1 - 2, This PR is missing an issue reference for traceability—update the
PR description to include a keywords-style reference like "Addresses
#<issue-id>" or "Implements #<issue-id>" with the actual issue number;
additionally, add a RelatedIssue field under the [Info] section in
TerrainVariation.ini (e.g., add "RelatedIssue = `#123`" next to "Version = 1-1-0")
so the feature (TerrainVariation.ini / [Info] / Version) explicitly records the
linked issue.
features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli (1)

23-27: PR metadata follow-up: add scope in title and link tracking issue.

Suggested title: perf(extended-materials): optimize terrain parallax path
If this maps to a tracked task, append Addresses #<id> (or Implements #<id>) in the PR description.

As per coding guidelines, "When reviewing PRs, please provide suggestions for: Conventional Commit Titles ... and Issue References ..."

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

In `@features/Extended`
Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli around lines 23 -
27, Update the PR title to include scope and the suggested conventional-commit
format — e.g. change it to "perf(extended-materials): optimize terrain parallax
path" — and add an issue reference in the PR description like "Addresses #<id>"
(or "Implements #<id>") if this change maps to a tracked task; note this PR
touches constants such as ParallaxCheapDistance, ParallaxNearShadowQuality,
ParallaxFarShadowQuality, and TerrainParallaxShadowMaxMipLevel so include the
issue link and short summary referencing the terrain parallax/extended-materials
change in the description.
🤖 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/Extended`
Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli:
- Around line 127-139: Normalize guard: after summing weights[] into wsum, avoid
calling rcp(wsum) when wsum is zero/near-zero by computing invwsum =
rcp(max(wsum, 1e-6)) (or choose a small epsilon) and then multiply weights[k] by
invwsum; update both occurrences that use rcp(wsum) (the block that references
heightBlend, weights, wsum, invwsum and the similar block later in the file) so
degenerate/invalid blends no longer produce INF/NaN.

In `@package/Shaders/Common/LightingLandscape.hlsli`:
- Around line 91-94: The non-full-PBR branch double-applies weight by
multiplying landRMAOS with weight at assignment and again when accumulating into
blendedRMAOS; change the assignment of landRMAOS inside that branch to not
multiply by weight (e.g., set landRMAOS = float4(1 - glossiness.x, 0, 1, 0)) and
keep the accumulation blendedRMAOS += landRMAOS * weight so each layer’s RMAOS
is weighted exactly once (references: landRMAOS, blendedRMAOS, blendedRGB,
landColorRGB, glossiness.x, weight).

---

Nitpick comments:
In `@features/Extended`
Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli:
- Around line 23-27: Update the PR title to include scope and the suggested
conventional-commit format — e.g. change it to "perf(extended-materials):
optimize terrain parallax path" — and add an issue reference in the PR
description like "Addresses #<id>" (or "Implements #<id>") if this change maps
to a tracked task; note this PR touches constants such as ParallaxCheapDistance,
ParallaxNearShadowQuality, ParallaxFarShadowQuality, and
TerrainParallaxShadowMaxMipLevel so include the issue link and short summary
referencing the terrain parallax/extended-materials change in the description.

In `@features/Terrain` Variation/Shaders/Features/TerrainVariation.ini:
- Around line 1-2: This PR is missing an issue reference for traceability—update
the PR description to include a keywords-style reference like "Addresses
#<issue-id>" or "Implements #<issue-id>" with the actual issue number;
additionally, add a RelatedIssue field under the [Info] section in
TerrainVariation.ini (e.g., add "RelatedIssue = `#123`" next to "Version = 1-1-0")
so the feature (TerrainVariation.ini / [Info] / Version) explicitly records the
linked issue.

In `@package/Shaders/Common/LightingLandscape.hlsli`:
- Line 126: The closing header-guard comment is mismatched: update the comment
after `#endif` to match the actual macro __LIGHTING_LANDSCAPE_HLSLI__ (replace
__LANDSCAPE_LAYERS_HLSLI__ with __LIGHTING_LANDSCAPE_HLSLI__), ensuring the
comment aligns with the guard macro used at the top of this file.
🪄 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: 57ffdc06-34ee-4729-b25a-f3f07a561d70

📥 Commits

Reviewing files that changed from the base of the PR and between c614997 and 2a8cb8f.

📒 Files selected for processing (10)
  • features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli
  • features/Terrain Variation/Shaders/Features/TerrainVariation.ini
  • features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli
  • package/Shaders/Common/LightingLandscape.hlsli
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/Lighting.hlsl
  • src/Features/ExtendedMaterials.cpp
  • src/Features/ExtendedMaterials.h
  • src/Features/TerrainVariation.cpp
  • src/Features/TerrainVariation.h
💤 Files with no reviewable changes (1)
  • src/Features/ExtendedMaterials.cpp

Comment thread features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli Outdated
Comment thread package/Shaders/Common/LightingLandscape.hlsli Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR restructures landscape/terrain shader paths to reduce branching and improve performance, while reworking Terrain Variation sampling and updating Extended Materials’ parallax/shadow logic (including secant-based refinement).

Changes:

  • Refactors Lighting.hlsl landscape layer blending into a shared include (LightingLandscape.hlsli) and streamlines Terrain Variation integration.
  • Removes ExtendShadows setting and adjusts Extended Materials shader constants/helpers for cheaper parallax + shadow evaluation.
  • Reworks Terrain Variation stochastic sampling to a consistent 2-sample approach and updates feature settings structs/padding accordingly.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Features/TerrainVariation.h Adjusts shader-define gating and aligns Settings layout to 16 bytes.
src/Features/TerrainVariation.cpp Updates UI toggles to write uint32_t settings and removes vertex-desc “dirty” forcing.
src/Features/ExtendedMaterials.h Removes ExtendShadows and fixes Settings padding/alignment.
src/Features/ExtendedMaterials.cpp Drops JSON/UI handling for ExtendShadows.
package/Shaders/Lighting.hlsl Major landscape/parallax/TV integration changes; adds landscape blend helpers and terrain shadow caching.
package/Shaders/Common/SharedData.hlsli Removes ExtendShadows from shader-visible CPM settings and adjusts padding.
package/Shaders/Common/LightingLandscape.hlsli New shared landscape blending macro include to reduce duplicated per-layer code.
features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli Reworks TV stochastic sampling (2-sample blend, distance/minification fallbacks, LOD jitter helpers).
features/Terrain Variation/Shaders/Features/TerrainVariation.ini Bumps Terrain Variation feature version.
features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli Adds new parallax/shadow helpers, secant refinement, and terrain shadow evaluation helpers.

Comment thread package/Shaders/Common/LightingLandscape.hlsli Outdated
@davo0411

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review please be mean like doodlum and no niceties. Point out any magic numbers and sloppily written code. Suggest improvements where you feel appropriate. Suggest ideas to further reduce compile times

@github-actions

github-actions Bot commented Apr 28, 2026

Copy link
Copy Markdown

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

Comment thread features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli Outdated
@doodlum
doodlum marked this pull request as draft April 30, 2026 23:33
@davo0411
davo0411 marked this pull request as ready for review May 4, 2026 04:31

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (7)
features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli (2)

27-33: 💤 Low value

Consider documenting or removing offset3 from StochasticOffsets.

With the transition to a 2-sample model, offset3 is always set to 0 (lines 101, 118). The field is retained for struct compatibility, but this could confuse future maintainers who might expect it to be used.

Consider adding a comment explaining that offset3 is unused (kept for ABI stability), or remove it if no external consumers depend on the struct layout.

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

In `@features/Terrain` Variation/Shaders/TerrainVariation/TerrainVariation.hlsli
around lines 27 - 33, The struct StochasticOffsets contains an unused field
offset3 (always set to zero under the new 2-sample model); update the
declaration of StochasticOffsets to either (a) add a clear comment above offset3
explaining it is intentionally unused and kept only for ABI/struct
compatibility, referencing the struct name StochasticOffsets and the field
offset3, or (b) remove offset3 entirely if you confirm no external consumers
rely on the existing layout (search for StochasticOffsets usages before
removing). Ensure the chosen change is applied where StochasticOffsets is
defined so future maintainers understand why offset3 is present or has been
removed.

111-113: 💤 Low value

Magic numbers in hash computation.

Lines 111 and 113 use unexplained constants (255437.0, 127.0) for the LOD hash computation. While these are typical in hash functions, brief comments would help future maintainers understand the rationale (e.g., "large prime for uniform distribution" or "offset for second independent sample").

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

In `@features/Terrain` Variation/Shaders/TerrainVariation/TerrainVariation.hlsli
around lines 111 - 113, The hash computation uses unexplained magic constants
(255437.0 and 127.0) in the cellID and second sample; update the code around the
cellID calculation and the hashLOD calls to either replace these literals with
named constants (e.g., LARGE_PRIME_FOR_HASH and SECOND_SAMPLE_OFFSET) or add
brief comments above the lines mentioning why the values were chosen (e.g.,
"large prime for uniform distribution" and "offset for independent second
sample"), referencing the variables cellID, landscapeUV and the hashLOD(...)
calls so maintainers can locate and understand the rationale.
features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli (2)

735-737: 💤 Low value

Incorrect closing comment.

Line 736's comment says // defined(LANDSCAPE) && defined(TERRAIN_VARIATION) but this #endif closes the #if defined(LANDSCAPE) block that started at line 346 (and implicitly includes line 584). The TERRAIN_VARIATION part is not required for this guard.

♻️ Suggested fix
 #	undef TERRAIN_HEIGHT_AT
-#endif  // defined(LANDSCAPE) && defined(TERRAIN_VARIATION)
+#endif  // defined(LANDSCAPE)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@features/Extended`
Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli around lines 735 -
737, The closing preprocessor comment on the `#endif` after the `#undef`
TERRAIN_HEIGHT_AT is wrong: it references "defined(LANDSCAPE) &&
defined(TERRAIN_VARIATION)" but the block being closed is the `#if`
defined(LANDSCAPE) block (and not dependent on TERRAIN_VARIATION). Update the
comment on that `#endif` to accurately reflect the opening guard (e.g., //
defined(LANDSCAPE)) so the `#endif` matches the `#if` that began the LANDSCAPE
section; refer to the surrounding symbols (`#if` defined(LANDSCAPE),
TERRAIN_VARIATION, `#undef` TERRAIN_HEIGHT_AT) to locate the correct closing
directive.

619-628: 💤 Low value

Inconsistent tap-count thresholds between functions.

TerrainDirectionalShadowTapCount uses thresholds [0.7, 0.25, 0.0] while ParallaxShadowTapCount uses [0.75, 0.5, 0.25]. The inconsistency may be intentional (directional shadows use fewer taps), but the differing threshold values (0.7 vs 0.75, 0.25 vs 0.5) could benefit from a brief comment explaining the rationale.

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

In `@features/Extended`
Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli around lines 619 -
628, TerrainDirectionalShadowTapCount currently uses thresholds (0.7, 0.25, 0.0)
that differ from ParallaxShadowTapCount's (0.75, 0.5, 0.25); either align the
thresholds if this was accidental or add a concise comment above the
TerrainDirectionalShadowTapCount definition explaining the intentional rationale
(e.g., fewer taps for directional shadows, performance/quality tradeoffs and why
0.7/0.25 were chosen vs 0.75/0.5/0.25), referencing the function names
TerrainDirectionalShadowTapCount and ParallaxShadowTapCount so future readers
know the difference is deliberate.
package/Shaders/Lighting.hlsl (3)

2257-2268: 💤 Low value

Variable lightDirectionTS shadows outer declaration.

Line 2261 redeclares lightDirectionTS inside the conditional block, but it's already declared and computed at line 2252 with the same expression. This variable shadowing is unnecessary and could confuse maintainers.

♻️ Suggested fix
 			if (LANDSCAPE_PARALLAX_ENABLED) {
 				if (ExtendedMaterials::TerrainHasSignificantBlend(input.LandBlendWeights1, input.LandBlendWeights2.xy) && ExtendedMaterials::TerrainHasAnyDisplacement()) {
 					float terrainHeightScale = ExtendedMaterials::TerrainMaxWeightedHeightScale(input, displacementParams);
 					if (terrainHeightScale > 0.01) {
-						float3 lightDirectionTS = normalize(mul(refractedLightDirection, tbn).xyz);
 #					if defined(TERRAIN_VARIATION)
 						parallaxShadow = ExtendedMaterials::GetParallaxSoftShadowMultiplierTerrain(input, uv, terrainShadowMipLevels, lightDirectionTS, sh0, terrainDirectionalShadowQuality, screenNoise, displacementParams, sharedOffset);
 #					else
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/Shaders/Lighting.hlsl` around lines 2257 - 2268, The variable
lightDirectionTS is being redeclared inside the LANDSCAPE_PARALLAX_ENABLED
branch although it was already computed earlier (using
normalize(mul(refractedLightDirection, tbn).xyz);), causing shadowing; remove
the local re-declaration and reuse the previously declared lightDirectionTS
before calling ExtendedMaterials::GetParallaxSoftShadowMultiplierTerrain (and
keep the existing arguments: input, uv, terrainShadowMipLevels,
lightDirectionTS, sh0, terrainDirectionalShadowQuality, screenNoise,
displacementParams, sharedOffset) so behavior is unchanged.

1025-1029: 💤 Low value

Redundant assignment of terrainDirectionalShadowQuality.

On line 1026, terrainDirectionalShadowQuality is initialized to parallaxShadowQuality, and immediately on lines 1027-1029, it's conditionally reassigned to the same value when LANDSCAPE is defined. The second assignment is a no-op.

♻️ Suggested simplification
 	float parallaxShadowQuality = ExtendedMaterials::ParallaxNearShadowQuality;
-	float terrainDirectionalShadowQuality = parallaxShadowQuality;
-#		if defined(LANDSCAPE)
-	terrainDirectionalShadowQuality = ExtendedMaterials::ParallaxNearShadowQuality;
-#		endif
+	float terrainDirectionalShadowQuality = ExtendedMaterials::ParallaxNearShadowQuality;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/Shaders/Lighting.hlsl` around lines 1025 - 1029, The variable
terrainDirectionalShadowQuality is initialized to parallaxShadowQuality and then
conditionally reassigned to the same
ExtendedMaterials::ParallaxNearShadowQuality inside the LANDSCAPE block, which
is redundant; remove the conditional reassignment (the lines inside the `#if`
defined(LANDSCAPE) / `#endif` that set terrainDirectionalShadowQuality =
ExtendedMaterials::ParallaxNearShadowQuality) so terrainDirectionalShadowQuality
remains initialized from parallaxShadowQuality without a no-op repeat, or
alternatively move the initial assignment into the conditional and drop the
unconditional one—update references to parallaxShadowQuality,
terrainDirectionalShadowQuality, and the LANDSCAPE conditional accordingly.

1031-1036: 💤 Low value

Consider documenting implicit macro dependencies.

The COMPUTE_TERRAIN_SHADOW_BASE and EVAL_TERRAIN_DIR_SHADOW macros capture multiple variables implicitly (input, uv, terrainShadowMipLevels, terrainDirectionalShadowQuality, screenNoise, displacementParams, sharedOffset). While this reduces duplication, it makes the code harder to reason about.

A brief comment listing the expected variables in scope would help maintainability.

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

In `@package/Shaders/Lighting.hlsl` around lines 1031 - 1036, Add a short comment
above the COMPUTE_TERRAIN_SHADOW_BASE and EVAL_TERRAIN_DIR_SHADOW macro
definitions that lists the implicit variables those macros expect in scope
(e.g., input, uv, terrainShadowMipLevels, terrainDirectionalShadowQuality,
screenNoise, displacementParams, sharedOffset) and mention which
ExtendedMaterials functions they map to
(ExtendedMaterials::ComputeTerrainParallaxShadowBaseHeight and
ExtendedMaterials::EvaluateTerrainDirectionalParallaxShadowMultiplier) so future
readers can quickly see required context before the macros are used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@features/Extended`
Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli:
- Around line 735-737: The closing preprocessor comment on the `#endif` after the
`#undef` TERRAIN_HEIGHT_AT is wrong: it references "defined(LANDSCAPE) &&
defined(TERRAIN_VARIATION)" but the block being closed is the `#if`
defined(LANDSCAPE) block (and not dependent on TERRAIN_VARIATION). Update the
comment on that `#endif` to accurately reflect the opening guard (e.g., //
defined(LANDSCAPE)) so the `#endif` matches the `#if` that began the LANDSCAPE
section; refer to the surrounding symbols (`#if` defined(LANDSCAPE),
TERRAIN_VARIATION, `#undef` TERRAIN_HEIGHT_AT) to locate the correct closing
directive.
- Around line 619-628: TerrainDirectionalShadowTapCount currently uses
thresholds (0.7, 0.25, 0.0) that differ from ParallaxShadowTapCount's (0.75,
0.5, 0.25); either align the thresholds if this was accidental or add a concise
comment above the TerrainDirectionalShadowTapCount definition explaining the
intentional rationale (e.g., fewer taps for directional shadows,
performance/quality tradeoffs and why 0.7/0.25 were chosen vs 0.75/0.5/0.25),
referencing the function names TerrainDirectionalShadowTapCount and
ParallaxShadowTapCount so future readers know the difference is deliberate.

In `@features/Terrain` Variation/Shaders/TerrainVariation/TerrainVariation.hlsli:
- Around line 27-33: The struct StochasticOffsets contains an unused field
offset3 (always set to zero under the new 2-sample model); update the
declaration of StochasticOffsets to either (a) add a clear comment above offset3
explaining it is intentionally unused and kept only for ABI/struct
compatibility, referencing the struct name StochasticOffsets and the field
offset3, or (b) remove offset3 entirely if you confirm no external consumers
rely on the existing layout (search for StochasticOffsets usages before
removing). Ensure the chosen change is applied where StochasticOffsets is
defined so future maintainers understand why offset3 is present or has been
removed.
- Around line 111-113: The hash computation uses unexplained magic constants
(255437.0 and 127.0) in the cellID and second sample; update the code around the
cellID calculation and the hashLOD calls to either replace these literals with
named constants (e.g., LARGE_PRIME_FOR_HASH and SECOND_SAMPLE_OFFSET) or add
brief comments above the lines mentioning why the values were chosen (e.g.,
"large prime for uniform distribution" and "offset for independent second
sample"), referencing the variables cellID, landscapeUV and the hashLOD(...)
calls so maintainers can locate and understand the rationale.

In `@package/Shaders/Lighting.hlsl`:
- Around line 2257-2268: The variable lightDirectionTS is being redeclared
inside the LANDSCAPE_PARALLAX_ENABLED branch although it was already computed
earlier (using normalize(mul(refractedLightDirection, tbn).xyz);), causing
shadowing; remove the local re-declaration and reuse the previously declared
lightDirectionTS before calling
ExtendedMaterials::GetParallaxSoftShadowMultiplierTerrain (and keep the existing
arguments: input, uv, terrainShadowMipLevels, lightDirectionTS, sh0,
terrainDirectionalShadowQuality, screenNoise, displacementParams, sharedOffset)
so behavior is unchanged.
- Around line 1025-1029: The variable terrainDirectionalShadowQuality is
initialized to parallaxShadowQuality and then conditionally reassigned to the
same ExtendedMaterials::ParallaxNearShadowQuality inside the LANDSCAPE block,
which is redundant; remove the conditional reassignment (the lines inside the
`#if` defined(LANDSCAPE) / `#endif` that set terrainDirectionalShadowQuality =
ExtendedMaterials::ParallaxNearShadowQuality) so terrainDirectionalShadowQuality
remains initialized from parallaxShadowQuality without a no-op repeat, or
alternatively move the initial assignment into the conditional and drop the
unconditional one—update references to parallaxShadowQuality,
terrainDirectionalShadowQuality, and the LANDSCAPE conditional accordingly.
- Around line 1031-1036: Add a short comment above the
COMPUTE_TERRAIN_SHADOW_BASE and EVAL_TERRAIN_DIR_SHADOW macro definitions that
lists the implicit variables those macros expect in scope (e.g., input, uv,
terrainShadowMipLevels, terrainDirectionalShadowQuality, screenNoise,
displacementParams, sharedOffset) and mention which ExtendedMaterials functions
they map to (ExtendedMaterials::ComputeTerrainParallaxShadowBaseHeight and
ExtendedMaterials::EvaluateTerrainDirectionalParallaxShadowMultiplier) so future
readers can quickly see required context before the macros are used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e416c1af-4478-4a0b-a78b-1dd58c13a03b

📥 Commits

Reviewing files that changed from the base of the PR and between 2a8cb8f and 0e17ca6.

📒 Files selected for processing (6)
  • features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli
  • features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/Lighting.hlsl
  • src/Features/TerrainVariation.cpp
  • src/Features/TerrainVariation.h

alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 20, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 20, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 20, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 20, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 20, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 20, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 21, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 21, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 21, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 21, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 21, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 21, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
@doodlum

doodlum commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review this source code, will it improve performance?

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== Changed files and statistics ==='
git diff --stat HEAD^ HEAD
git diff --name-status HEAD^ HEAD

echo
echo '=== Outline: core parallax implementation ==='
ast-grep outline 'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsParallaxCore.hlsli' --items all --view expanded

echo
echo '=== Outline: terrain implementation ==='
ast-grep outline 'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli' --items all --view expanded

echo
echo '=== Outline: lighting integration ==='
ast-grep outline package/Shaders/Lighting.hlsl --items all --view expanded

echo
echo '=== Targeted performance-relevant diff ==='
git diff --unified=80 HEAD^ HEAD -- \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsParallaxCore.hlsli' \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli' \
  'features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli' \
  package/Shaders/Lighting.hlsl \
  package/Shaders/Common/LightingLandscape.hlsli \
  package/Shaders/Common/SharedData.hlsli \
  src/Features/ExtendedMaterials.cpp \
  src/Features/ExtendedMaterials.h \
  src/Features/TerrainVariation.cpp \
  src/Features/TerrainVariation.h

Length of output: 3172


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='community-shaders/skyrim-community-shaders'
pr=2220

echo '=== PR head/base metadata ==='
gh pr view "$pr" --repo "$repo" --json number,title,baseRefName,headRefName,baseRefOid,headRefOid,commits \
  --jq '{number,title,base:.baseRefName,head:.headRefName,baseOid:.baseRefOid,headOid:.headRefOid,commits:[.commits[]|{oid:.oid,messageHeadline:.messageHeadline}]}'

echo
echo '=== PR changed files ==='
gh api "repos/$repo/pulls/$pr/files?per_page=100" --paginate --jq '.[] | [.status, .filename, (.additions|tostring), (.deletions|tostring)] | `@tsv`'

echo
echo '=== Local checkout identity and available refs ==='
git rev-parse HEAD
git branch -a --no-color | sed -n '1,100p'
git remote -v

echo
echo '=== Locate expected shader files in this checkout (if present under a different path) ==='
fd -HI 'ExtendedMaterialsParallaxCore\.hlsli|ExtendedMaterialsTerrain\.hlsli|Lighting\.hlsl|TerrainVariation\.hlsli' . | sed -n '1,120p'

Length of output: 10463


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='04482fcbc1746bd1f6875723180dd5e03e7e05d7'
head='5c591c25c6ab413447b924245569852f2aff428e'

echo '=== Aggregate diff: parallax core ==='
git diff --unified=35 "$base...$head" -- \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsParallaxCore.hlsli'

echo
echo '=== Aggregate diff: terrain + terrain variation ==='
git diff --unified=30 "$base...$head" -- \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli' \
  'features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli'

echo
echo '=== Aggregate diff: lighting call sites and layer blending ==='
git diff --unified=35 "$base...$head" -- \
  package/Shaders/Lighting.hlsl \
  package/Shaders/Common/LightingLandscape.hlsli

echo
echo '=== Current implementation: key symbols and call sites ==='
rg -n -C 12 \
  'GetParallaxCoords\s*\(|GetParallaxSoftShadowMultiplier\s*\(|GetTerrainHeight\s*\(|GetTerrainHeightQuadRayMarch\s*\(|ComputeTerrainParallaxShadowBaseHeight\s*\(|EvaluateTerrain(Directional)?ParallaxShadowMultiplier\s*\(|TerrainMaxWeightedHeightScale\s*\(|TerrainHasSignificantBlend\s*\(' \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsParallaxCore.hlsli' \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli' \
  package/Shaders/Lighting.hlsl

echo
echo '=== Loop context around lighting and expensive terrain/parallax calls ==='
rg -n -C 20 \
  'for\s*\(|while\s*\(|GetTerrainHeight\s*\(|EvaluateTerrain(Directional)?ParallaxShadowMultiplier\s*\(|GetParallaxSoftShadowMultiplier\s*\(' \
  package/Shaders/Lighting.hlsl

Length of output: 198125


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='04482fcbc1746bd1f6875723180dd5e03e7e05d7'

echo '=== Base: original parallax and terrain code ==='
git show "$base:features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli" \
  | rg -n -C 20 \
    'GetParallaxCoords\s*\(|GetParallaxSoftShadowMultiplier\s*\(|GetTerrainHeight\s*\(|GetTerrainHeightQuadRayMarch\s*\(|StochasticEffectParallax\s*\(|StochasticEffect\s*\(|GetMipLevel\s*\('

echo
echo '=== Current: include placement, mip helpers, and tuning values ==='
rg -n -C 12 \
  '`#include`|GetMipLevel\s*\(|GetMipLevelFromDims\s*\(|ComputeParallaxMarchMip\s*\(|ParallaxCheapDistance|ParallaxNearShadowQuality|ParallaxFarShadowQuality|TerrainParallaxShadowMaxMipLevel|ParallaxShadowTapCount\s*\(' \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterials.hlsli' \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsParallaxCore.hlsli' \
  'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli'

echo
echo '=== Line-numbered hot paths for review findings ==='
nl -ba 'features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli' \
  | sed -n '315,395p'
nl -ba package/Shaders/Lighting.hlsl | sed -n '1178,1240p'
nl -ba package/Shaders/Lighting.hlsl | sed -n '2318,2350p'
nl -ba 'features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli' | sed -n '115,205p'

echo
echo '=== Settings layouts and writer-side synchronization ==='
rg -n -C 10 \
  'struct.*Settings|TerrainVariationSettings|enableLODTerrainTilingFix|enableTilingFix|ExtendShadows|UpdateShaderSettings' \
  package/Shaders/Common/SharedData.hlsli \
  src/Features/TerrainVariation.h \
  src/Features/TerrainVariation.cpp \
  src/Features/ExtendedMaterials.h \
  src/Features/ExtendedMaterials.cpp

Length of output: 49788


The PR description image 1 is a hand-drawn secant-interpolation diagram. It derives r = h1 / (h1 - h2) from two height samples, with h1, h2, r, and 1-r marked along the ray/surface construction.

The PR description image 2 is a CAPFRAMEX chart comparing new with dev. new reports 115.2 average FPS and 96.5 1% low, versus 110.7 and 86.4 for dev; its 0.1% low is worse at 75.7 vs 78.1. The captures are only 11.99 seconds each.

@doodlum Yes—the source has credible performance improvements, but it is not an unconditional win for every landscape scene.

Changes that should improve GPU performance

  1. Terrain Variation: 3 samples → 2, sometimes 1

    • StochasticEffect and StochasticEffectParallax in features/Terrain Variation/Shaders/TerrainVariation/TerrainVariation.hlsli now take two samples instead of three.
    • When w2Contrast <= 0, the second fetch is skipped entirely.
    • This is the clearest direct saving. Terrain layers can be sampled many times per pixel, so removing one-third of stochastic texture fetches is meaningful.
  2. Terrain parallax shadows are dramatically cheaper

    • The old terrain shadow path performed 1–4 full terrain-height evaluations depending on quality. Each evaluation can sample several terrain layers.
    • The new directional and point-light terrain shadow helpers use one height evaluation.
    • Directional terrain shadowing is additionally computed once and cached before directional lighting is evaluated, rather than recomputed in that later phase.
    • This is likely the largest benefit in terrain with parallax shadows enabled.
  3. Six mip calculations collapse into one

    • The old landscape path called GetMipLevel for all six terrain color maps.
    • InitializeTerrainMipLevels now does one GetDimensions/derivative-based mip calculation and copies the result to all six layers.
    • This reduces ALU and texture-metadata operations, though it assumes the terrain layers have comparable texture dimensions.
  4. POM marching is likely cheaper on average

    • The new marcher uses a coarser march mip, four-position batches, early intersection detection, and only 1–2 secant refinements after 2–4 contact refinements.
    • Compared with the prior linear refinement behavior, this should reduce expensive high-detail terrain-height work in typical cases.
    • It is still not free: a grazing-angle, highly blended six-layer terrain pixel can be expensive. The dynamic 4–32 step range means worst-case cost remains high.

What prevents calling this a universal win

  • The benchmark is one ~12-second capture per build. It demonstrates a promising +4.1% average FPS and +11.7% 1% low, but its 0.1% low regresses by ~3.1%. Repeat several captures after warm-up, use identical weather/camera movement, and report median plus variance.
  • Actual GPU cost depends strongly on:
    • active terrain-layer count;
    • Terrain Variation and POM settings;
    • viewing angle;
    • nearby point lights;
    • texture cache behavior;
    • register pressure after compilation.

Remaining hot-path issue

package/Shaders/Lighting.hlsl Lines 2338-2345 performs terrain eligibility checks for every point light:

  • TerrainHasSignificantBlend(...)
  • TerrainHasAnyDisplacement()
  • TerrainMaxWeightedHeightScale(...)

The first and third are pixel-invariant after the terrain setup. Compute them once before the point-light loop, for example as hasTerrainParallaxShadow, then have each light only test its light-specific conditions.

Moreover, TerrainHasSignificantBlend in features/Extended Materials/Shaders/ExtendedMaterials/ExtendedMaterialsTerrain.hlsli Lines 316-319 is ineffective:

return (w1.x + w1.y + w1.z + w1.w + w2.x + w2.y) > 0.01;

The weights were normalized earlier, so their sum is normally 1.0. This does not detect a meaningful multi-layer blend; it merely detects that the pixel has terrain weights at all. Either remove it or replace it with a test such as “at least two weights exceed a threshold” if the optimization specifically targets blended terrain.

Also, lightDirectionTS is normalized at Line 2333 and normalized again at Line 2342 in the landscape branch. Reuse the first value.

Verdict

Yes, this PR should improve runtime performance in the intended Terrain Variation + terrain-parallax workloads. The two strongest reasons are the 2-tap/1-tap stochastic sampling and the single-tap cached terrain shadowing. The CAPFRAMEX result is consistent with that.

The remaining point-light-loop work should be hoisted before claiming the implementation is fully optimized, and the performance claim needs repeated GPU profiling to verify that reduced texture work was not offset by register pressure or divergence.

alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 22, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 22, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 22, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 22, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 22, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 22, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 23, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 23, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 23, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 23, 2026
Squashed sync of community-shaders#2220:
a full rework of Extended Materials parallax (secant-stepping
march) and Terrain Variation (deterministic 2-sample stochastic
blend), plus a landscape-layer-blend refactor split out of
Lighting.hlsl into LightingLandscape.hlsli /
ExtendedMaterialsParallaxCore.hlsli / ExtendedMaterialsTerrain.hlsli.

1. Refactored lighting/landscape layers to facilitate small compiler
   wins for terrain variation (TV) and PBR, reducing branching
   inside lighting.hlsl.
2. Adopted secant stepping instead of linear for parallax occlusion
   mapping, per graphics discord discussion.
3. Full terrain variation rework: now always takes 2 samples.
4. General comment/code cleanup and magic-number fixes.

Fork-specific adaptations (VR mip bias, distance-based parallax
quality falloff, dead-code cleanup, standards fixes) are layered on
top as separate commits, not part of this squashed import.

Co-Authored-By: davo0411 <davidkehoe0411@outlook.com>
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 23, 2026
Upstream PR 2220 made ExtendedMaterials::GetMipLevel deterministic
(dropped the screen-noise dither), which silently swallowed our
second VR-only mip bump alongside it. VR's texel-density halving at
the top of the function survived the merge; this restores the
additive mipLevel++ that ran after log2() as well, matching our
prior VR-conservative mip bias.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
alandtse added a commit to alandtse/open-shaders that referenced this pull request Jul 23, 2026
Upstream PR 2220's secant-stepping rewrite of GetParallaxCoords
dropped the distance-parameterized near/far quality falloff that
had landed on our dev independently after the PR's base (upstream
removed it entirely as part of the rework, calling it "distance
shenanigans" in their own history). The new mip-based step scaling
serves a related purpose for near/mid distances, but had no hard
cutoff for far geometry, silently regressing the cost savings on
distant terrain/meshes.

Restores the `distance` parameter, a far-distance early-out (skip
the march entirely past the cutoff), and a smooth near-band blend
of the final result and pixel offset so the transition doesn't pop.

The far-distance early-out also needs an exception: pre-merge dev's
GetParallaxCoords always ran the march for TRUE_PBR materials
flagged PBR::Flags::InterlayerParallax regardless of distance (it
has no distance-cheap approximation), so the restored cutoff
carries that bypass in the non-LANDSCAPE TRUE_PBR path.

Part of syncing community-shaders#2220
("perf: terrain variation & parallax", davo0411).
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.

3 participants