VPFX Pack Manifest Format
This document describes the current VPFX pack.json format.
A VPFX pack is recognized as a native VPFX pack only when the zip root contains:
pack.jsonThe manifest file tells VPFX:
What this pack is calledWhich pack format version it usesWhere the entry post-effect graph is locatedWhich runtime capabilities it requiresWhich runtime targets it expectsWhich external textures it declaresWhich optional metadata should be shown or searchedThis document is based on the current VPFX v1 manifest parser.
1. File location
pack.json must be placed at the root of the zip.
Correct:
my_vpfx_pack.zip├─ pack.json├─ post_effect/│ └─ main.json└─ shaders/ └─ composite/ ├─ final.vsh └─ final.fshIncorrect:
my_vpfx_pack.zip└─ my_vpfx_pack/ ├─ pack.json ├─ post_effect/ └─ shaders/If pack.json is hidden inside an extra folder, VPFX will not detect the zip as a VPFX native pack.
2. Minimal valid manifest
A minimal VPFX manifest looks like this:
{ "format_version": 1, "pack_id": "example_minimal_pack", "name": "Example Minimal VPFX Pack", "version": "1.0.0", "author": "Your Name", "description": "A minimal VPFX post-processing pack.", "entry_post_effect": "post_effect/main.json", "capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": false, "custom_targets": true, "compute": false }}This is enough for a simple scene-color post-processing pack.
3. Complete manifest example
A more complete manifest can include target mappings, declared textures, and metadata:
{ "format_version": 1, "pack_id": "example_cinematic_pack", "name": "Example Cinematic VPFX Pack", "version": "1.0.0", "author": "Your Name", "description": "A cinematic color grading pack for VPFX.", "entry_post_effect": "post_effect/main.json",
"capabilities": { "scene_color": true, "scene_depth": true, "shadow_depth": true, "custom_targets": true, "compute": false },
"targets": { "shadow_depth": "vulkanpostfx:shadow_depth" },
"textures": { "BlueNoise": { "path": "textures/blue_noise.png", "filter": "nearest", "wrap": "repeat" }, "ColorLut": { "path": "textures/lut.png", "filter": "linear", "wrap": "clamp" } },
"metadata": { "homepage": "https://example.com", "license": "MIT", "tags": [ "cinematic", "color-grading", "shadow-depth" ] }}Do not copy this full example for your first pack unless you actually need these features. Start minimal.
4. Field summary
| Field | Type | Required | Description |
|---|---|---|---|
format_version | integer | Yes | VPFX manifest format version. Currently must be 1. |
pack_id | string | Yes | Unique pack identifier and namespace. |
name | string | Yes | Display name shown to users. |
version | string | Yes | Pack version string. |
author | string | No | Pack author. Defaults to empty string. |
description | string | No | Short pack description. Defaults to empty string. |
entry_post_effect | string | Yes | Path to the main post-effect graph inside the zip. |
capabilities | object | Yes | Runtime features required by this pack. |
targets | object | Conditional | Required when capabilities.shadow_depth is true. |
textures | object | No | Declared external texture files. |
metadata | object | No | Optional homepage, license, and tags. |
5. format_version
Required.
"format_version": 1Current supported value:
1If another value is used, the pack will fail to load.
Invalid:
"format_version": 2The current parser rejects unsupported versions with:
F002 format_version6. pack_id
Required.
"pack_id": "example_minimal_pack"pack_id is the pack’s unique identifier. It is also used as the namespace in shader references.
Allowed pattern:
^[a-z0-9_.-]{3,64}$Allowed characters:
lowercase lettersnumbersunderscore _dot .hyphen -Length:
3 to 64 charactersGood examples:
example_minimal_packcinematic_tone_packauthor.cool_packdebug-shadow-viewvpfx_bsl_tone_showcaseBad examples:
Example PackMy Shader!!!abcool packshader@packInvalid pack_id values are rejected with:
F003 pack_id7. name
Required.
"name": "Example Minimal VPFX Pack"This is the human-readable display name.
It must be a non-empty string.
Good:
"name": "Warm Cinematic Tone"Bad:
"name": ""8. version
Required.
"version": "1.0.0"This is the pack version, not the VPFX manifest format version.
Recommended style:
1.0.01.1.0-beta0.2.3-previewThe parser only requires this to be a non-empty string.
Do not confuse:
"format_version": 1with:
"version": "1.0.0"format_version is the VPFX manifest format.
version is your pack version.
9. author
Optional.
"author": "Your Name"If omitted, VPFX stores it as an empty string.
Recommended:
"author": "PlayerName"or:
"author": "Team Name"10. description
Optional.
"description": "A warm cinematic tone mapping pack."If omitted, VPFX stores it as an empty string.
Keep it short. The description may be used in UI search or pack listings.
Good:
"description": "Warm color grading with subtle contrast and vignette."Bad:
"description": "best shader ever"11. entry_post_effect
Required.
"entry_post_effect": "post_effect/main.json"This path must exist inside the zip.
If the file does not exist, the pack will fail to load with:
F005 entry_post_effectCorrect:
my_pack.zip├─ pack.json└─ post_effect/ └─ main.jsonManifest:
"entry_post_effect": "post_effect/main.json"Incorrect:
"entry_post_effect": "post_effect/does_not_exist.json"12. capabilities
Required.
"capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": false, "custom_targets": true, "compute": false}All five fields are required and must be booleans.
| Field | Type | Meaning |
|---|---|---|
scene_color | boolean | The pack requires access to scene color. |
scene_depth | boolean | The pack requires scene depth support. |
shadow_depth | boolean | The pack requires VPFX shadow depth support. |
custom_targets | boolean | The pack requires custom render targets. |
compute | boolean | The pack requires compute shader support. |
Current VPFX runtime capabilities are:
scene_color: truescene_depth: trueshadow_depth: truecustom_targets: truecompute: falseThis means:
"compute": trueis not currently supported and will fail capability validation.
For a first pack, use:
"capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": false, "custom_targets": true, "compute": false}13. Capability rules
13.1 scene_color
Use:
"scene_color": trueif your pack reads:
minecraft:scene_colorMost packs should set this to true.
13.2 scene_depth
Use:
"scene_depth": trueif your pack needs scene depth.
Scene depth is for main-camera depth effects, such as:
depth fogdepth debug viewdistance-based color gradingdepth-aware outlinesDo not enable this unless your graph actually uses scene depth.
13.3 shadow_depth
Use:
"shadow_depth": trueif your pack needs VPFX shadow map depth.
shadow_depth is not the same as scene depth.
It may contain:
terrain castersentity castersplayer castersblock entity castersIf shadow_depth is enabled, the manifest must also include:
"targets": { "shadow_depth": "vulkanpostfx:shadow_depth"}If shadow_depth is enabled but targets.shadow_depth is missing, the manifest parser rejects the pack.
13.4 custom_targets
Use:
"custom_targets": trueif your graph declares custom targets in post_effect/main.json.
For many packs, this can be true even if the first version has no custom targets.
If you want the strictest minimal declaration for a copy pass with no custom target, you can use:
"custom_targets": falseHowever, most pack authors will eventually need custom targets for blur, bloom, downsampling, or multi-pass effects.
13.5 compute
Current recommendation:
"compute": falseVPFX currently reports compute support as unavailable.
Do not set:
"compute": trueunless the runtime explicitly supports it in a future version.
14. targets
Conditional.
The manifest-level targets object is currently required when:
"shadow_depth": trueExample:
"targets": { "shadow_depth": "vulkanpostfx:shadow_depth"}The target mapping value must match:
^[a-z0-9_.-]+:[a-z0-9_./-]+$Good target identifiers:
vulkanpostfx:shadow_depthminecraft:shadow_depthexample_pack:tempauthor_pack:blur/downsample_0Bad target identifiers:
shadow_depthExample:Targetpack id:targetpack:/badImportant:
Manifest-level targets is not the same thing as graph-level targets.
Graph-level targets are declared in:
post_effect/main.jsonManifest-level targets is used as a pack-level capability contract.
For current v1 packs, the most important rule is:
If capabilities.shadow_depth is true, targets.shadow_depth must exist.Recommended shadow-depth mapping:
"targets": { "shadow_depth": "vulkanpostfx:shadow_depth"}If your pack does not use shadow depth, you can omit targets.
15. textures
Optional.
The textures object declares extra texture files that can be used by the pack.
Example:
"textures": { "BlueNoise": { "path": "textures/blue_noise.png", "filter": "nearest", "wrap": "repeat" }, "ColorLut": { "path": "textures/lut.png", "filter": "linear", "wrap": "clamp" }}Each texture entry name must be a GLSL-safe identifier.
Allowed texture name pattern:
^[A-Za-z_][A-Za-z0-9_]*$Good names:
BlueNoiseColorLutNoiseTex_DitherPatternBad names:
blue-noise1Noisemy texturenoise.texture16. Texture entry fields
Each texture entry is an object.
16.1 path
Required.
"path": "textures/blue_noise.png"The file must exist inside the zip.
If the file is missing, the pack fails to load.
Correct:
my_pack.zip├─ pack.json└─ textures/ └─ blue_noise.pngManifest:
"textures": { "BlueNoise": { "path": "textures/blue_noise.png" }}16.2 filter
Optional.
Supported values:
linearnearestDefault:
linearExamples:
"filter": "linear""filter": "nearest"Use nearest for noise textures, masks, pixel-art lookup images, or exact sample patterns.
Use linear for smooth lookup textures.
16.3 wrap
Optional.
Supported values:
clamprepeatDefault:
clampExamples:
"wrap": "clamp""wrap": "repeat"Use repeat for tiling noise textures.
Use clamp for lookup tables, masks, and non-tiling images.
17. metadata
Optional.
Example:
"metadata": { "homepage": "https://example.com", "license": "MIT", "tags": [ "cinematic", "warm", "tone-mapping" ]}Supported fields:
| Field | Type | Required | Description |
|---|---|---|---|
homepage | string | No | Project page, download page, or author page. |
license | string | No | License name. |
tags | string array | No | Searchable tags. |
If metadata is omitted, VPFX stores:
homepage: ""license: ""tags: []metadata.tags must be an array of strings.
Good:
"tags": [ "cinematic", "shadow-depth", "color-grading"]Bad:
"tags": "cinematic"Bad:
"tags": [ "cinematic", 123]18. Required fields checklist
A valid VPFX v1 manifest must include:
format_versionpack_idnameversionentry_post_effectcapabilities.scene_colorcapabilities.scene_depthcapabilities.shadow_depthcapabilities.custom_targetscapabilities.computeIf capabilities.shadow_depth is true, it must also include:
targets.shadow_depth19. Optional fields checklist
Optional fields:
authordescriptiontargetstexturesmetadatametadata.homepagemetadata.licensemetadata.tagsRemember:
targets becomes required when shadow_depth is enabled.20. Common manifest errors
20.1 Missing pack.json
Cause:
pack.json is not at the zip root.Error code:
F001 pack.jsonFix the zip layout.
20.2 Unsupported format_version
Cause:
"format_version": 2Current supported value is:
"format_version": 1Error code:
F002 format_version20.3 Invalid pack_id
Cause:
"pack_id": "My Cool Pack!"Fix:
"pack_id": "my_cool_pack"Error code:
F003 pack_id20.4 Missing entry post-effect file
Cause:
"entry_post_effect": "post_effect/missing.json"but the file does not exist in the zip.
Error code:
F005 entry_post_effect20.5 Missing required field
Cause:
{ "format_version": 1, "pack_id": "example_pack"}Missing required fields such as name, version, entry_post_effect, or capabilities.
Error code:
F00620.6 Invalid capability object
Cause:
"capabilities": { "scene_color": true}All capability booleans are required.
Correct:
"capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": false, "custom_targets": true, "compute": false}20.7 shadow_depth enabled without targets.shadow_depth
Invalid:
{ "format_version": 1, "pack_id": "shadow_pack", "name": "Shadow Pack", "version": "1.0.0", "entry_post_effect": "post_effect/main.json", "capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": true, "custom_targets": true, "compute": false }}Valid:
{ "format_version": 1, "pack_id": "shadow_pack", "name": "Shadow Pack", "version": "1.0.0", "entry_post_effect": "post_effect/main.json", "capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": true, "custom_targets": true, "compute": false }, "targets": { "shadow_depth": "vulkanpostfx:shadow_depth" }}Error code:
F007 targets.shadow_depth20.8 Invalid texture name
Invalid:
"textures": { "blue-noise": { "path": "textures/blue_noise.png" }}Correct:
"textures": { "BlueNoise": { "path": "textures/blue_noise.png" }}Error code:
F008 textures.<name>20.9 Missing texture file
Cause:
"textures": { "BlueNoise": { "path": "textures/blue_noise.png" }}but the zip does not contain:
textures/blue_noise.pngError code:
F008 textures.BlueNoise.path20.10 Unsupported texture filter or wrap
Invalid:
"filter": "trilinear"Valid:
"filter": "linear"or:
"filter": "nearest"Invalid:
"wrap": "mirror"Valid:
"wrap": "clamp"or:
"wrap": "repeat"Error code:
F00821. Legacy fields not used by VPFX v1 native packs
Do not use the old legacy fields for new VPFX native packs.
Avoid:
"id": "example_pack"Use:
"pack_id": "example_pack"Avoid:
"entry_effect_key": "some_effect"VPFX v1 native packs use:
"entry_post_effect": "post_effect/main.json"The current native pack path is based on pack.json with format_version, pack_id, entry_post_effect, and capabilities.
22. Recommended manifest for first packs
For a simple first pack:
{ "format_version": 1, "pack_id": "my_first_vpfx_pack", "name": "My First VPFX Pack", "version": "1.0.0", "author": "Your Name", "description": "My first VPFX scene-color post-processing pack.", "entry_post_effect": "post_effect/main.json", "capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": false, "custom_targets": true, "compute": false }, "metadata": { "license": "MIT", "tags": [ "minimal", "color" ] }}This is the recommended starting point.
23. Recommended manifest for shadow-aware packs
For a pack that uses VPFX shadow depth:
{ "format_version": 1, "pack_id": "my_shadow_pack", "name": "My Shadow VPFX Pack", "version": "1.0.0", "author": "Your Name", "description": "A VPFX pack that uses shadow_depth.", "entry_post_effect": "post_effect/main.json", "capabilities": { "scene_color": true, "scene_depth": true, "shadow_depth": true, "custom_targets": true, "compute": false }, "targets": { "shadow_depth": "vulkanpostfx:shadow_depth" }, "metadata": { "tags": [ "shadow-depth", "shadow-receiver", "experimental" ] }}Only use this after you understand how to sample shadow_depth.
24. Recommended manifest for packs with declared textures
For a pack using texture inputs:
{ "format_version": 1, "pack_id": "my_texture_pack", "name": "My Texture VPFX Pack", "version": "1.0.0", "author": "Your Name", "description": "A VPFX pack using a declared blue noise texture.", "entry_post_effect": "post_effect/main.json", "capabilities": { "scene_color": true, "scene_depth": false, "shadow_depth": false, "custom_targets": true, "compute": false }, "textures": { "BlueNoise": { "path": "textures/blue_noise.png", "filter": "nearest", "wrap": "repeat" } }, "metadata": { "tags": [ "blue-noise", "dithering" ] }}The file must exist at:
textures/blue_noise.pnginside the zip.
25. Validation behavior
When VPFX scans a zip:
1. It checks whether pack.json exists at the zip root.2. It parses the manifest.3. It checks format_version.4. It validates pack_id.5. It checks entry_post_effect exists.6. It parses capabilities.7. It parses manifest-level targets if present.8. It parses declared textures if present.9. It parses optional metadata if present.10. It parses the post-effect graph.11. It validates graph targets and passes.12. It checks shader files exist.13. It preprocesses shader includes.If the pack fails validation, VPFX logs an error and skips the pack.
26. Manifest authoring checklist
Before sharing a pack, check:
pack.json is at the zip root.format_version is 1.pack_id matches ^[a-z0-9_.-]{3,64}$.name is not blank.version is not blank.entry_post_effect points to an existing file.capabilities contains all five boolean fields.compute is false.targets.shadow_depth exists if shadow_depth is true.declared texture names are GLSL-safe.declared texture paths exist in the zip.metadata.tags is an array of strings.27. Next document
This document only covers pack.json.
The next document should cover:
04 - Post Effect Graph FormatThat document explains:
post_effect/main.jsontargetspassesinputsoutputssampler namescustom targetsscene depthshadow depth inputsself-read/write rules