Skip to content

feat(grass lighting): grass sphere normal feature flag and fixes#1483

Merged
doodlum merged 4 commits into
devfrom
grass-sphere
Sep 18, 2025
Merged

feat(grass lighting): grass sphere normal feature flag and fixes#1483
doodlum merged 4 commits into
devfrom
grass-sphere

Conversation

@doodlum
Copy link
Copy Markdown
Collaborator

@doodlum doodlum commented Sep 17, 2025

Summary by CodeRabbit

  • New Features

    • Added a grass normal handling option that preserves original normals when effect lighting is active, improving lighting fidelity on grass.
  • Performance

    • Simplified grass shader paths by removing unused grass PBR permutations, reducing permutation count and potential compile time.
  • Bug Fixes

    • More consistent propagation of effect lighting to grass, ensuring visuals match lighting settings.
    • Improved geometry state handling for lighting/effect features to prevent stale flags.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 17, 2025

Walkthrough

Introduces a new GrassSphereNormal bit in shader permutation/state, conditionally alters grass normal handling in RunGrass.hlsl, adds grass-related engine hooks to propagate lighting to the new flag, and removes prior Grass PBR permutation and hook logic from TruePBR.cpp. Minor casting/log changes and enum expansion included.

Changes

Cohort / File(s) Summary of Changes
Permutation flags
package/Shaders/Common/Permutation.hlsli
Added Permutation::ExtraFlags::GrassSphereNormal = (1 << 5) to the flags bitfield.
Grass shader normal handling
package/Shaders/RunGrass.hlsl
Included Common/Permutation.hlsli. Wrapped backface normal flip and z-clamp/normalize so they run only when GrassSphereNormal is not set; behavior unchanged otherwise.
Engine hooks and grass extensions
src/Hooks.cpp
Standardized bit handling (clear-then-set, static_cast<uint32_t>). Adjusted Effect and Lighting setup geometry paths. Added GrassExtensions hooks: propagate kEffectLighting to grass property ctor and set/clear GrassSphereNormal during grass setup. Wired new hooks into install flow.
State descriptor enum
src/State.h
Added State::ExtraShaderDescriptors::GrassSphereNormal = 1 << 5; updated enum punctuation.
Removal of Grass PBR paths
src/TruePBR.cpp
Removed Grass-specific PBR permutation generation and multiple Grass shader hooks and registrations; retained non-Grass paths.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Game
  participant Engine as Engine Hooks
  participant GrassProp as BSGrassShaderProperty_ctor
  participant GrassSetup as BSGrassShader_SetupGeometry
  participant Shader as RunGrass.hlsl

  Game->>Engine: Load/Init
  Engine->>GrassProp: Intercept ctor
  Note right of GrassProp: If linked Lighting has kEffectLighting,<br/>enable kEffectLighting on Grass property
  GrassProp-->>Engine: Return property

  Game->>GrassSetup: SetupGeometry(pass, renderFlags)
  Note right of GrassSetup: Clear GrassSphereNormal<br/>Set GrassSphereNormal if property has kEffectLighting
  GrassSetup-->>Shader: Draw call with ExtraShaderDescriptor

  Shader->>Shader: If (ExtraShaderDescriptor & GrassSphereNormal) == 0
  Note right of Shader: Apply backface flip and clamp/normalize z
  Shader-->>Game: Shaded grass pixels
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • jiayev
  • alandtse
  • Pentalimbed

Poem

A meadow of bits in the twilight’s glow,
I twitch my ears where the shaders grow.
Flip or no flip? A flag says “proceed!” 🐇
Grass hums softly to lighting’s lead.
Old trails trimmed, new hooks in the breeze—
I hop through normals with effortless ease. 🌿

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary work in the changeset—adding a GrassSphereNormal feature flag and related grass lighting fixes across shaders and hooks—using a clear scope ("grass lighting") and concise phrasing that a reviewer can scan for context.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch grass-sphere

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.

@doodlum doodlum changed the title feat: grass sphere normal feature flag and flag fixes feat: grass sphere normal feature flag and fixes Sep 17, 2025
Automated formatting by clang-format, prettier, and other hooks.
See https://pre-commit.ci for details.
@github-actions
Copy link
Copy Markdown

Using provided base ref: 28c1112
Using base ref: 28c1112
Base commit date: 2025-09-17T15:33:07+01:00 (Wednesday, September 17, 2025 03:33 PM)
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)

503-510: Make flag test explicit and remove redundant clamp.

HLSL prefers boolean conditions; compare to 0 to avoid warnings. Also, normal.z is clamped twice; keep just one.

Apply:

-    if (!(Permutation::ExtraShaderDescriptor & Permutation::ExtraFlags::GrassSphereNormal)) {
-        if (!frontFace)
-            normal = -normal;
-
-        normal.z = max(0.0, normal.z);
-        normal = normalize(float3(normal.xy, max(0, normal.z)));
-    }
+    if ((Permutation::ExtraShaderDescriptor & Permutation::ExtraFlags::GrassSphereNormal) == 0) {
+        if (!frontFace)
+            normal = -normal;
+        // Clamp Z once and renormalize
+        normal = normalize(float3(normal.xy, max(0.0, normal.z)));
+    }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28c1112 and f6276dd.

📒 Files selected for processing (4)
  • package/Shaders/Common/Permutation.hlsli (1 hunks)
  • package/Shaders/RunGrass.hlsl (2 hunks)
  • src/Hooks.cpp (3 hunks)
  • src/State.h (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{cpp,cxx,cc,c,h,hpp,hxx,hlsl,hlsli,fx,fxh,py}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not include TODO/FIXME placeholders; provide complete, working solutions

Files:

  • package/Shaders/Common/Permutation.hlsli
  • package/Shaders/RunGrass.hlsl
  • src/State.h
  • src/Hooks.cpp
src/**/*.{cpp,cxx,cc,h,hpp,hxx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{cpp,cxx,cc,h,hpp,hxx}: Ensure SE/AE/VR runtime compatibility; use runtime detection patterns (e.g., REL::RelocateMember())
Include robust error handling and resource management with graceful degradation in the plugin code

Files:

  • src/State.h
  • src/Hooks.cpp
🧠 Learnings (1)
📚 Learning: 2025-08-05T17:40:44.828Z
Learnt from: ThePagi
PR: doodlum/skyrim-community-shaders#1369
File: package/Shaders/Lighting.hlsl:0-0
Timestamp: 2025-08-05T17:40:44.828Z
Learning: In the skyrim-community-shaders repository, ultra trees (object LOD trees) are detected using a compound shader define condition `defined(DO_ALPHA_TEST) && defined(LOD_BLENDING) && defined(RIM_LIGHTING) && defined(SOFT_LIGHTING)` because "they have no define" according to the comment. The `ExtraFlags::IsTree` flag is used for different tree handling (AO removal in skylighting) and may not apply to ultra trees specifically. Before replacing the compound condition with `IsTree`, verification is needed to ensure the flag covers ultra trees.

Applied to files:

  • package/Shaders/Common/Permutation.hlsli
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Build plugin and addons
🔇 Additional comments (7)
package/Shaders/Common/Permutation.hlsli (1)

64-65: New permutation bit looks correct; confirm cross-language sync.

Bit 1<<5 does not overlap existing ExtraFlags. Please confirm this stays in sync with src/State.h::ExtraShaderDescriptors::GrassSphereNormal (also 1<<5).

src/State.h (1)

152-154: Enum mapping aligns with HLSL; keep synchronized.

The C++ bit (1<<5) matches the HLSL flag. Consider adding a brief comment “must match Permutation::ExtraFlags::GrassSphereNormal”.

package/Shaders/RunGrass.hlsl (1)

8-8: Including Permutation.hlsli is appropriate.

Enables access to ExtraShaderDescriptor/flags with no register conflicts (uses b4).

src/Hooks.cpp (4)

171-182: EffectShadows bit handling is fine.

Clear-then-set pattern avoids stale state; cast hygiene is good.


195-205: IsTree flag set/clear logic LGTM.

Uses runtime base object check and consistent casts.


229-246: GrassSphereNormal bit propagation is correct; add cautious null checks upstream.

Clear-then-set is correct. The properties[1] access mirrors existing code, but if geometry/properties are ever null, this would silently skip; acceptable, but keep an eye on VR parity.


946-951: Gate new hooks per runtime; verify relocations for VR.

You added ctor callsite and vfunc hooks unconditionally. If VR vtables/offsets differ, this can break.

Consider:

-		logger::info("Installing SetupGeometry hooks");
-		stl::write_vfunc<0x6, EffectExtensions::BSEffectShader_SetupGeometry>(RE::VTABLE_BSEffectShader[0]);
-		stl::write_vfunc<0x6, LightingExtensions::BSLightingShader_SetupGeometry>(RE::VTABLE_BSLightingShader[0]);
-		stl::write_thunk_call<GrassExtensions::BSGrassShaderProperty_ctor>(REL::RelocationID(15214, 15383).address() + REL::Relocate(0x45B, 0x4F5));
-		stl::write_vfunc<0x6, GrassExtensions::BSGrassShader_SetupGeometry>(RE::VTABLE_BSGrassShader[0]);
+		logger::info("Installing SetupGeometry hooks");
+		stl::write_vfunc<0x6, EffectExtensions::BSEffectShader_SetupGeometry>(RE::VTABLE_BSEffectShader[0]);
+		stl::write_vfunc<0x6, LightingExtensions::BSLightingShader_SetupGeometry>(RE::VTABLE_BSLightingShader[0]);
+		if (!REL::Module::IsVR()) { // TODO: add VR relocations once validated
+			stl::write_thunk_call<GrassExtensions::BSGrassShaderProperty_ctor>(REL::RelocationID(15214, 15383).address() + REL::Relocate(0x45B, 0x4F5));
+			stl::write_vfunc<0x6, GrassExtensions::BSGrassShader_SetupGeometry>(RE::VTABLE_BSGrassShader[0]);
+		}

Comment thread src/Hooks.cpp
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Sep 17, 2025

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

@doodlum doodlum changed the title feat: grass sphere normal feature flag and fixes feat(grass lighting): grass sphere normal feature flag and fixes Sep 18, 2025
@doodlum doodlum merged commit aa301ab into dev Sep 18, 2025
19 checks passed
@alandtse alandtse deleted the grass-sphere branch February 6, 2026 05:20
@coderabbitai coderabbitai Bot mentioned this pull request Feb 9, 2026
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.

1 participant