Skip to content

feat(snow-cover): add snow cover feature#2047

Closed
InTheBottle wants to merge 169 commits into
community-shaders:devfrom
InTheBottle:snow2
Closed

feat(snow-cover): add snow cover feature#2047
InTheBottle wants to merge 169 commits into
community-shaders:devfrom
InTheBottle:snow2

Conversation

@InTheBottle
Copy link
Copy Markdown
Contributor

@InTheBottle InTheBottle commented Apr 1, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Snow Cover feature with per-world configuration support.
    • Implemented seasonal snowline dynamics with summer/winter height offsets.
    • Added whitelist/blacklist system for controlling which objects receive snow coverage.
    • Introduced RGB/HSV color conversion utilities for advanced rendering.
  • Refactor

    • Reorganized global feature list for improved initialization order.
    • Extended shader permutation system with new configuration flags.
    • Restructured shader constant buffers for enhanced material settings.
  • Chores

    • Updated feature buffer data composition and ordering.

Exist and others added 30 commits September 8, 2024 09:30
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 1, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 441faa58-eff0-4909-b3fd-63f6df229670

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

A new snow cover feature is introduced with regional shader configurations, HLSL shader logic for snow/ice material blending and foliage tinting, C++ feature implementation with seasonal dynamics and configuration management, and integration with existing rendering pipelines through permutation flags and buffer updates.

Changes

Cohort / File(s) Summary
Snow Cover Configuration
features/Snow Cover/Shaders/Features/SnowCover.ini, features/Snow Cover/Shaders/SnowCover/{MarkarthWorld,RiftenWorld,SolitudeWorld,Tamriel,WhiterunWorld,WindhelmWorld}.json
Version metadata and per-world shader parameter configurations (textures, tints, angles, seasonal offsets, melting speeds) for six distinct world regions.
Snow Cover Whitelist/Blacklist
features/Snow Cover/Shaders/SnowCover/{whitelist,blacklist}.txt
Entity/mesh whitelisting (8 entries) and decal blacklist for filtering which geometry receives snow effects.
Core Snow Shader Logic
features/Snow Cover/Shaders/SnowCover/SnowCover.hlsli
HLSL include implementing snow/ice blending (height computation, environmental multiplier, foliage tinting, PBR/non-PBR material updates, displacement-based variant selection, LOD adjustments).
Ambient Composite Compute Shader
package/Shaders/AmbientCompositeCS.hlsl
New compute shader for compositing ambient lighting with conditional support for Skylighting, SSGI, and IBL; includes per-eye sampling for VR.
Shared Shader Definitions
package/Shaders/Common/{Color,Permutation,SharedData}.hlsli
HSV↔RGB conversion utilities, new NoSnow permutation flag (1 << 6), renamed CPMSettingsExtendedMaterialSettings, and new SnowCoverSettings cbuffer struct.
Snow Cover Feature Implementation
src/Features/{SnowCover.h,SnowCover.cpp}
Complete feature class with configuration structs, seasonal altitude/accumulation logic, ImGui settings UI, resource loading/binding, whitelist/blacklist parsing, permutation bit management, and world-aware config persistence.
Feature Registration & Globals
src/{Feature.cpp,FeatureBuffer.cpp,Globals.{h,cpp}}
Updated feature list ordering and composition, FeatureBuffer packing with new snowCover.GetCommonBufferData(), global feature instance declarations and initialization for snow cover alongside reordered existing features.
Shader Integration Points
package/Shaders/{DistantTree,Lighting,RunGrass}.hlsl
Conditional snow-cover includes, foliage tinting via ApplySnowFoliage, sky-light-driven snow occlusion, normal adjustments, and permutation bit checks; includes defines for BASIC_SNOW_COVER in foliage shaders.
State & Permutation Management
src/State.h
Added ExtraShaderDescriptors::NoSnow flag and corrected PermutationCB::operator== to compare both vertex and pixel shader descriptors.
Form ID Parsing Utility
src/Utils/{FormIdParser.h,FormIdParser.cpp}
New utility for parsing form IDs/names from text files with FNV-1a hashing, whitespace trimming, and comment stripping.

Sequence Diagram

sequenceDiagram
    participant CPU as SnowCover Feature
    participant Cfg as Config System
    participant Tex as Texture Manager
    participant RenderPass as Render Pass (Lighting/Grass/Tree)
    participant Shader as GPU Shader (SnowCover.hlsli)
    participant Output as Frame Buffer

    CPU->>Cfg: LoadSettings() / LoadWorldConfig()
    Cfg-->>CPU: Parse JSON + Whitelist/Blacklist
    CPU->>Tex: CreateTextures(DDS paths)
    Tex-->>CPU: Bind SRVs (t38–t44)
    CPU->>CPU: ComputeSeasonalAltitude()
    CPU->>CPU: UpdateTimeSnowing(weather, speed)
    CPU->>RenderPass: Prepass() binds SRVs + sets NoSnow permutation
    RenderPass->>RenderPass: Permute shader based on NoSnow flag
    RenderPass->>Shader: Execute (SnowCover::ApplySnow[*] functions)
    Shader->>Shader: ComputeSnowHeight(SnowMap + seasonal offset)
    Shader->>Shader: DeriveEnvironmentalMultiplier(height, peak angles)
    Shader->>Shader: ApplySnowMaterial(main/alt textures, normals, PBR params)
    Shader->>Shader: ApplySnowFoliage(foliage tinting, hue shift)
    Shader-->>Output: Blended snow/ice base color + normals
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • feat(ibl): revamp ibl and dalc sh #1947 — Modifies package/Shaders/Common/SharedData.hlsli to add shader cbuffer structures and shared APIs (SnowCoverSettings, ExtendedMaterialSettings) that this PR depends on.
  • feat: diffuse ibl #1054 — Overlaps on core infrastructure changes: extends SharedData cbuffer, updates Feature::GetFeatureList() ordering, and adds color utility functions (HSVtoRGB, RGBtoHSV) used by foliage tinting.
  • perf(ssgi): optimize  #1499 — Directly related to package/Shaders/AmbientCompositeCS.hlsl; the retrieved PR removes this compute shader while the main PR introduces/modifies it.

Suggested Reviewers

  • doodlum
  • alandtse
  • jiayev

Poem

🐰 Snowflakes dance through shader's dream,
Winter's glow on every seam,
Textures blend with frosty care,
GPU sparkles fill the air!
Rabbit hops through worlds of white,
Snow-covered shaders, shimmering bright! ❄️

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 'feat(snow-cover): add snow cover feature' clearly and directly summarizes the main change—adding a snow cover feature to the codebase.

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

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

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

❤️ Share

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

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

github-actions Bot commented Apr 1, 2026

Actionable Suggestions

  • Inverse Square Lighting (InTheBottle): Needs version bump to 1-3-0
  • Performance Overlay (soda): Needs version bump to 1-1-0
  • Sky Sync (soda): Needs version bump to 1-1-0

@InTheBottle InTheBottle changed the title Snow2 feat: Snow cover Apr 1, 2026
@InTheBottle
Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 1, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 7

🧹 Nitpick comments (2)
package/Shaders/Common/Color.hlsli (1)

88-88: Optional PR metadata polish

Consider updating the PR title to a scoped conventional form, e.g. feat(snow-cover): add snow cover feature, and add an issue keyword like Implements #<id> if this tracks an issue.

As per coding guidelines: "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 `@package/Shaders/Common/Color.hlsli` at line 88, Update the PR metadata:
change the PR title to a scoped conventional commit style (e.g.,
"feat(snow-cover): add snow cover feature") and add an issue reference like
"Implements #<id>" in the PR description; you can locate this change while
reviewing the diff touching package/Shaders/Common/Color.hlsli (the comment line
with the RGB/HSV HLSL link) to ensure the PR title and description reflect the
code intention and tracking number.
src/Features/SnowCover.h (1)

41-41: Narrow HasShaderDefine() to the shader families that actually use snow.

Returning true for every RE::BSShader::Type widens SNOW_COVER permutations even for shader families that immediately ignore the define. Restricting this to the lighting/tree/grass path will keep shader-cache churn down.

As per coding guidelines, "Consider GPU workload and performance impact when implementing graphics features, with special attention to shader compilation and runtime performance."

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

In `@src/Features/SnowCover.h` at line 41, The HasShaderDefine(RE::BSShader::Type)
implementation currently returns true for every shader type which forces
SNOW_COVER into all shader permutations; change HasShaderDefine to only return
true for the shader families that actually use snow (e.g., the lighting, tree
and grass shader types) by checking the incoming RE::BSShader::Type against
those specific enum values and returning true only for them, otherwise return
false; update the HasShaderDefine method (and any associated comments) to
enumerate the allowed types so shader-cache churn is avoided.
🤖 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/Snow` Cover/Shaders/SnowCover/SnowCover.hlsli:
- Around line 27-29: GetEnvironmentalMultiplier currently divides by
SharedData::snowCoverSettings.BlendSmoothness which can be zero; clamp the
denominator to a small epsilon (e.g.
max(SharedData::snowCoverSettings.BlendSmoothness, EPSILON)) before dividing or
validate/replace BlendSmoothness on settings load; update the
GetEnvironmentalMultiplier function to use the clamped value so division cannot
produce inf/NaN and downstream snow blends remain stable.

In `@package/Shaders/AmbientCompositeCS.hlsl`:
- Around line 74-80: linAmbient is converted to linear (via
Color::GammaToLinear) and attenuated but later the shader adds
directionalAmbientColor * albedo in gamma space, causing incorrect lighting; fix
by keeping ambient compositing entirely in linear space: compute linAmbient =
Color::GammaToLinear(albedo * directionalAmbientColor) (or multiply linAlbedo *
linDirectionalAmbientColor), accumulate the ambient term into the linear
lighting accumulator (e.g., add to linDiffuseColor or a dedicated linear ambient
accumulator) and only gamma-encode once when writing out the final color (use
Color::LinearToGamma at the output), updating usages around linAmbient and the
final write where directionalAmbientColor * albedo is added so no ambient term
is mixed in gamma space.

In `@package/Shaders/Lighting.hlsl`:
- Around line 31-33: The SNOW_COVER macro is being undefined whenever
EXTENDED_MATERIALS is not defined, which prevents non-EMAT snow fallbacks from
running; update the preprocessor condition so SNOW_COVER is only undefined for
incompatible geometry (SKINNED, SKIN, EYE, HAIR) and not tied to
EXTENDED_MATERIALS—i.e., remove the "!defined(EXTENDED_MATERIALS)" clause around
the `#undef` SNOW_COVER (leave checks for SKINNED/SKIN/EYE/HAIR intact) and verify
the existing non-EMAT fallback code paths (e.g., disp = 0) still execute when
EXTENDED_MATERIALS is not defined.

In `@package/Shaders/RunGrass.hlsl`:
- Around line 558-592: The foliage snow path in the SNOW_COVER block runs
unconditionally and needs to be skipped when the world is interior; wrap the
snow occlusion / SnowCover::ApplySnowFoliage logic with a check against
SharedData::InInterior (e.g. if (!SharedData::InInterior) { ... } ), or
early-return/skip that entire SNOW_COVER section when SharedData::InInterior is
true. Update the block that computes snowOcclusion and calls
SnowCover::ApplySnowFoliage (inside RunGrass.hlsl’s SNOW_COVER handling) so it
only executes when SharedData::InInterior is false, keeping existing use of
FrameBuffer::CameraPosAdjust, eyeIndex, and other symbols intact.

In `@src/Features/SnowCover.cpp`:
- Around line 404-419: SnowCover::SaveConfig currently saves to disk then calls
Reload(), but Reload() exits early because last_worldspace still equals
GetWorldspace(); to force the post-save reload, reset last_worldspace (e.g.,
clear or set to an empty value) before calling Reload() so Reload() will treat
the worldspace as changed and reapply textures/derived maps; ensure this reset
happens in both normal and exception paths so Reload() always runs.
- Around line 607-623: The blacklist check is performed too late so a
blacklisted movable with AffectHavok enabled can have NoSnow cleared by the
velocity branch; reorder the logic so that after the whitelist check
(whitelist.contains(FormIdParser::fnv_hash(name))) you immediately test
blacklist.contains(FormIdParser::fnv_hash(name)) and set
state->permutationData.ExtraShaderDescriptor |=
(uint)State::ExtraShaderDescriptors::NoSnow if true, otherwise proceed into the
existing animation/movable/Havok branch (settings.AffectHavok,
userData->CanBeMoved(), userData->GetLinearVelocity(...)) to decide whether to
set or clear NoSnow; keep all referenced symbols (settings.AffectHavok,
userData, whitelist.contains, blacklist.contains, FormIdParser::fnv_hash(name),
state->permutationData.ExtraShaderDescriptor,
State::ExtraShaderDescriptors::NoSnow) unchanged.
- Around line 148-150: The "Defaults" button currently only assigns wsettings =
WorldSettings(), but other persisted fields used by ToWorldConfig() (seasonal
months/heights, map bounds, texture paths, snow/melt speeds, etc.) remain stale;
update the ImGui::Button("Defaults") handler to also reset all individual
members that ToWorldConfig() serializes (e.g., seasonalMonths, seasonalHeights,
mapBounds, texturePaths, snowSpeed, meltSpeed or any similarly named member
variables) back to their default values (or copy them from the new
WorldSettings() instance) so clicking Defaults truly resets every persisted
field before Save.

---

Nitpick comments:
In `@package/Shaders/Common/Color.hlsli`:
- Line 88: Update the PR metadata: change the PR title to a scoped conventional
commit style (e.g., "feat(snow-cover): add snow cover feature") and add an issue
reference like "Implements #<id>" in the PR description; you can locate this
change while reviewing the diff touching package/Shaders/Common/Color.hlsli (the
comment line with the RGB/HSV HLSL link) to ensure the PR title and description
reflect the code intention and tracking number.

In `@src/Features/SnowCover.h`:
- Line 41: The HasShaderDefine(RE::BSShader::Type) implementation currently
returns true for every shader type which forces SNOW_COVER into all shader
permutations; change HasShaderDefine to only return true for the shader families
that actually use snow (e.g., the lighting, tree and grass shader types) by
checking the incoming RE::BSShader::Type against those specific enum values and
returning true only for them, otherwise return false; update the HasShaderDefine
method (and any associated comments) to enumerate the allowed types so
shader-cache churn is avoided.
🪄 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: 2a71e8f8-6405-4390-9d95-517c80d7839c

📥 Commits

Reviewing files that changed from the base of the PR and between d158508 and 4fcc9d5.

⛔ Files ignored due to path filters (4)
  • features/Snow Cover/Shaders/SnowCover/Skyrim.dds is excluded by !**/*.dds
  • features/Snow Cover/Shaders/SnowCover/default/main.dds is excluded by !**/*.dds
  • features/Snow Cover/Shaders/SnowCover/default/main_n.dds is excluded by !**/*.dds
  • features/Snow Cover/Shaders/SnowCover/default/main_rmaos.dds is excluded by !**/*.dds
📒 Files selected for processing (26)
  • features/Snow Cover/Shaders/Features/SnowCover.ini
  • features/Snow Cover/Shaders/SnowCover/MarkarthWorld.json
  • features/Snow Cover/Shaders/SnowCover/RiftenWorld.json
  • features/Snow Cover/Shaders/SnowCover/SnowCover.hlsli
  • features/Snow Cover/Shaders/SnowCover/SolitudeWorld.json
  • features/Snow Cover/Shaders/SnowCover/Tamriel.json
  • features/Snow Cover/Shaders/SnowCover/WhiterunWorld.json
  • features/Snow Cover/Shaders/SnowCover/WindhelmWorld.json
  • features/Snow Cover/Shaders/SnowCover/blacklist.txt
  • features/Snow Cover/Shaders/SnowCover/whitelist.txt
  • package/Shaders/AmbientCompositeCS.hlsl
  • package/Shaders/Common/Color.hlsli
  • package/Shaders/Common/Permutation.hlsli
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/DistantTree.hlsl
  • package/Shaders/Lighting.hlsl
  • package/Shaders/RunGrass.hlsl
  • src/Feature.cpp
  • src/FeatureBuffer.cpp
  • src/Features/SnowCover.cpp
  • src/Features/SnowCover.h
  • src/Globals.cpp
  • src/Globals.h
  • src/State.h
  • src/Utils/FormIdParser.cpp
  • src/Utils/FormIdParser.h

Comment thread features/Snow Cover/Shaders/SnowCover/SnowCover.hlsli Outdated
Comment thread package/Shaders/AmbientCompositeCS.hlsl
Comment thread package/Shaders/Lighting.hlsl Outdated
Comment thread package/Shaders/RunGrass.hlsl
Comment thread src/Features/SnowCover.cpp
Comment thread src/Features/SnowCover.cpp
Comment thread src/Features/SnowCover.cpp Outdated
@InTheBottle InTheBottle changed the title feat: Snow cover feat(snow-cover): add snow cover feature Apr 1, 2026
@InTheBottle InTheBottle closed this Apr 2, 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.

3 participants