⚠️ Note: The Portable Effects specification is still being finalized and may change.
The Portable Effects Format is an open standard for sharing shader effects across the Noise Factor ecosystem.
This repository serves as the canonical source of truth for the Portable Effects specification.
Portable Effects are self-contained shader packages that work across all Noise Factor applications.
portable/
├── effect/ # Working example effect
│ ├── definition.json # Effect definition
│ ├── dsl.txt # Example DSL program
│ ├── help.md # Effect documentation
│ ├── glsl/
│ │ └── example.glsl # WebGL shader
│ └── wgsl/
│ └── example.wgsl # WebGPU shader
├── viewer/ # Hot-reloading effect viewer
│ ├── index.html # Full-page viewer with param controls
│ └── vendor/ # Noisemaker runtime (after pull)
├── docs/ # Format specification
└── pull-noisemaker # Script to fetch runtime
cd portable
./pull-noisemakerThis fetches the latest Noisemaker runtime bundle.
Modify files in the effect/ directory:
definition.json— Effect definition and parametersglsl/example.glsl— WebGL shader codewgsl/example.wgsl— WebGPU shader code
Open viewer/index.html in a browser. The viewer automatically reloads when you save changes.
Create a ZIP archive for sharing or importing into applications:
# Using bash
./package-portable.sh
# Or using Node.js
npm run packageThis creates effect.zip.
To use your effect in Noisedeck or other Noise Factor applications:
- Open the application
- Go to File Menu → Import Effect from ZIP...
- Select your
effect.zipfile - Your effect will be available in the effect browser
Use it in DSL programs:
search user
example().write(o0)
render(o0)The included effect/ directory contains a complete portable effect based on synth.solid:
effect/definition.json:
{
"name": "Example",
"namespace": "user",
"func": "example",
"description": "Solid color fill - example portable effect",
"starter": true,
"globals": {
"r": { "type": "float", "default": 0.5, "min": 0, "max": 1 },
"g": { "type": "float", "default": 0.5, "min": 0, "max": 1 },
"b": { "type": "float", "default": 0.5, "min": 0, "max": 1 },
"a": { "type": "float", "default": 1.0, "min": 0, "max": 1 }
},
"passes": [{ "name": "example", "program": "example", "outputs": { "color": "outputTex" } }]
}effect/glsl/example.glsl:
#version 300 es
precision highp float;
uniform float r, g, b, a;
out vec4 fragColor;
void main() {
fragColor = vec4(r * a, g * a, b * a, a);
}A portable effect needs only two files:
my-effect/
├── definition.json # Effect metadata and parameters
└── glsl/
└── main.glsl # Fragment shader source
{
"name": "My Effect",
"func": "myEffect",
"namespace": "synth",
"description": "A simple shader effect",
"starter": true,
"tags": ["noise", "custom"],
"globals": {
"scale": {
"type": "float",
"default": 1.0,
"min": 0.1,
"max": 10.0
}
}
}#version 300 es
precision highp float;
uniform vec2 resolution;
uniform float time;
uniform float scale;
in vec2 vUv;
out vec4 fragColor;
void main() {
vec2 uv = vUv * scale;
vec3 color = vec3(uv, sin(time) * 0.5 + 0.5);
fragColor = vec4(color, 1.0);
}Once loaded into any Noisemaker application, use it in DSL programs:
search user
myEffect(scale: 2.0).write(o0)
render(o0)
| Document | Description |
|---|---|
| FORMAT.md | Complete specification of the effect format |
| PARAMETERS.md | Defining uniforms and UI controls |
| SHADERS.md | Writing compatible GLSL shaders |
| DSL.md | Using effects in the Polymorphic DSL |
| VIEWER.md | Using the hot-reloading effect viewer |
| Type | Namespace | Description |
|---|---|---|
| Starter | synth |
Generates 2D imagery from scratch |
| Filter | filter |
Transforms a 2D input texture |
| Mixer | mixer |
Blends two input textures |
| 3D Starter | synth3d |
Generates 3D volumetric data |
| 3D Filter | filter3d |
Transforms 3D volumetric data |
| Points | points |
Agent/particle simulations |
| Render | render |
Rendering utilities (loops, 3D) |
The starter field in definition.json determines whether an effect can begin a DSL chain or must receive input from another effect.
This specification is released under the MIT License.
Effects you create are your own — share them however you like.