Skip to content

fix: vegetation issues#2303

Merged
alandtse merged 9 commits into
devfrom
vegetation-fixes
May 10, 2026
Merged

fix: vegetation issues#2303
alandtse merged 9 commits into
devfrom
vegetation-fixes

Conversation

@doodlum
Copy link
Copy Markdown
Collaborator

@doodlum doodlum commented May 9, 2026

ScreenShot370
  • Fixed grass collision crash by queuing grass collision with nullsub hook, when all game threads should be synced with main
  • Fixed grass too dark by using soft lighting instead of back lighting
  • Fixed lod blending vertex color option not working, added back setting that made vertexcolor on landscape be colors only, not brightness

Summary by CodeRabbit

  • Bug Fixes

    • Improved grass lighting and subsurface scattering for more consistent visuals.
    • Refined terrain vertex color handling for stable appearance.
  • Changes

    • Removed the "wrapped lighting" option from grass lighting controls.
    • Increased default subsurface scattering intensity.
    • Switched grass collision processing to a queued approach for better performance.
  • Chores

    • Bumped shader feature configuration version.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR removes the EnableWrappedLighting toggle, refactors grass lighting to use a soft-light subsurface helper and always-use saturate diffuse, applies DisableTerrainVertexColors across shader paths, updates shader VS/PS color IO, and changes GrassCollision to queue traversal results for upload with a main-update hook and FLOAT collision texture format.

Changes

Grass Lighting and Collision Refactor

Layer / File(s) Summary
Shader Data Contracts
package/Shaders/Common/SharedData.hlsli, src/Features/GrassLighting.h, features/Grass Lighting/Shaders/Features/GrassLighting.ini
Removes EnableWrappedLighting from HLSL struct and C++ settings; changes padding to float2; updates SubsurfaceScatteringAmount default; increments INI version.
C++ Settings and UI
src/Features/GrassLighting.cpp
Removes EnableWrappedLighting from JSON serialization macro and deletes the ImGui "Enable Wrapped Lighting" checkbox/tooltip.
Subsurface Scattering Helper
package/Shaders/RunGrass.hlsl
Adds GetSoftLightMultiplier(angle, rolloff) helper for soft subsurface curve.
Lighting Calculations
package/Shaders/RunGrass.hlsl
Directional and point-light diffuse always use saturate(angle); subsurface uses GetSoftLightMultiplier with rolloff from vertex data; final subsurface accumulation uses subsurfaceColor * albedo.
Terrain Vertex Color Handling
package/Shaders/Lighting.hlsl, package/Shaders/RunGrass.hlsl
Applies DisableTerrainVertexColors logic: forces input.Color.xyz = 1 when enabled, otherwise normalizes input.Color by max RGB with EPSILON_DIVISION; updates VS/PS IO to use Color: COLOR0 and stores per-instance fade in Color.w.
Collision Queue State
src/Features/GrassCollision.h
Adds queuedBoundingBoxes and queuedCollisions vectors to stage traversal results.
Collision Processing Methods
src/Features/GrassCollision.h
Replaces UpdateCollisions(PerFrame&) with QueueCollisions(); adds MainUpdate_QueueCollisions thunk and registers it during hook installation.
Collision Traversal Logic
src/Features/GrassCollision.cpp
Traverses and accumulates local collision data, then moves containers into queued vectors behind EnableGrassCollision instead of writing GPU buffers during traversal.
Collision Queue Upload and Cleanup
src/Features/GrassCollision.cpp
Update() sets perFrameData.BoundingBoxCount from queued size, uploads queued data to D3D buffers conditionally when non-empty, clears queues, and removes old per-frame UpdateCollisions call site.
Collision Texture Format and Hook Implementation
src/Features/GrassCollision.cpp
Changes collision texture format to DXGI_FORMAT_R16G16B16A16_FLOAT and implements the main-update thunk to call QueueCollisions().

Sequence Diagram (high-level interaction between traversal, queue, update, GPU, and shaders):

sequenceDiagram
  participant Traversal
  participant Queues
  participant Update
  participant GPU
  participant Shader
  Traversal->>Queues: stage bounding boxes & collisions
  Update->>Queues: read queued data and sizes
  Update->>GPU: upload structured buffers (if non-empty)
  GPU->>Shader: shaders read updated buffers at draw time
Loading

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

Suggested Reviewers

  • alandtse

"A rabbit hops through shader code with glee,
Wrapping lights away — now diffuse runs free.
Soft subsurface glows, vertex colors aligned,
Queued collisions upload, buffers redesigned. ✨🐰"

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

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.
Title check ❓ Inconclusive The title 'fix: vegetation issues' is overly vague and does not clearly describe the specific changes made. The PR addresses multiple distinct issues including grass collision, lighting behavior, and vertex color blending, but the title uses generic phrasing that lacks meaningful specificity. Consider a more specific title such as 'fix: grass collision crash and improve grass lighting' or 'fix: grass collision, lighting, and vertex color issues' to better convey the main changes to reviewers scanning the history.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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
  • Commit unit tests in branch vegetation-fixes

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
package/Shaders/RunGrass.hlsl (1)

619-623: 💤 Low value

Redundant saturate() call.

The wrappedDirLight is already guaranteed to be in [0,1] range since the numerator uses saturate() and the denominator is ≥1. The outer saturate() on line 622 is unnecessary.

♻️ Suggested simplification
 	float wrapAmount = saturate(input.VertexNormal.w * 10.0) * 0.5;

 	float wrappedDirLight = saturate(dirLightAngle + wrapAmount) / (1.0 + wrapAmount);
-	lightsDiffuseColor += dirLightColor * dirDetailedShadow * saturate(wrappedDirLight) * Color::VanillaNormalization();
+	lightsDiffuseColor += dirLightColor * dirDetailedShadow * wrappedDirLight * Color::VanillaNormalization();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package/Shaders/RunGrass.hlsl` around lines 619 - 623, The call to saturate
on wrappedDirLight is redundant because wrappedDirLight is computed from
saturate(dirLightAngle + wrapAmount) / (1.0 + wrapAmount) which already produces
a value in [0,1]; remove the outer saturate and use wrappedDirLight directly in
the multiply that updates lightsDiffuseColor (the expression involving
wrappedDirLight, dirLightColor, dirDetailedShadow, and
Color::VanillaNormalization())—adjust the line that currently multiplies by
saturate(wrappedDirLight) to multiply by wrappedDirLight instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Features/GrassCollision.cpp`:
- Line 191: The variable `context` (initialized from `globals::d3d::context`) is
declared twice in the same scope causing a redefinition error; remove the
duplicate declaration and reuse the existing `context` variable instead (either
delete the later `auto context = globals::d3d::context;` or delete this earlier
one and ensure all uses reference the single consolidated `context`), updating
any subsequent usages in the `GrassCollision` function so they refer to the
single `context` identifier.

---

Nitpick comments:
In `@package/Shaders/RunGrass.hlsl`:
- Around line 619-623: The call to saturate on wrappedDirLight is redundant
because wrappedDirLight is computed from saturate(dirLightAngle + wrapAmount) /
(1.0 + wrapAmount) which already produces a value in [0,1]; remove the outer
saturate and use wrappedDirLight directly in the multiply that updates
lightsDiffuseColor (the expression involving wrappedDirLight, dirLightColor,
dirDetailedShadow, and Color::VanillaNormalization())—adjust the line that
currently multiplies by saturate(wrappedDirLight) to multiply by wrappedDirLight
instead.
🪄 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 Plus

Run ID: e5d2d346-92cb-445e-9f16-5761f5e4c3ab

📥 Commits

Reviewing files that changed from the base of the PR and between 58d53e3 and 3312087.

📒 Files selected for processing (9)
  • package/Shaders/Common/LightingCommon.hlsli
  • package/Shaders/Common/LightingEval.hlsli
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/Lighting.hlsl
  • package/Shaders/RunGrass.hlsl
  • src/Features/GrassCollision.cpp
  • src/Features/GrassCollision.h
  • src/Features/GrassLighting.cpp
  • src/Features/GrassLighting.h
💤 Files with no reviewable changes (1)
  • src/Features/GrassLighting.cpp

Comment thread src/Features/GrassCollision.cpp
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/Features/GrassCollision.cpp (1)

191-212: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove the duplicated collision-upload wrapper.

There’s an extra if (!queuedCollisions.empty()) { here. That leaves the braces unbalanced and pushes the later context declaration into the wrong scope, so this version of Update() will not compile.

Proposed fix
-		if (!queuedCollisions.empty()) {
-			auto context = globals::d3d::context;
-			D3D11_MAPPED_SUBRESOURCE mapped;
-
-		if (!queuedCollisions.empty()) {
+		auto context = globals::d3d::context;
+
+		if (!queuedCollisions.empty()) {
 			D3D11_MAPPED_SUBRESOURCE mapped;
 			DX::ThrowIfFailed(context->Map(collisionInstances->resource.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped));
 			size_t bytes = sizeof(float4) * queuedCollisions.size();
 			memcpy_s(mapped.pData, bytes, queuedCollisions.data(), bytes);
 			context->Unmap(collisionInstances->resource.get(), 0);
@@
 		queuedBoundingBoxes.clear();
 		queuedCollisions.clear();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Features/GrassCollision.cpp` around lines 191 - 212, The duplicate if
wrapper around queuedCollisions should be removed so braces and scope are
correct: delete the extra "if (!queuedCollisions.empty()) {" and its unmatched
brace so the single collision upload block uses the already-declared context and
maps collisionInstances correctly; ensure the block that maps collisionInstances
(using DX::ThrowIfFailed(context->Map(collisionInstances->resource.get(), ...)))
is the only check for queuedCollisions, and that the subsequent mapping of
collisionBoundingBoxes (using collisionBoundingBoxes,
perFrameData.BoundingBoxCount, queuedBoundingBoxes) remains intact before
clearing queuedBoundingBoxes and queuedCollisions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/Features/GrassCollision.cpp`:
- Around line 191-212: The duplicate if wrapper around queuedCollisions should
be removed so braces and scope are correct: delete the extra "if
(!queuedCollisions.empty()) {" and its unmatched brace so the single collision
upload block uses the already-declared context and maps collisionInstances
correctly; ensure the block that maps collisionInstances (using
DX::ThrowIfFailed(context->Map(collisionInstances->resource.get(), ...))) is the
only check for queuedCollisions, and that the subsequent mapping of
collisionBoundingBoxes (using collisionBoundingBoxes,
perFrameData.BoundingBoxCount, queuedBoundingBoxes) remains intact before
clearing queuedBoundingBoxes and queuedCollisions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 470558b2-bee2-4d59-a888-11bab92cfb3f

📥 Commits

Reviewing files that changed from the base of the PR and between 3312087 and 91a1b58.

📒 Files selected for processing (1)
  • src/Features/GrassCollision.cpp

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 9, 2026

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package/Shaders/Lighting.hlsl`:
- Around line 2896-2901: The DisableTerrainVertexColors branch is applied too
late and only removes tint after vertexAO/skylightingDiffuse have already been
derived from the original vertexColor; move the terrain-vertex-color override
(the SharedData::lodBlendingSettings.DisableTerrainVertexColors check that sets
vertexColor = 1 or normalizes it) to before the skylight AO/sky lighting diffuse
calculations (where vertexAO and skylightingDiffuse are computed, under
LANDSCAPE and SKYLIGHTING permutations), or alternatively ensure
vertexAO/skylightingDiffuse are recomputed from the modified vertexColor
immediately after this branch so skylight darkening respects
DisableTerrainVertexColors.

In `@package/Shaders/RunGrass.hlsl`:
- Around line 750-752: The soft-light/subsurface term is being tinted by albedo
twice (subsurfaceColor * albedo on line with subsurfaceColor, then whole
diffuseColor *= albedo), causing albedo² darkening; fix by applying albedo only
once — either remove the * albedo from the subsurface addition (change
"diffuseColor += subsurfaceColor * albedo" to "diffuseColor += subsurfaceColor")
or move the final albedo multiplication so it only multiplies the intended base
diffuse contribution rather than re-tinting the subsurface term (adjust use of
diffuseColor *= albedo accordingly), referencing the diffuseColor,
directionalAmbientColor, subsurfaceColor and albedo symbols.
🪄 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 Plus

Run ID: 03e7b54d-66cd-4af9-9cab-0a31dfaf975d

📥 Commits

Reviewing files that changed from the base of the PR and between d0a2aea and cecf671.

📒 Files selected for processing (3)
  • package/Shaders/Lighting.hlsl
  • package/Shaders/RunGrass.hlsl
  • src/Features/GrassLighting.h

Comment thread package/Shaders/Lighting.hlsl Outdated
Comment thread package/Shaders/RunGrass.hlsl
@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator

what is the reason to remove the wrapped lighting toggle?

@doodlum
Copy link
Copy Markdown
Collaborator Author

doodlum commented May 10, 2026

what is the reason to remove the wrapped lighting toggle?

soft lighting is the vanilla form of wrapped lighting

@alandtse alandtse changed the title fix: fix vegetation issues fix: vegetation issues May 10, 2026
Comment thread src/Features/GrassCollision.h Outdated
Copy link
Copy Markdown
Collaborator

@alandtse alandtse left a comment

Choose a reason for hiding this comment

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

Please add the VR offset and should be good.

@alandtse alandtse merged commit 52c493e into dev May 10, 2026
12 checks passed
SkrubbySkrubInAShrub pushed a commit that referenced this pull request May 14, 2026
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
ParticleTroned pushed a commit to ParticleTroned/skyrim-community-shaders that referenced this pull request May 15, 2026
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
ParticleTroned pushed a commit to ParticleTroned/skyrim-community-shaders that referenced this pull request May 16, 2026
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
IgorAlanAlbuquerque pushed a commit to IgorAlanAlbuquerque/skyrim-community-shaders that referenced this pull request May 29, 2026
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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