-
Notifications
You must be signed in to change notification settings - Fork 137
Developers
This is the base package that loads all the custom shaders.
This is the main dll in the repo that enables the replacement of vanilla shaders with new shaders.
Can be found primarily in https://github.com/doodlum/skyrim-community-shaders/tree/main/src
The default shaders will be found in https://github.com/doodlum/skyrim-community-shaders/tree/main/package/Shaders.
These default shaders should be overwritten by feature specific shaders.
These are custom features that are loaded after the default CS install.
To add a new feature, the DLL needs to be modified. See prior examples of adding new features for the full list. https://github.com/doodlum/skyrim-community-shaders/pull/83
The main features should live here: https://github.com/doodlum/skyrim-community-shaders/tree/dev/src/Features
- GetName
- Used in ImGui feature list and json entry per feature
- GetShortName
- Used for ini loading (No spaces usually)
- SetupResources
- Called once in startup
- Reset
- Called once per frame
- DrawSettings
- Used for rendering imgui
- Draw
- Normal rendering code here
- Save
- Serialize settings to json
- RestoreDefaultSettings
- Reset feature settings to default value
- Load
- Deserialize settings from json, also need to call
Feature::Loadafter loading
- Deserialize settings from json, also need to call
These are already default defined in Feature.h but can be overriden if you need to do something extra like defined below
- GetShaderDefineName
- used as an additional macro added when compiling shaders specified by HasShaderDefine, if the feature is loaded
- HasShaderDefine
- if a shader type returns true, then GetShaderDefineName macro is added to its compilation, if the feature is loaded
- DrawDeferred
- This one is not called yet, that is in the subsurface-scattering branch
- DataLoaded
- Called by SKSE
kDataLoadedevent
- Called by SKSE
- PostPostLoad
- Called by SKSE
kPostPostLoadevent
- Called by SKSE
- ClearShaderCache
- Called by imgui clear shader cache button
- GetFeatureModLink
- Specify link to feature, which will be presented to the user when feature is unloaded: example
- DrawFailLoadMessage
- Returns true/false depending on whether the stock failed to load message should be printed: example
- DrawUnloadedUI
- Called when feature is unloaded to add any content to the panel (you probably want to return false for DrawFailLoadMessage if using this): example
Shaders are stored in https://github.com/doodlum/skyrim-community-shaders/tree/dev/features
To debug CS you will need to be able to debug both the cpp dll and the hlsl shader files.
- Save a copy of the original exe so you can replace it.
- Use Steamless to strip the SteamDRM from the Skyrim.exe. This is required for a debugger to attach.
Make sure to check
Keep Bind Sectionin steamless, game will not boot without it.
To ensure addresses don't move, disable ASLR. This can be done with CFF Explorer. Optional Header -> DLL Characteristics -> DLL can move. Disable this.

Renderdoc can be used to debug shaders. You can also try alandtse's fork. See extra features.
- Disable incompatible features:
- Skyrim Upscaler
- reshade
-
Optional Enable Global Hooking. Make sure to
Enable Global Hookwhich will grey out all settings. This also will prevent closing renderdoc until you disable the setting. - Set up
Launch Applicationso it will find the skse.exe (or Skyrim.exe if global hooking) when it launches.

- Launch Skyrim. You will know RenderDoc has connected because of the message in the top left of Skyrim
Capturing D3D11. If it doesn't show, try toggling the global hook and launching again.

- Enable Developer Mode. Developer Mode can be enabled by setting the
Advanced Settings->Log LeveltoTRACEorDEBUG.

- Enable
Advanced->Extended Frame Annotationsto help populate info in the rendering process.

-
Clear Shader Cache and Disk Cache. This is necessary to save debug information in the shaders to access named buffers/hlsl in renderdoc.
-
In game, press
F12to capture the scene. -
In Renderdoc,
File->Attach to Running Instance. Select Skyrim andConnect to App.

- Once attached, a new tab will appear. Double click any captures to load.

- You can verify you are seeing debug information by opening up the Pipeline tab and checking the Vertex or Pixel shaders. The resources should be named. In this case, we're getting
water.hlsldata.

With Claude Code or other agentic AI, you can connect RenderDoc as a MCP server to help debug hlsl shaders.
- Download agentic-renderdoc. This is alandtse's fork, the upstream may be better. Follow it's installation steps.
- Setup Claude Code with the CS repo.
- Confirm you can see the MCP server:
claude mcp list
Checking MCP server health...
renderdoc: agentic-renderdoc - ✓ Connected- Capture the scene in renderdoc with the version of CS that is causing the issue.
- Make sure Claud knows about and can access the MCP. Just ask it to use the renderdoc MCP.
- Describe the problem to Claude to a reasonable degree to not waste tokens. Identify:
- What event ID (EID)? Find exactly which shader is drawing the bad item. E.g., scroll through the timeline to what is drawing it.
- What shader? Pixel/Compute etc. Check the
Pipeline State. If you can identify the specific CS hlsl file, it'll be even more efficient. - Identify the coordinates and the texture. E.g., (Rt0 kMain at 754, 587). In the Texture viewer, you can right click to save the information in the bottom of the window.
It is possible to block individual shaders in game to find a faulty shader.
- Find the faulty mesh in game. Confirm the mesh is caused by CS by toggling CS using the
Toggle Effects Key(defaultNumpad *). The faulty mesh should disappear. If it doesn't, it's a Vanilla bug. This is an example with CS disabled:

CS Enabled showing faulty mesh (note texture is missing in red circle):

- Enable Developer Mode. Developer Mode can be enabled by setting the
Advanced Settings->Log LeveltoTRACEorDEBUG.

- Hit the
PageUporPageDownto cycle all active shaders until the faulty mesh disappears. This should match the vanilla shader.

- [Optional] Stop blocking shaders by clicking on the
Advanced Settings->Stop Blocking Shadersbutton. This should also flush the log and also provide a noticeable log entry to identify the last shader blocked. This button only appears when shaders are being blocked.

- Review the CommunityShaders.log file. The blocked shader should be the last entry before
Stopped blocking shaders(from step 4). In the example below, the ID/descriptor is12000004and it is a Lighting/Vertex shader, with the compile options ofWETNESS_EFFECTS LIGHT_LIMIT_FIX COMPLEX_PARALLAX_MATERIALS DYNAMIC_CUBEMAPS LODLANDNOISE LODLANDSCAPE MODELSPACENORMALS SHADOWSPLITCOUNT=3. With this information, we can look atlighting.hlslto figure out what hlsl is active.
[2023-11-20 19:09:59.451] [debug] [33112] [ShaderCache.cpp:1557] Blocking shader (6/93) Lighting:Vertex:WETNESS_EFFECTS LIGHT_LIMIT_FIX COMPLEX_PARALLAX_MATERIALS DYNAMIC_CUBEMAPS LODLANDNOISE LODLANDSCAPE MODELSPACENORMALS SHADOWSPLITCOUNT=3
[2023-11-20 19:09:59.451] [debug] [33112] [ShaderCache.cpp:1209] Skipping blocked shader 12000004:Lighting:Vertex:WETNESS_EFFECTS LIGHT_LIMIT_FIX COMPLEX_PARALLAX_MATERIALS DYNAMIC_CUBEMAPS LODLANDNOISE LODLANDSCAPE MODELSPACENORMALS SHADOWSPLITCOUNT=3 total: 1
[2023-11-20 19:10:10.734] [debug] [33112] [ShaderCache.cpp:1568] Stopped blocking shaders
For comparison, if we block the corresponding Pixel shader, the coloring will be distorted instead which is revealed to be ID/descriptor 12000005 which is the Lighting:Pixel shader.

[2023-11-20 23:07:17.546] [debug] [70860] [ShaderCache.cpp:1537] Blocking shader (24/97) Lighting:Pixel:WETNESS_EFFECTS LIGHT_LIMIT_FIX COMPLEX_PARALLAX_MATERIALS DYNAMIC_CUBEMAPS LODLANDNOISE LODLANDSCAPE MODELSPACENORMALS SHADOWSPLITCOUNT=3 VC
[2023-11-20 23:07:17.564] [debug] [74308] [ShaderCache.cpp:1243] Skipping blocked shader 12000005:Lighting:Pixel:WETNESS_EFFECTS LIGHT_LIMIT_FIX COMPLEX_PARALLAX_MATERIALS DYNAMIC_CUBEMAPS LODLANDNOISE LODLANDSCAPE MODELSPACENORMALS SHADOWSPLITCOUNT=3 VC total: 1
Please note the hotreload works for changes to hlsl/hlsli files. Changes to cpp code require a restart of the game.
- Make sure 'Enable Async' is on
- Disable 'Enable Disk Cache' (Probably obsolete, but does not hurt)
- Change hlsl/hlsli
- Click 'Clear Shader Cache'
- The game should recompile shaders now
- Make sure 'Enable Async' is on
- Disable 'Enable Disk Cache' (Probably obsolete, but does not hurt)
- Enable File Watcher, this will add a watcher for hlsl files in the root folder and automatically clear shader cache for changed files
- Change hlsl file in root
- The game should recompile shaders now
Use the standard process for every normal release — new features, improvements, or non-urgent fixes that have accumulated on dev.
1. Merge all work to dev via normal PRs
All commits that should ship must be on dev. Semantic-release reads conventional commit messages (feat:, fix:, chore:, etc.) to determine the version bump, so commit message format matters.
2. Trigger the release workflow
Go to Actions → Release: Semantic Version → Run workflow, select branch dev, set release_type: stable.
The workflow will:
- Auto-bump any feature
.iniversions whose shaders or code changed since the last tag - Run
semantic-release, which determines the next version from commit history (e.g.v1.6.0) - Update
CMakeLists.txtwith the new version and commit it - Create a draft GitHub release with auto-generated release notes
3. Build and package
The Release: Build Artifacts workflow triggers automatically on the new tag and uploads the packaged .7z artifacts to the draft release.
4. Review and publish the draft release
Open the draft release on GitHub, review the release notes, then publish it.
5. Nexus upload triggers automatically
Publishing the release triggers Release: Nexus Upload Trigger, which calls Nexus: Upload Release for each mod that changed since the previous tag. Core and any features with a bumped version are uploaded automatically.
To verify before publishing, run Nexus: Upload Release manually with dry_run: true — it queries Nexus and shows planned vs current versions without uploading anything.
Use a hotfix release when dev has moved forward with new unreleased features and a critical fix needs to ship against the last stable tag.
If dev has no unreleased features yet, you can release directly from dev as normal.
Hotfix branches represent a maintenance line, not a single patch:
hotfix/1.5.x ← correct (the 1.5 line)
hotfix/1.5.1 ← wrong (semantic-release won't match this)
1. Land the fix on dev first (normal PR flow)
# fix merged to dev via PR as usual2. Create a hotfix branch from the stable tag
git fetch community-shaders
git checkout -b hotfix/1.5.x v1.5.03. Cherry-pick the fix from dev
git cherry-pick <commit-sha> # the fix commit from dev
git push origin hotfix/1.5.x4. Trigger the release
Go to Actions → Release: Semantic Version → Run workflow, select branch hotfix/1.5.x, set release_type: stable.
The workflow will:
- Auto-bump any feature INI versions that changed on this branch
- Run semantic-release, which sees
v1.5.0as the baseline and producesv1.5.1 - Update
CMakeLists.txtversion and commit it - Create a draft GitHub release tagged
v1.5.1 - Trigger the build and Nexus upload pipeline automatically
5. Publish the release
Review the draft release on GitHub, then publish it. The Nexus upload will trigger automatically on publish.
6. Clean up
The hotfix/1.5.x branch can be deleted after the release is published. All fixes should already be on dev from step 1.