Contents
Math Parser represents a fundamental shift in Cycles shading workflow, transforming the renderer from a static node graph into a 'programmable' rendering engine. It allows you to evaluate complex, user-defined mathematical expressions directly within the shader graph, effectively replacing entire trees of "Math" and "Vector Math" nodes with a single, readable formula like sin(x) * y + dot(N, z).
Under the hood, Math Parser features a built-in expression parser.. when shaders are compiled in the SVM Cycles compile process, it translates the text string into a highly optimized, integer-based bytecode. This bytecode is then executed by a lightweight, custom-built Virtual Machine running natively on the GPU (OptiX/CUDA) or CPU. This two-stage architecture ensures that string parsing happens only once, while the rendering loop executes pre-calculated instructions with zero runtime overhead.
The result is the flexibility of 'code' with the raw speed of native nodes. Whether you are designing complex fractals, custom shapes, trigonometric patterns, or whatever you have in mind .. you now have direct access to the engine's math core without sacrificing speed and workflow consistency.
Beyond raw performance, effectively, this tool is a massive workflow accelerator. Complex mathematical logic — which typically requires chaining dozens of Math, Vector Math, and Mix nodes into an unreadable "spaghetti" graph — can now be condensed into a single node.
This creates a self-documenting workflow: a formula like pow(max(0, dot(N, P)), 5) is instantly recognizable, whereas the equivalent node structure requires tracing wires across the screen to decipher it. This paradigm shift allows for rapid prototyping — edit your expressions instantly and spend your time refining the render, not debugging spaghetti connections.
Workflow
Complex shading logic often turns node trees into unreadable shading webs. Math Parser collapses entire sub-graphs into a single, readable node. It supports vector operations natively (component-wise math), meaning sin(x) works whether x is a single float or a 3D vector. You can use as many Math Parser nodes as you want also mixed with any other existing node while it natively supports the new Repeat Zone in Blender 5.0+.
Composability
You don't need to write one massive, unreadable formula.
The Math Parser is designed for Expression Chaining.
Because inputs x, y, and z are standard sockets, you can chain multiple Math Parser nodes together.
Example 1:
- Circles grid approached one step at time
We can use this approach while prototyping, once final, - we'll put all together.
Example 2:
- Node A only passes in 24 as pure value.
- Node B creates a Circles Grid.
- Node C creates a Diamond Checker.
- Node D simply says x + (y*0.75) to combine them.
This modular approach keeps your logic clean, readable, and reusable, allowing you to build complex Compound Logic from simple, atomic expressions.
How it Works
The implementation follows a distinct two-stage "compiler/interpreter" architecture that strictly separates the CPU-intensive parsing setup from the performance-critical rendering loop. This mirrors the native architecture of the Cycles SVM (Shading Virtual Machine) itself, ensuring that the Math Parser introduces zero runtime overhead. By pre-compiling text expression into optimized integer bytecode before the render starts, the node executes with the same raw speed, stability, and vectorization as a hard-coded C++ node, remaining fully compatible with OptiX and CUDA acceleration.
When you edit the string parameter, a custom parser tokenizes your math and compiles it into a linear array of integer-based bytecode. We also do constant folding and other optimization there. This happens only once.
During rendering, the shader kernel reads this pre-compiled bytecode. A tiny Virtual Machine executes the instructions. No string parsing happens during the render, ensuring native GPU speeds.
Design Philosophy
The parser has been built specifically for the strict environment of a render kernel. It prioritizes stability and predictability over general-purpose scripting features.
- Deterministic: CPU and GPU results are guaranteed to match exactly.
- Zero Allocation: Uses no dynamic memory or STL during render time. Safe for kernels.
- POD-Only: The runtime is purely "Plain Old Data" (integers/floats), making it ultra-fast to load.
- Scalar & Vector: Full float/vector math support.
- Shader Globals: Access Position (P), Normal (N), UV, derivatives etc.
- Constants: PI, E, GR (Golden Ratio).
- Operators: Unary, Binary, Ternary, and Bitwise shifts.
- No Control Flow: No
if/else(usemixorstep). - No Loops: No
fororwhileloops. - No Custom Funcs: No new function definitions.
- Evolving Core: The parser is built to grow.
- Roadmap: High-level Color functions (Gamma, Contrast, Tint etc.) and additional Math Constants are actively being implemented.
- Backward Compatible: New functions are added without breaking existing expression syntax.
Ecosystem Integration
The Math Parser isn't an external script or a post-process effect; it is a fully integrated, native SVM shader node. This means it behaves exactly like any other node in the graph, offering first-class support for Blender's modern architecture.
The parser statically analyzes your expression before rendering. It intelligently flags the Cycles kernel to request heavy attributes (like UV derivatives or Tangents) only if they are explicitly used. Additionally, if no input variables are used, - no eval at all in the rendering loop.
There are no global limits.. you can use as many Math Parser nodes as you need in a single material tree. Thanks to the highly optimized bytecode architecture, the memory footprint remains negligible even with hundreds of instances.
You don't have to choose between code and nodes. Use the Math Parser to handle complex formulas logic, then pipe the result into standard Color Ramps, Mix nodes, or Principled BSDFs. It fits perfectly into any existing node pipeline.
Because the parser operates as a stateless, pure mathematical function, it is fully compatible with the new Repeat Zone. You can safely place the node inside loops to perform iterative fractal calculations, accumulation of any sort or complex simulation logic directly in the shader.
Safety & Debugging
We have engineered the Math Parser to be both robust against mathematical errors and helpful when you make a typo. It is designed to never crash.
Standard math functions can produce NaNs (Not a Number) or 'infinite' values if fed the wrong data. MathParser uses "Safe" versions of potential problematic functions that gracefully handle edge cases by returning 0.0 or by clamping input values.
- Division by Zero: Returns
0.0instead of crashing. - Invalid Roots:
sqrt(-x)returns0.0. - Logarithms:
log(0),log(-x)are handled safely. - Trigonometry:
asin/acosinputs > 1 are clamped. - Power:
pow(-x, float)returns0.0. - Modulo:
fmod(x, 0)returns0.0.
If an expression is invalid, the node won't just silently fail. The compiler analyzes the string and outputs verbose error messages to the console, helping fix typos instantly.
- Invalid Characters: Detects typos or unsupported symbols.
- Syntax Logic: Identifies misplaced commas outside functions.
- Parentheses: Detects mismatched
(open or closed)brackets. - Structure: Validates operator usage (e.g., preventing
**or//). - Fnc calling: Validates fnc arguments usage (e.g., preventing
sin(x,y)or-2instead of neg(2).
Reliability is paramount. We don't just check if the result "looks right" visually. The parser core is rigorously validated against a suite of hundreds of numerical unit tests. We compare the bytecode output against ground-truth C++ math libraries to ensure precision, stability, and identical behavior across CPU and GPU architectures.
Syntax Reference
The parser supports standard arithmetic operators + - * / % (modulo) and bitwise operations. It fully supports arbitrary nesting of parentheses ((...)) to define complex execution orders.
x, y, z.
(Case insensitive: X, Y, Z also work)
x.x, y.z, or Z.y
sin(x) works whether x is a float or a vector.
0.5, .5, 1., or 1 are all valid.
Operators
| + - * / | Standard Arithmetic (Add, Subtract, Multiply, Divide). |
| % | Modulo (Remainder of division). |
| ^ | Power / Exponentiation ($x^y$). |
| & | | Bitwise AND / Bitwise OR (Operates on integer bits). |
| << >> | Bitwise Left Shift / Right Shift. |
Trigonometry & Basic Math
| sin(a), cos(a), tan(a) | Standard trigonometric functions (radians). |
| asin(a), acos(a), atan(a) | Inverse trigonometry (Arc functions). |
| sinh(a), cosh(a), tanh(a) | Hyperbolic functions. |
| pow(a, b), sqrt(a) | Power ($a^b$) and Square Root. |
| exp(a), log(a), log2(a), log10(a) | Exponential ($e^a$) and Logarithms (Natural, Base-2, Base-10). |
| floor(a), ceil(a), trunc(a) | Rounding functions. |
| neg(a) | Negates the input. Use neg(2) instead of -2. |
| inv(a) | Inverts the input. |
| fract(a), mod(a, b) | Fractional part and Modulo (remainder). |
Vector Math
| dot(a, b) | Dot product. Returns scalar. |
| cross(a, b) | Cross product. Returns vector perpendicular to a and b. |
| length(v) | Returns the magnitude of vector v. |
| distance(a, b) | Distance between points a and b. |
| normalize(v) | Returns direction vector (length 1.0). |
| reflect(I, N) | Reflects vector I against normal N. |
| refract(I, N, ior) | Calculates refraction vector based on Index of Refraction. |
Logic & Blending
| mix(a, b, t), lerp(...) | Linear interpolation between a and b by factor t. |
| sstep(a, b, t) | Smoothstep, hermite interpolation. Returns 0 if t < a; 1 if t > b, and smooths in between. |
| step(edge, x) | Returns 0.0 if x < edge, otherwise 1.0. Hard mask. |
| min(a, b), max(a, b) | Returns the smaller or larger of two values. |
| clamp(x, min, max) | Constrains x to stay between min and max. |
| union(vec, vec), diff(...) | Fuzzy boolean between two vectors. |
| saturate(x) | Shortcut for clamp(x, 0.0, 1.0). |
Specials
| smin(a, b, k), smax(...) | Smooth Minimum/Maximum. Blends a and b with factor k. |
| rotate(vec, axis, angle) | Rotates vector vec around axis by angle (radians). |
| translate(vec, vec) | Translate a vector vec by another vec. |
| scale(vec, vec) | Scale a vector vec by another vec. |
| pulse(x, center, width) | Returns 1.0 if x is within width of center. Great for isolines. |
| wloop(val, min, max) | Wraps values continuously (sawtooth wave) between min and max. |
| luma(color) | Calculates the luminance (brightness) of a vector color. |
| rnd(seed) | High quality pseudo-random number generator (splitmix64-based). |
| vec(a, b, c) | Create a vector with a, b, c components. |
Shader Globals
| P, N, NG | World Space: Shading Position, Smooth Normal, and Geometric Normal. |
| PO, NO | Object Space: Position and Normal. |
| WI, RL | Incoming Ray Vector (View Direction) and Ray Length (Distance to camera/surface). |
| UV, U, V, BUV |
Default Texture Coordinates. BUV accesses raw Barycentric UVs.
|
| DUXY, DVXY |
Derivatives: rate of change of UVs relative to screen pixels ($dUV/dx$, $dUV/dy$). |
| DPU, DPV | Surface tangents ($dP/du$, $dP/dv$). |
| VIEW |
Camera Space Coordinate (Local X, Local Y, Depth Z). (0,0,0 is Camera Position). |
WIN |
Raster Coordinate (Pixel X, Pixel Y, 0). (Range: 0 to Resolution). |
Constants
| PI | Archimedes constant (approx 3.14159). |
| TWOPI | PI x2 (approx 6.28318). |
| PITWO | PI /2 (approx 1.570796). |
| INVPI | 1 / PI (0.31830). |
| E | Euler's number (approx 2.71828). |
| PHI, GR | Golden Ratio (approx 1.61803). |
Expression Recipes
Copy these snippets into the Expression field.
Sine Wave Distortion
Adds a sine wave ripple traveling along the Y axis to the coordinate X.
Organic Soft Union (SDF)
Smoothly blends two spheres (radii 1.0 and 0.5) with a softness factor of 0.2.
Fresnel Term
Calculates a standard Fresnel edge glow effect manually.
Rounded Square
Draws a rounded square.
Concentric Shape
Draws concentric shapes.
Squares/Circles Pattern
Draws a nice alternated pattern.
Diamond Checkboard
Draws a diamond checkboard.
Origami Pattern
Draws a kind of origami pattern.
Bar Code
Draws a kind of origami pattern.
Smooth Circular Grid
Draws a kind of origami pattern.
