Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
ShaderHelperForMac
New V2 refactor. Check README.md. Mod for Apple Silicon (ARM Mac) that automatically fixes broken/pink materials caused by mod shaders that were compiled without Metal GPU support.
| Last updated | 2 weeks ago |
| Total downloads | 140 |
| Total rating | 2 |
| Categories | Client-side Utility AI Generated |
| Dependency string | DrummerCraig-ShaderHelperForMac-2.0.0 |
| Dependants | 0 other packages depend on this package |
README
ShaderHelperForMac
v2.0.0 — A mod for Valheim on Apple Silicon (ARM Mac) that fixes broken/pink materials caused by mod shaders compiled without Metal GPU support.
Do not run this mod unless you are on an Apple Silicon Mac.
I created this mod for myself but it has made such a meaningful difference that I wanted to share it with the community. It is a work in progress and no guarantees are provided.
To get the most out of playing on an ARM Mac, take the time and watch this instructional video here: https://youtu.be/SQCVkaRel40?si=wxOIYrW1vIzIdtzh
The Problem
Valheim mods ship Unity asset bundles with shaders compiled only for Windows (Direct3D 11). When loaded on macOS with the Metal graphics API, Unity cannot find a Metal-compatible shader variant and substitutes a bright magenta/pink error material. This happens silently — the mod author doesn't need to do anything wrong for it to occur.
Installation
Requirements
- Valheim (any recent version) on Steam, Apple Silicon Mac
- BepInEx for Valheim installed
Steps
- Create the folder:
BepInEx/plugins/ShaderHelperForMac-DrummerCraig/ - Copy both files from the download into that folder:
ShaderHelperForMac.dll AssetsTools.NET.dll - Launch Valheim. The plugin initializes automatically.
Configuration
BepInEx config file
Located at BepInEx/config/drummercraig.shaderhelperformac.cfg.
| Setting | Default | Description |
|---|---|---|
Default All Transparent |
false |
When true, all unsupported shaders are made transparent automatically. When false, shaders are left pink unless the mod is explicitly listed in a config file or covered by a per-mod txt file. |
Force Transparent Shader Prefixes |
(empty) | Comma-separated shader name prefixes always made transparent, regardless of other settings. |
Force Fallback Shader Prefixes |
(empty) | Comma-separated shader name prefixes always replaced with the fallback shader, even if Unity reports them as supported. Use for shaders that render pink despite isSupported=true. |
Periodic Sweep Interval |
30 |
How often (seconds) to re-sweep all materials. Set to 0 to disable. |
Per-mod txt files (recommended)
Located at BepInEx/config/ShaderHelperForMac/. Create one file per mod, named after the mod's DLL (e.g. WardIsLove.txt). Use shaderhelper initmod <DllName> to auto-generate a starting file.
Each file uses section headers to control behaviour for that mod:
[forcefallback]
# Shader name prefixes that render pink despite isSupported=true.
# Start here when solid objects (armour, weapons, furniture) are pink.
SomeAuthor/SomePinkShader
[forcetransparent]
# Same as forcefallback but hides the object (for particles/effects).
[fallback]
# Specific materials to replace with the solid fallback shader.
mat:some_material_name
suffix:_glow # matches any material ending with _glow
[transparent]
# Specific materials to make invisible.
mat:some_particle
suffix:Trail
[original]
# Specific materials to leave completely untouched.
[default]
fallback # or: transparent, original
Files are reloaded automatically when changed. Run shaderhelper sweep to apply immediately.
Legacy DLL list files
Also located at BepInEx/config/ShaderHelperForMac/. These apply a single action to all broken-shader materials in a mod.
| File | Effect |
|---|---|
usetransparentshader.txt |
Makes all broken-shader materials in the mod invisible. |
usefallbackshader.txt |
Replaces all broken-shader materials with a solid visible placeholder. |
useoriginalshader.txt |
Leaves the mod's shaders completely untouched. |
One DLL name per line (without .dll), case-insensitive. Lines starting with # are comments.
Console Commands
Open the in-game console with F5.
Fixing pink shaders
| Command | Description |
|---|---|
shaderhelper sweep |
Re-run the material sweep immediately. Reloads config files first. Shows a HUD notification when complete. |
shaderhelper reload |
Reload all config files without running a sweep. |
shaderhelper initmod <DllName> |
Auto-generate a starter txt file for a mod based on what the plugin has already seen. |
shaderhelper initmod <DllName> force |
Regenerate the txt file even if one already exists. |
Diagnosing pink shaders
| Command | Description |
|---|---|
shaderhelper nearby [radius] |
Log all materials on objects within radius units (default 30). Shows shader name, support status, action, and DLL. Best tool for identifying pink objects you can see. |
shaderhelper nearby [radius] mod |
Same as above but filters out vanilla Valheim/Unity shaders — only shows mod materials. |
shaderhelper nearby [radius] <DllName> |
Same as above but filtered to a specific mod's DLL. |
shaderhelper pink |
Log all materials with unsupported shaders that currently have no fix rule. |
shaderhelper loaded [DllName] |
Log all materials in memory, optionally filtered to a specific DLL. Finds prefab assets that haven't been placed in the scene yet. |
shaderhelper scan <DllName> |
Log all loaded materials attributed to a specific DLL with shader name and support status. |
shaderhelper dumpmod <DllName> |
List all shader names the scanner recorded for a specific DLL. |
shaderhelper status |
Show plugin state — fallback shader, config counts, loaded rules. |
shaderhelper shaders |
Dump all shader objects in memory with names and support status. |
shaderhelper renderers |
Dump materials from active scene renderers only (faster than loaded). |
shaderhelper all |
Dump all materials in memory (both supported and unsupported). |
Troubleshooting
Objects are still pink
Stand near the pink objects and run shaderhelper nearby 15. Check BepInEx/LogOutput.log — it shows every nearby material with its shader name and action. If the action is Original, that material has no fix rule yet. Add a mat: entry to the appropriate mod's txt file and run shaderhelper sweep.
If the shader shows isSupported=True but still renders pink, add the shader name prefix to [forcefallback] in that mod's txt file.
Objects that should be visible are transparent
The plugin made them invisible because their shader was broken. Find the material name from shaderhelper nearby and add mat:MaterialName to [fallback] in the mod's txt file. Run shaderhelper sweep to apply.
A mod looks wrong after being set to fallback (flat color, no textures)
Expected — the fallback shader has no textures. This is a compatibility placeholder. Correct visuals require the mod author to recompile with Metal support.
I don't know which DLL a mod uses
Look in BepInEx/plugins/. The .dll filename without the extension is what to use. If a mod bundles its shaders inside the DLL itself (rather than a separate bundle), the scanner may report it as a large embedded bundle — in that case, dll='unknown' is expected and per-material mat: rules in the txt file still work.
The plugin seems slow at startup
The scanner reads all mod bundles at launch. With many large mods this takes a few seconds. The log shows [N/total] 'ModName' — X shader(s) lines as it progresses.
Why It May Not Always Work
-
Bundle byte layout varies by Unity version. The plugin reads shader names directly from the raw bundle binary. Different Unity versions and build tools place data at different byte offsets. If the layout doesn't match a known pattern, the shader's name can't be read — DLL-based attribution won't apply to it.
-
shader.isSupportedis not always accurate. Some shaders reportisSupported = truewhile still rendering pink on Metal. Use[forcefallback]in a mod's txt file to force replacement of these. -
Shaders loaded after startup are not always caught immediately. The plugin sweeps at scene load, after
ZNetScene.Awake, afterDungeonGenerator.Generate, and when items are equipped. Shaders that appear between these points may stay pink until the next sweep. Runshaderhelper sweepin the console to force an immediate re-sweep. -
Valheim's own shaders exist in both the game and mod bundles. Shaders like
Custom/PieceandCustom/Creatureare built into the game with Metal support, but mod bundles often ship their own copies without Metal support. The plugin distinguishes these using instance IDs captured at startup. -
The fallback shader carries no textures. When a material is replaced with the fallback, it renders as a solid flat color with no textures, normal maps, or emission. This is a compatibility shim — correct visuals require the mod author to recompile their shaders with Metal support.
-
Some mods manage shader replacement themselves. Mods using Jotunn's
JVLmock_system replace their own shaders at runtime. The plugin is aware of these and skips them. Other mods doing custom runtime replacement may conflict — add them touseoriginalshader.txt.
How It Works
At startup the plugin:
- Scans all
.dlland.bundlefiles inBepInEx/plugins/for shader names, recording which DLL each shader came from. - Captures a baseline of all materials in memory before mod prefabs load, so vanilla materials are never touched.
- Selects a fallback shader — tries
Custom/Piece,Custom/Creature,Custom/Vegetationin order, using the first one supported on Metal. - Records canonical Valheim shader IDs — to distinguish the game's own supported copies from unsupported bundle copies of the same name.
- Installs Harmony patches —
ZNetScene.Awake,DungeonGenerator.GenerateDungeon, andVisEquipment.AttachItempostfixes trigger sweeps when new objects are spawned;AssetBundle.LoadAssetintercepts materials the moment a bundle is loaded;Shader.Findintercepts runtime shader lookups. - Sweeps all loaded materials on every scene load and periodically on a configurable timer, applying replacements based on config files.