Expand description
§Nodal Scene Interface – ɴsɪ
A flexible, modern API for offline 3D renderers
Nsɪ is built around the concept of nodes. Each node has a unique handle to identify it. It also has a type which describes its intended function in the scene.
Nodes are abstract containers for data. The interpretation depends on the node type. Nodes can also be connected to each other to express relationships.
Data is stored on nodes as attributes. Each attribute has a name which is unique on the node and a type which describes the kind of data it holds (strings, integer numbers, floating point numbers, etc.). The standard ɴsɪ attribute names are exposed as typed constants – see Typed attribute names below.
Relationships and data flow between nodes are represented as connections. Connections have a source and a destination. Both can be either a node or a specific attribute of a node. There are no type restrictions for connections in the interface itself. It is acceptable to connect attributes of different types or even attributes to nodes. The validity of such connections depends on the types of the nodes involved.
What we refer to as the ɴsɪ has two major components:
-
Methods to create nodes, attributes and their connections. These are attached to a rendering
Context. -
Nodes understood by the renderer.
Much of the complexity and expressiveness of the interface comes from the supported nodes.
The first part was kept deliberately simple to make it easy to support multiple ways of creating nodes.
§Examples
// Create a context to send the scene to.
let ctx = nsi::Context::new(None).expect("Could not create NSI context.");
// Create a dodecahedron.
// 12 regular pentagon faces.
let face_index: [i32; 60] = [
0, 16, 2, 10, 8, 0, 8, 4, 14, 12, 16, 17, 1, 12, 0, 1, 9, 11, 3, 17, 1,
12, 14, 5, 9, 2, 13, 15, 6, 10, 13, 3, 17, 16, 2, 3, 11, 7, 15, 13, 4,
8, 10, 6, 18, 14, 5, 19, 18, 4, 5, 19, 7, 11, 9, 15, 7, 19, 18, 6,
];
// Golden ratio.
let phi: f32 = 0.5 * (1.0 + 5_f32.sqrt());
// Golden ratio conjugate.
let phi_c: f32 = phi - 1.0;
// 20 control points, each a Point3F32 ([f32; 3]).
// Length divisibility by 3 is enforced at the type level.
let positions: [nsi::Point3F32; 20] = [
[1., 1., 1.],
[1., 1., -1.],
[1., -1., 1.],
[1., -1., -1.],
[-1., 1., 1.],
[-1., 1., -1.],
[-1., -1., 1.],
[-1., -1., -1.],
[0., phi_c, phi],
[0., phi_c, -phi],
[0., -phi_c, phi],
[0., -phi_c, -phi],
[phi_c, phi, 0.],
[phi_c, -phi, 0.],
[-phi_c, phi, 0.],
[-phi_c, -phi, 0.],
[phi, 0., phi_c],
[phi, 0., -phi_c],
[-phi, 0., phi_c],
[-phi, 0., -phi_c],
];
// Create a new mesh node and call it 'dodecahedron'.
ctx.create("dodecahedron", nsi::MESH, None);
// Connect the 'dodecahedron' node to the scene's root.
ctx.connect("dodecahedron", None, nsi::ROOT, "objects", None);
// Define the geometry of the 'dodecahedron' node.
ctx.set_attribute(
"dodecahedron",
&[
// Typed name: `nsi::POSITION` is `Attribute<[nsi::Point3F32]>`.
// Wrong-shape data (e.g. a `&[f32]`) is rejected by rustc at
// this call site.
nsi::point_slice!(nsi::POSITION, &positions),
nsi::i32_slice!("P.indices", &face_index),
// 5 vertices per each face.
nsi::i32_slice!("nvertices", &[5; 12]),
// Render this as a subdivison surface.
nsi::string!("subdivision.scheme", "catmull-clark"),
// Crease each of the dodecahedron's 30 edges. Each edge is
// a pair (start, end) of vertex indices into `positions`,
// so this list is twice as long as `creasesharpness`.
nsi::i32_slice!(
"subdivision.creasevertices",
&[
0, 8, 0, 12, 0, 16, 1, 9, 1, 12, 1, 17, 2, 10, 2, 13,
2, 16, 3, 11, 3, 13, 3, 17, 4, 8, 4, 14, 4, 18, 5, 9,
5, 14, 5, 19, 6, 10, 6, 15, 6, 18, 7, 11, 7, 15, 7, 19,
8, 10, 9, 11, 12, 14, 13, 15, 16, 17, 18, 19,
]
),
nsi::f32_slice!("subdivision.creasesharpness", &[4.2; 30]),
],
);§More Examples
These can be found in the examples
folder.
All the examples in this crate require a (free) 3Delight installation to run!
§Interactive
Demonstrates using the FnStatus callback closure during rendering and a
channel for communicating between main- and rendering thread(s).
§Jupyter
Render directly into a Jupyter notebook.
Follow these instructions to get a Rust Jupyter kernel up and running first.
§Output
This is a full output example showing color conversion and writing data
out to 8bit/channel PNG and 32bit/channel (float) OpenEXR formats.
§Volume
Demonstrates rendering an OpenVDB asset. Mostly
through the toolbelt helpers.
§Crate Organization
The nsi crate is a facade. The work is split across smaller crates so
consumers can pick the layer they need:
nsi-trait– pure-Rust trait crate. DefinesNsi(selfis the context), theAttributetyped-name machinery,NodeType,Action, and the standard node-type / attribute-name constants. No FFI deps.nsi-ffi-wrap– FFI wrapper. ProvidesContext, the C-API loader (dynamic viadlopen2or static vialink_lib3delight), the parameter macros (f32!,point_slice!, …), andFfiApiAdapterwhich exposes any pure-RustNsiimpl through the C API (handle-mapping is internal, via a factory closure).nsi-3delight– helpers for the 3Delight renderer (environment lights, shader graphs, etc.).nsi-toolbelt– convenience scene-construction helpers (handle generation, append/prepend, transform shortcuts).nsi-jupyter– render into a Jupyter notebook.nsi-sys– auto-generated bindings for the NSI C header.nsi-procedural– scaffolding for writing procedural-node plugins.
The nsi crate re-exports everything from nsi-ffi-wrap (which itself
pulls types and constants from nsi-trait) so a typical user only needs
to depend on nsi.
§Typed Attribute Names
The standard ɴsɪ attribute names are exposed as typed constants of
Attribute<T>, where T describes the data shape the attribute
accepts. Examples:
Attribute<f32> -- e.g. nsi::FIELD_OF_VIEW
Attribute<i32> -- e.g. nsi::U_COUNT, nsi::U_ORDER
Attribute<[f32]> -- e.g. nsi::U_KNOT, nsi::TRIM_CURVES_KNOT
Attribute<[Point3F32]> -- nsi::POSITION (length always divisible by 3)
Attribute<[Point4F32]> -- nsi::WEIGHTED_POSITION (rational xyzw points)
Attribute<Matrix4F64> -- nsi::MATRIXThe Rust constant identifiers are derived from the new ɴsɪ naming
convention (see the naming-convention.md chapter in the ɴsɪ spec). The
wire-side string literals each constant points to currently still hold
the legacy names ("fov", "nu", "transformationmatrix", …) so the
constants work against today’s renderers; switching to the new wire
names is a one-line change per constant when the renderer ships them.
Renderer-specific or experimental attributes are added in their own
crates without touching this one – Attribute::new("custom_name") is
const, so consumers declare their own typed constants.
Note: the parameter macros (nsi::f32!, nsi::point_slice!, …)
currently accept the wire-side string literal directly; static
verification against Attribute<T> is in progress.
§Getting Pixels
The crate has support for streaming pixels from the renderer, via callbacks
(i.e. closures) during and/or after rendering via the output module.
This module is enabled through the feature of the same name (see below).
It should be straightforward to create an async implementation with this
or use channels to stream pixels back to a main thread (see the
interactive example).
§Cargo Features
-
output– Add support for streaming pixels from the renderer to the calling context via closures. -
jupyter– Add support for rendering to Jupyter notebooks (when using a Rust Jupyter kernel). -
toolbelt– Add convenience methods that work with aContext. -
delight– Add some nodes & shaders specific to 3Delight. -
nightly– Enable some unstable features (suggested if you build with anightlytoolchain) -
ustr_handles– useustrfor node handles. This will give a you a speed boost if your node names aren’t changing while an app using ɴsɪ is running but is not advised otherwise (ustrare never freed).
§Linking Style
The 3Delight dynamic library (lib3delight) can either be linked to during
build or loaded at runtime.
By default the lib is loaded at runtime.
-
Load
lib3delighat runtime (default). This has several advantages:-
If you ship your application or library you can ship it without the library. It can still run and will print an informative error if the library cannot be loaded.
-
A user can install an updated version of the renderer and stuff will ‘just work’.
-
-
Dynamically link against
lib3delight.-
lib3delightbecomes a dependency. If it cannot be found your lib/app will not load/start. -
The feature is called
link_lib3delight. -
You should disable default features (they are not needed/used) in this case:
[dependencies] nsi = { version = "0.7", default-features = false, features = ["link_lib3delight"] }
-
-
Download
lib3delightduring build.-
lib3delightis downloaded during build. Note that this may be an outdated version. This feature mainly exists for CI purposes. -
The feature is called
download_lib3delight.
-
Modules§
- argument
- Optional arguments passed to methods of an ɴsɪ context.
- attribute
- Typed attribute / parameter names — compile-time witnesses for ɴsɪ
NSIParam_tidentifiers. - c_
adapter - C API adapter for
Nsitrait implementations. - c_api
- C API function generation for [
Nsi] trait implementations. - context
- An ɴsɪ context.
- delight
- Helpers for using ɴsɪ with 3Delight.
- dlopen2
- Library for opening and working with dynamic link libraries (also known as shared object).
- jupyter
- Jupyter Notebook support.
- lazy_
static - A macro for declaring lazily evaluated statics.
- macros
- Macros for defining NSI renderer implementations.
- node
- Standard ɴsɪ node types — re-exported from
nsi-trait. - nsi_sys
- Auto-generated Rust bindings for Illumination Research’s Nodal Scene Interface – ɴsɪ.
- output
- Output driver callbacks.
- toolbelt
- Convenience methods for an ɴsɪ context.
Macros§
- callback
- Create a
Callbackargument. - color
- Create a
Colorargument. - color_
slice - Create a
ColorSlicearray argument. - define_
nsi_ c_ api - Macro for defining the complete C API for an [
Nsi] implementation. - define_
nsi_ renderer - Generates a complete NSI renderer implementation.
- f32
- Create a
F32argument. - f64
- Create a
F64precision argument. - f32_
slice - Create a
F32Slicearray argument. - f64_
slice - Create a
F64Sliceprecision array argument. - i32
- Create a
I32argument. - i64
- Create a
I64argument. - i32_
slice - Create a
I32Slicearray argument. - i64_
slice - Create a
I64Slicearray argument. - matrix_
f32 - Create a
MatrixF32row-major, 4×4 transformation matrix argument. The matrix is given as 16 [f32] values. - matrix_
f64 - Create a
MatrixF64row-major, 4×4 transformation matrix argument. The matrix is given as 16 [f64] values. - matrix_
f32_ slice - Create a
MatrixF32Slicerow-major, 4×4 transformation matrices argument. Each matrix is given as 16 [f32] values. - matrix_
f64_ slice - Create a
MatrixF64Slicerow-major, 4×4 transformation matrices argument. Each matrix is given as 16 [f64] values. - normal
- Create a
Normalargument. - normal_
slice - Create a
NormalSlicearray argument. - point
- Create a
Pointargument. - point4_
f32_ slice - Create a slice-of-4-component-f32-points argument.
- point_
slice - Create a
PointSlicearray argument. - reference
- Create a
Referenceargument. - reference_
slice - Create a
Referencearray argument. - reference_
stable - Create a
Referenceargument from data with a stable address. - string
- Create a
Stringargument. - string_
slice - Create a
Stringarray argument. - vector
- Create a
Vectorargument. - vector_
slice - Create a
VectorSlicearray argument.
Structs§
- Accumulating
Callbacks - Helper for users who want the complete accumulated image at finish time.
- Arg
- An (optional) argument passed to a method of
Context. - Attribute
- Typed name of an ɴsɪ attribute.
- Callback
- See
ArgDatafor details. - Color
- See
ArgDatafor details. - Color
Slice - See
ArgDatafor details. - Context
- An ɴꜱɪ Context.
- Error
Callback - Wrapper to pass a
FnErrorclosure to aContext. - F32
- See
ArgDatafor details. - F64
- See
ArgDatafor details. - F32Slice
- See
ArgDatafor details. - F64Slice
- See
ArgDatafor details. - FfiApi
Adapter - Adapter that exposes an
Nsiimplementation through the C API. - FfiParam
- C-compatible parameter struct, layout-identical to
NSIParam_t. - Finish
Callback - Wrapper to pass an
FnFinishclosure to anOutputDrivernode. - Flags
- Parameter flags matching the C API constants.
- Handle
- A node handle string backed by an owned
CString. - I32
- See
ArgDatafor details. - I64
- See
ArgDatafor details. - I32Slice
- See
ArgDatafor details. - I64Slice
- See
ArgDatafor details. - Layer
- Description of an
OutputLayernode inside a flat, raw pixel. - Matrix
F32 - See
ArgDatafor details. - Matrix
F64 - See
ArgDatafor details. - Matrix
F32Slice - See
ArgDatafor details. - Matrix
F64Slice - See
ArgDatafor details. - Normal
- See
ArgDatafor details. - Normal
Slice - See
ArgDatafor details. - Open
Callback - Wrapper to pass an
FnOpenclosure to anOutputDrivernode. - Pixel
Format - Accessor for the pixel format the renderer sends in
FnOpen,FnWriteandFnFinish - Point
- See
ArgDatafor details. - Point4
F32Slice - Slice of weighted (rational) homogeneous 4-component f32 control points
— backing for
point4_f32_slice!(NURBS rational positionsPw, RGBA-style colour-with-alpha attributes, etc.). - Point
Slice - See
ArgDatafor details. - Reference
- See
ArgDatafor details. A reference to data that will be passed through FFI. - Reference
Slice - See
ArgDatafor details. - Status
Callback - Wrapper to pass a
FnStatusclosure to aContext. - String
- See
ArgDatafor details. - String
Slice - See
ArgDatafor details. - Token
- A token string backed by an interned
Ustr. - Vector
- See
ArgDatafor details. - Vector
Slice - See
ArgDatafor details. - Write
Callback - Wrapper to pass an
FnWriteclosure to anOutputDrivernode.
Enums§
- Action
- Actions for render control.
- ArgData
- A variant describing data passed to the renderer.
- Error
- An error type the callbacks return to communicate with the renderer.
- Layer
Depth - The depth (number and type of channels) a pixel in a
Layeris composed of. - Node
Type - Node types in the ɴsɪ scene graph.
- Render
Status - The status of a interactive render session.
- Scalar
Type - The scalar type of pixel channel data.
- Type
- NSI data type discriminant, binary-compatible with
NSIType_tfromnsi.h.
Constants§
- ALL
- Wildcard node that references all existing nodes at once (
.all). - ATTRIBUTES
- Container for generic attributes (e.g. visibility). Documentation.
- BUCKET_
ORDER bucket-order(currentlybucketorder) — bucket traversal pattern ("horizontal","spiral", …).- CALLBACK_
ERROR callback.error(currentlyerrorhandler) — error-handler callback registered throughNSIBegin.- CALLBACK_
STOP callback.stop(currentlystoppedcallback) — callback fired when an interactive render stops.- CURVES
- Linear, b-spline and Catmull-Rom curves. Documentation.
- CYLINDRICAL_
CAMERA - A cylindrical camera. Documentation.
- ENVIRONMENT
- Geometry type to define environment lighting. Documentation.
- FACE_
SET - Assign attributes to part of a mesh, curves or particles. Documentation.
- FIELD_
OF_ VIEW field-of-view(currentlyfov) — perspective camera FOV in degrees.- FILENAME
filename(currentlyshaderfilename) — OSL shader filename.- FISHEYE_
CAMERA - A fisheye camera. Documentation.
- GLOBAL
- Global settings node (
.global). Documentation. - INSTANCES
- Specifies instances of other nodes. Documentation.
- MATRIX
matrix(currentlytransformationmatrix) — 4×4 row-major matrix (f64).- MESH
- Polygonal mesh or subdivision surface. Documentation.
- NURBS
- NURBS surface with optional trim curves.
- ORTHOGRAPHIC_
CAMERA - An orthographic camera. Documentation.
- OUTPUT_
DRIVER - A target where to output rendered pixels. Documentation.
- OUTPUT_
LAYER - Describes one render layer to be connected to an
outputdrivernode. Documentation. - OVERSAMPLING
oversampling— pixel oversampling rate.- PARTICLES
- Collection of particles. Documentation.
- PERSPECTIVE_
CAMERA - A perspective camera. Documentation.
- PLANE
- An infinite plane. Documentation.
- POSITION
position(currentlyP) — Cartesian control points / vertices.- PROCEDURAL
- Geometry to be loaded or generated in delayed fashion. Documentation.
- RESOLUTION
resolution— pixel resolution of ascreennode,[width, height].- ROOT
- The scene’s root (
.root). Documentation. - SCREEN
- Describes how the view from a camera node will be rasterized into an
outputlayernode. Documentation. - SET
- Expresses relationships of groups of nodes. Documentation.
- SHADER
- OSL shader or layer in a shader group. Documentation.
- SPHERICAL_
CAMERA - A spherical camera. Documentation.
- STREAM_
FILENAME stream.filename(currentlystreamfilename) — output file path whenNSIBeginis invoked in stream-to-file mode.- STREAM_
FORMAT stream.format(currentlystreamformat) — output stream format forNSIBegin("nsi","binarynsi","autonsi").- STREAM_
PATH_ REPLACEMENT stream.path-replacement(currentlystreampathreplace) — substitution pairs applied to paths in the output stream.- TRANSFORM
- Transformation to place objects in the scene. Documentation.
- TRIM_
CURVES_ CURVE_ COUNT trim-curves.curve-count(currentlytrimcurves.ncurves) — curves per loop.- TRIM_
CURVES_ CV_ COUNT trim-curves.cv-count(currentlytrimcurves.n) — control-point count per trim curve.- TRIM_
CURVES_ KNOT trim-curves.knot— concatenated knots; total length = Σ(n[i] + order[i]).- TRIM_
CURVES_ LOOP_ COUNT trim-curves.loop-count(currentlytrimcurves.nloops) — number of trim loops on a NURBS surface.- TRIM_
CURVES_ MAX trim-curves.max— parametric end per trim curve.- TRIM_
CURVES_ MIN trim-curves.min— parametric start per trim curve.- TRIM_
CURVES_ ORDER trim-curves.order— order per trim curve (degree + 1).- TRIM_
CURVES_ SENSE trim-curves.sense— one per loop.0= keep inside,1= keep outside (hole).- TRIM_
CURVES_ U trim-curves.u— concatenated u control values; length = Σn[i].- TRIM_
CURVES_ V trim-curves.v— concatenated v control values; length = Σn[i].- TRIM_
CURVES_ W trim-curves.w— concatenated weights; length = Σn[i].- U_COUNT
u.count(currentlynu) — control-point count along u.- U_KNOT
u.knot(currentlyuknot) — knot vector along u; length =nu + uorder.- U_ORDER
u.order(currentlyuorder) — order along u (degree + 1, ≥ 2).- VOLUME
- A volume loaded from an OpenVDB file. Documentation.
- V_COUNT
v.count(currentlynv) — control-point count along v.- V_KNOT
v.knot(currentlyvknot) — knot vector along v; length =nv + vorder.- V_ORDER
v.order(currentlyvorder) — order along v (degree + 1, ≥ 2).- WEIGHTED_
POSITION weighted-position(currentlyPw) — rational (weighted homogeneous) control points: xyzw.
Statics§
- FERRIS
Deprecated - Legacy driver name - defaults to f32.
Deprecated: Use
FERRIS_F32,FERRIS_U16, etc. for type-specific drivers. - FERRIS_
F32 - Driver name for f32 pixel type.
- FERRIS_
I8 - Driver name for i8 pixel type.
- FERRIS_
I16 - Driver name for i16 pixel type.
- FERRIS_
I32 - Driver name for i32 pixel type.
- FERRIS_
U8 - Driver name for u8 pixel type.
- FERRIS_
U16 - Driver name for u16 pixel type.
- FERRIS_
U32 - Driver name for u32 pixel type.
Traits§
- Callback
Ptr - FfiApi
- Trait abstracting the NSI C API functions.
- FnError
- A closure which is called to inform about the errors during scene defintion or a render.
- FnFinish
- A closure which is called once per
OutputDriverinstance when rendering completes. - FnOpen
- A closure which is called once per
OutputDriverinstance. - FnStatus
- A closure which is called to inform about the status of an ongoing render.
- FnWrite
- A closure which is called for each bucket of pixels the
OutputDriverinstance sends during rendering. - Nsi
- Core ɴsɪ interface trait.
- Param
Value - A single ɴsɪ parameter (name + typed data).
- Pixel
Type - Marker trait for pixel scalar types supported by ndspy.
- Stable
Deref - Trait for types that can be safely converted to a Reference. This is implemented only for types that guarantee stable memory addresses.
Functions§
- register_
output_ drivers - Helper function to register output drivers for an API implementation.
Type Aliases§
- ArgSlice
- A slice of (optional) arguments passed to a method of
Context. - ArgVec
- A vector of (optional) arguments passed to a method of
Context. - Color3
F32 - RGB color with
f32components. - Color4
F32 - RGBA color with
f32components. - Matrix3
F32 - 3×3 matrix with
f32components. - Matrix4
F32 - 4×4 matrix with
f32components. - Matrix4
F64 - 4×4 matrix with
f64components. - Name
- Plain
Stringwhen theustrfeature is not enabled. - Normal3
F32 - 3D normal with
f32components. - Parameter
- Typed name of an ɴsɪ function-parameter — alias of
Attribute<T>. - Point2
F32 - 2D point with
f32components — typically a parametric (u, v) coordinate. - Point3
F32 - 3D point with
f32components — Cartesian position. - Point4
F32 - 4D point with
f32components — rational/weighted homogeneous (xyzw). - Vector2
F32 - 2D vector with
f32components. - Vector3
F32 - 3D vector with
f32components.