Material Apprentice is an agentic framework for procedural material generation and editing by reflecting tacit expertise in video tutorials.
- Create a new conda environment for the project
conda create -n materialapprentice -c conda-forge python=3.12
conda activate materialapprentice
- Download Blender 4.5. For MacOS, open the
.dmgfile and drag the app tomaterial-apprentice/blender/. For Linux, unzip atmaterial-apprentice/blender/blender-4.5.4-linux-x64. Note: first manually opening Blender on MacOS helps resolve security issues. Next, set paths.
MacOS
export BLENDER_PATH=/path/to/repo/material-apprentice/blender/Blender.app/Contents/MacOS/Blender
export BLENDER_PYTHON=/path/to/repo/material-apprentice/blender/Blender.app/Contents/Resources/4.5/python/bin/python3.11
Linux
export BLENDER_PATH=/path/to/repo/material-apprentice/blender/blender-4.5.4-linux-x64/blender
export BLENDER_PYTHON=/path/to/repo/material-apprentice/blender/blender-4.5.4-linux-x64/4.5/python/bin/python3.11
On a headless Linux box, Blender also needs a few system libraries. If $BLENDER_PATH --version fails with a libXfixes.so.3 (or similar) error:
sudo apt-get install -y libxfixes3 libxi6 libxrender1 libxxf86vm1 libxkbcommon0 \
libsm6 libgl1 libxrandr2 libxinerama1 libxcursor1
- Install dependencies. There are two tiers: the conda env only needs the launcher, while the pipeline itself runs inside Blender's bundled Python.
pip install -r requirements.txt
$BLENDER_PYTHON -m pip install -r requirements-blender.txt
The pinned files above reproduce a known-good install. For the latest versions instead, use:
pip install sceneprogexec
sceneprogexec install numpy matplotlib sceneprogsyn sceneprogexec sceneprogllm
- Set your OpenAI API key
export OPENAI_API_KEY=sk-...
Run all commands from the repository root. The pipeline resolves
dataset/,assets/,node_cache/, andresults/relative to the current working directory.
Generate a new procedural material from a text prompt:
sceneprogexec run apprentice.py -- -p "rusted iron" -o output.blend
Optionally provide a reference image with -i:
sceneprogexec run apprentice.py -- -p "rusted iron" -i reference.png -o output.blend
Edit an existing material given its source program.py and a new prompt.
The program from a previous generation is stored inside that run's log at results/<output>_log.npz, where <output> is the stem of the -o filename you passed (so -o output.blend writes results/output_log.npz). Extract it to a .py first:
import numpy as np
log = np.load("results/output_log.npz", allow_pickle=True)
# best_code3 is the final selected program, as (source_code, render_image)
with open("rusted_iron_program.py", "w") as f:
f.write(log["best_code3"][0])Then pass that file to --initial_code:
sceneprogexec run apprentice.py -- \
-p "add green moss patches in the crevices" \
--initial_text "rusted iron" \
--initial_code rusted_iron_program.py \
-o output.blend
--initial_text is the name of the source material. --initial_code is the path to its program.py. Both must be provided together.
| Flag | Required | Description |
|---|---|---|
-p / --prompt |
Yes | Text description of the target material |
-o / --output |
Yes | Output .blend file path |
-i / --image |
No | Reference image path |
--initial_text |
No* | Source material name (editing mode) |
--initial_code |
No* | Path to source program.py (editing mode) |
--model |
No | Model name (default: gpt-5) |
-k / --api_key |
No | OpenAI API key (overrides OPENAI_API_KEY) |
| Path | Purpose |
|---|---|
apprentice.py |
Canonical entrypoint — generation and editing (local) |
core/ |
Pipeline stages (rag, generator, compiler, sampler, evaluator, exporter, …) |
blender/ |
The MaterialGraph DSL (node API, groups, layout, export) |
assets/ |
Few-shot context files for each stage |
dataset/ |
Processed video-tutorial corpus used for retrieval |
node_cache/ |
Precomputed node-attribute embeddings (avoids re-embedding on every run) |
results/ |
Per-run logs (<output>_log.npz), including the generated programs |