CustomScript-NumPy
Write raw NumPy on your images — the UE5 Material Editor trick, ported to ComfyUI
- imga
- imgb
- imgc
- IMAGE
If you've ever sat in a game engine's material editor wishing you could just type result = np.maximum(a, b) instead of chaining five blend nodes, this is the node for you. CustomScript-NumPy is the flagship of the ComfyUI-FuncAsTexture pack, and the author built the whole pack around it. It's a direct transplant of Unreal Engine 5's Custom node from the Material Editor: you type NumPy code, it runs on your images.
The pitch in the README is disarmingly honest - the author was tired of guessing blend weights (is this screen or overlay and at what strength?) and wanted visible, rule-based image math instead of trial and error. That's the whole ethos of the pack: everything else in it is a pre-baked example of this one node.
How it works
You get three image inputs (imga, imgb, imgc) and the node hands them to your script as NumPy arrays shaped [B, H, W, C], float values 0–1, channel-last. Beyond the raw arrays it does a few thoughtful things:
- Channels are pre-split. You get
imga_r,imga_g,imga_b(and the same forimgbandimgc) as copies, so you can manipulate one channel without juggling slices. - A
make_rgb(r, g, b)helper is pre-defined to stack three channels back together. import numpy as npis already done - no need to add it, though it won't hurt.- Five parameters are exposed as widgets -
pfloat1–pfloat3(floats, negatives allowed) andpint1–pint2(ints) - and injected into your script's namespace. That's how you build reusable formulas with knobs on them instead of hardcoding numbers.
Your script runs, and whatever you assign to result comes out the IMAGE output, auto-converted back to the [B, H, W, C] tensor format ComfyUI expects. Leave imga unconnected and you get a 512×512 zero canvas to work against (which is exactly how several derived nodes rely on it).
The formula input is the one you actually live in - it's a multiline text box, and it's the only required input.
The two or three things that actually matter
formula- your NumPy code. Useresult = ...to output. Reference the arrays and parameters above.imga- the reference image. Its resolution defines the output resolution (512×512 if unconnected).pfloat1/pint1- the parameter knobs your formula reads. Optional until your formula references them.
Some formulas to steal from the README:
# Weighted blend - rule-based, no guessing
result = imga * 0.7 + imgb * 0.3
# Binarize
threshold = 0.5
result = np.where(imga > threshold, 1.0, 0.0)
# Rec.601-ish grayscale, then rebuild RGB
gray = 0.299 * imga_r + 0.587 * imga_g + 0.114 * imga_b
result = make_rgb(gray, gray, gray)
Install
ComfyUI Manager → search "FuncAsTexture", or:
cd ComfyUI/custom_nodes
git clone https://github.com/CoiiChan/ComfyUI-FuncAsTexture-CoiiNode
# then restart ComfyUI
There's no requirements.txt and nothing to download - the pack only needs NumPy, PyTorch, and Pillow, all of which ComfyUI ships. It registers under the FunctionAsTexture category.
Where people get burned
- Resolution mismatch. The README's own warning: if
imgaandimgbdiffer in size, NumPy will either throw or broadcast something you didn't intend. Keep them the same resolution. - No clamping. Your output is not forced to 0–1. Values above 1 or below 0 will exist in the tensor even if the preview looks clipped - pipe through the pack's Clamp node or clip in the formula.
- Syntax errors are loud. The node wraps your script in a
try/except, so a typo surfaces asError evaluating formula: <your code>. Read the tail of that error; it includes the Python traceback. - The formula is a required input on every derived node too. If you open Add or Max and see a big wall of script, that's not a bug - these nodes are literally this node with a pre-filled formula and hidden parameters. You can edit them.
The "i person" in the README's sign-off isn't a typo - the author describes themselves as an independent maker of specialized nodes, and deliberately refuses to build an all-in-one pack. That focus is why this node's ergonomics are better than the usual "exec a string" hacks floating around.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| formula | STRING | #Default already import numpy as np imga_r = (imga_r + imga_g) * 0.5 imga = make_rgb(imga_r, imga_g, imga_b) result = imga #Node Introduction:https://github.com/CoiiChan/Comfyui-FuncAsTexture-CoiiNode | — |
| imgaopt | IMAGE | Optional ,Reference size ,Default =(1,512,512,3) | |
| imgbopt | IMAGE | Optional | |
| imgcopt | IMAGE | Optional | |
| pfloat1opt | FLOAT | 0.00 | Optional,Floating-point parameter passed to the script. |
| pfloat2opt | FLOAT | 0.00 | Optional,Floating-point parameter passed to the script. |
| pfloat3opt | FLOAT | 0.00 | Optional,Floating-point parameter passed to the script. |
| pint1opt | INT | 0 | Optional(INT),Integer parameter passed to the script. |
| pint2opt | INT | 0 | Optional(INT),Integer parameter passed to the script. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |