What Sulkan actually loads
Sulkan supports two shader content sources: the built-in shader set bundled in
assets/sulkan/shaders, and external packs discovered from the game's
shaders/ directory. External packs are not mounted directly in place. They are normalized into a generated resource pack and then reloaded through Minecraft's resource-pack system.
Pack IDs are derived from the folder name or zip filename. The built-in pack always uses
__builtin__. If a selected external pack disappears, Sulkan falls back to the built-in pack automatically.
Layout and normalization rules
| Layout inside pack | Result |
|---|---|
| assets/sulkan/shaders/... | Used as-is. This is the native Sulkan namespace. |
| shaders/... | Remapped to assets/sulkan/shaders/... during staging. This is the simplest format for pack authors. |
| pack.png | Preserved when present and copied into the generated active resource pack. |
shader-pack.zip
|- README.md
|- pack.png
|- shaders/
| |- core/
| | |- shadow_depth.vsh
| | |- shadow_depth.fsh
| | |- entity_shadow_depth.vsh
| | |- entity_shadow_depth.fsh
| | |- terrain_shadow.vsh
| | |- terrain_shadow.fsh
| | |- entity_shadow.vsh
| | |- entity_shadow.fsh
| | |- terrain.vsh
| | |- terrain.fsh
| | |- water.vsh
| | |- water.fsh
| | |- ao.vsh
| | |- xegtao_evaluate.fsh
| | |- xegtao_denoise.fsh
| | |- ao_apply.fsh
| | |- volumetric_clouds.vsh
| | |- volumetric_clouds.fsh
| | |- volumetric_clouds_composite.fsh
| | |- atmosphere_composite.fsh
| | |- bloom_prefilter.fsh
| | |- bloom_downsample.fsh
| | |- bloom_blur.fsh
| | |- bloom_composite.fsh
| | |- luminance_downsample.fsh
| | |- exposure_adapt.fsh
| | |- fxaa.fsh
| |- include/
| | |- chunksection.glsl
| | |- held_light.glsl
| | |- scene_tonemap.glsl
| | |- shadow_sampling.glsl
| | |- sulkan_terrain_core.glsl
| | |- terrain_atlas_sampling.glsl
| | |- wind.glsl - Path separators are normalized to /.
- Leading / characters are removed.
- Entries containing .. are rejected outright.
- A leading container directory is trimmed when the nested path begins with assets/, shaders/, or pack.png.
- A pack is considered supported only when at least one normalized file lands under assets/sulkan/shaders.
Shadows
shadow_depth.*, entity_shadow_depth.*, terrain_shadow.*, entity_shadow.*
Eight core files plus receiver-side helpers like shadow_sampling.glsl.
Terrain and water
terrain.*, water.*
Main world receiver surface, water scene shading, and wind-aware terrain paths.
Ambient occlusion
ao.vsh, xegtao_evaluate.fsh, xegtao_denoise.fsh, ao_apply.fsh
The full screen-space AO chain is in the downloadable base template.
Clouds and atmosphere
volumetric_clouds.*, volumetric_clouds_composite.fsh, atmosphere_composite.fsh
Cloud rendering, cloud composite, and the late fog or sky atmosphere composite are all present.
Bloom, exposure, and FXAA
bloom_*.fsh, luminance_downsample.fsh, exposure_adapt.fsh, fxaa.fsh
The late post chain is part of the starter pack, not something authors have to reconstruct later.
Shared helpers
include/*.glsl
Seven shared include files are bundled so pack authors can follow the exact helper layer the current source tree uses.
Entrypoints you can override
Any file under Sulkan's shader namespace can be overridden, but the main pack-facing entrypoints live in
assets/sulkan/shaders/core. The most reliable approach is to treat Sulkan as its own shader target rather than assuming foreign pack layouts will be partially adapted.
Shadows
shadow_depth.*, entity_shadow_depth.*, terrain_shadow.*, entity_shadow.*
Terrain and entity caster and receiver passes. These are the most coupled entrypoints because they depend on shared split and depth bindings.
Water and terrain
water.*, terrain.*
Water uses scene color, scene depth, and shadow data. Terrain paths also rely on lightmap and atlas bindings.
Ambient occlusion
ao.vsh, xegtao_evaluate.fsh, xegtao_denoise.fsh, ao_apply.fsh
Screen-space AO evaluation, denoise, and composite passes.
Clouds and atmosphere
volumetric_clouds.*, volumetric_clouds_composite.fsh, atmosphere_composite.fsh
Late-stage sky and post composite passes.
Bloom and exposure
bloom_prefilter.fsh, bloom_downsample.fsh, bloom_blur.fsh, bloom_composite.fsh, luminance_downsample.fsh, exposure_adapt.fsh
Post-processing chain for bloom and exposure adaptation.
Anti-aliasing
fxaa.fsh
Late full-screen anti-aliasing pass. It is pack-facing even though it is toggled separately from the quality presets.
Shared includes
include/chunksection.glsl, include/held_light.glsl, include/scene_tonemap.glsl, include/shadow_sampling.glsl, include/sulkan_terrain_core.glsl, include/terrain_atlas_sampling.glsl, include/wind.glsl
Override these with care. Receiver behavior often depends on shared helper code as much as on the main entrypoint.
Stable binding contracts
Sulkan's Java side centralizes shader-facing resource names in a single binding registry. For pack authors, the stable contract is the combination of entrypoint names, uniform block names, sampler names, and compile-time defines that the live pipelines already expect.
| Binding | Type | Current usage |
|---|---|---|
| ShadowMatrices | UBO | Terrain shadow caster matrices for core/shadow_depth.*. |
| EntityShadowMatrices | UBO | Entity shadow caster matrices for core/entity_shadow_depth.* and entity receiver vertex work. |
| TerrainShadowSplits | UBO | Receiver-side shadow split ranges and matrices used by terrain, entity, and water receivers. |
| WaveUniforms | UBO | Water animation and wave parameters shared by water shading and terrain helpers. |
| Sampler1 | Sampler | Overlay sampler used by the entity receiver path. |
| Sampler3 | Sampler | Water scene color capture. Used for refraction and surface blur. |
| Sampler4 / 6 / 7 | Sampler | Terrain shadow depth cascades 0 through 2. Current source tree exposes three terrain cascades, not four. |
| Sampler5 | Sampler | Water scene depth capture. Used for thickness, intersection, and refraction depth tests. |
| Sampler8 | Sampler | Held-light spotlight shadow depth. |
| Sampler9 | Sampler | Dynamic entity shadow depth. |
Several passes also depend on vanilla-style bindings such as Sampler0 for the base texture or atlas and Sampler2 for the lightmap. Those are visible in the shipped GLSL files and should stay declared where the pipeline expects them, even though the Sulkan-specific registry focuses on the extra binding contract above.
Author from the template, not from guesswork
- Start from run/shaders/base-pass-through or the downloadable base-shader.zip. The template mirrors the current built-in shader tree, including shadows, terrain, water, AO, clouds, atmosphere, bloom, exposure, FXAA, and include helpers.
- Preserve entrypoint names, block names, and sampler names unless you are changing the Java pipeline definitions and GLSL together.
- Edit one subsystem at a time. Stabilize terrain or water first, then AO, then clouds or atmosphere, then the late post chain.
- Keep the short shaders/... layout while authoring locally, then zip the pack contents and drop the archive into the shaders/ folder.
- After reload, check the client log for [Sulkan] Compiled pipeline ... lines. A successful Gradle build is not enough to prove runtime shader compatibility.
- The template preserves optional defines such as ALPHA_CUTOUT, PER_FACE_LIGHTING, NO_OVERLAY, EMISSIVE, and DISSOLVE. Do not strip them unless you are sure the pass no longer needs them.
The repository includes a source-aligned starter at run/shaders/base-pass-through. The repo copy and downloadable zip mirror Sulkan's current built-in shader tree, so the template already includes AO, clouds, atmosphere, bloom, exposure, FXAA, terrain, water, shadows, and shared include helpers.
ALPHA_CUTOUT
PER_FACE_LIGHTING
NO_OVERLAY
EMISSIVE
DISSOLVE Common failure modes
Sulkan tries to fail soft. Unsupported entries still show up in the UI summary, and invalid selections fall back safely. That does not make authoring errors obvious by default, so these are the first cases to check.
| Symptom | Likely cause |
|---|---|
| Pack ignored entirely | No normalized file landed under assets/sulkan/shaders. |
| Zip looks correct but still fails | A leading container directory is only trimmed when the nested path begins with assets/, shaders/, or pack.png. |
| Folder or archive is listed as unsupported | Common causes are unreadable folders, invalid zip archives, wrong internal layout, or non-zip files placed directly in shaders/. |
| Selection silently falls back | If the configured external pack disappears, Sulkan normalizes the selection back to __builtin__. |