Skip to main content

Crate nsi

Crate nsi 

Source
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:

  1. Methods to create nodes, attributes and their connections. These are attached to a rendering Context.

  2. 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. Defines Nsi (self is the context), the Attribute typed-name machinery, NodeType, Action, and the standard node-type / attribute-name constants. No FFI deps.
  • nsi-ffi-wrap – FFI wrapper. Provides Context, the C-API loader (dynamic via dlopen2 or static via link_lib3delight), the parameter macros (f32!, point_slice!, …), and FfiApiAdapter which exposes any pure-Rust Nsi impl 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::MATRIX

The 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 a Context.

  • delight – Add some nodes & shaders specific to 3Delight.

  • nightly – Enable some unstable features (suggested if you build with a nightly toolchain)

  • ustr_handles – use ustr for 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 (ustr are 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 lib3deligh at runtime (default). This has several advantages:

    1. 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.

    2. A user can install an updated version of the renderer and stuff will ‘just work’.

  • Dynamically link against lib3delight.

    • lib3delight becomes 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 lib3delight during build.

    • lib3delight is 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_t identifiers.
c_adapter
C API adapter for Nsi trait 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 Callback argument.
color
Create a Color argument.
color_slice
Create a ColorSlice array 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 F32 argument.
f64
Create a F64 precision argument.
f32_slice
Create a F32Slice array argument.
f64_slice
Create a F64Slice precision array argument.
i32
Create a I32 argument.
i64
Create a I64 argument.
i32_slice
Create a I32Slice array argument.
i64_slice
Create a I64Slice array argument.
matrix_f32
Create a MatrixF32 row-major, 4×4 transformation matrix argument. The matrix is given as 16 [f32] values.
matrix_f64
Create a MatrixF64 row-major, 4×4 transformation matrix argument. The matrix is given as 16 [f64] values.
matrix_f32_slice
Create a MatrixF32Slice row-major, 4×4 transformation matrices argument. Each matrix is given as 16 [f32] values.
matrix_f64_slice
Create a MatrixF64Slice row-major, 4×4 transformation matrices argument. Each matrix is given as 16 [f64] values.
normal
Create a Normal argument.
normal_slice
Create a NormalSlice array argument.
point
Create a Point argument.
point4_f32_slice
Create a slice-of-4-component-f32-points argument.
point_slice
Create a PointSlice array argument.
reference
Create a Reference argument.
reference_slice
Create a Reference array argument.
reference_stable
Create a Reference argument from data with a stable address.
string
Create a String argument.
string_slice
Create a String array argument.
vector
Create a Vector argument.
vector_slice
Create a VectorSlice array argument.

Structs§

AccumulatingCallbacks
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 ArgData for details.
Color
See ArgData for details.
ColorSlice
See ArgData for details.
Context
An ɴꜱɪ Context.
ErrorCallback
Wrapper to pass a FnError closure to a Context.
F32
See ArgData for details.
F64
See ArgData for details.
F32Slice
See ArgData for details.
F64Slice
See ArgData for details.
FfiApiAdapter
Adapter that exposes an Nsi implementation through the C API.
FfiParam
C-compatible parameter struct, layout-identical to NSIParam_t.
FinishCallback
Wrapper to pass an FnFinish closure to an OutputDriver node.
Flags
Parameter flags matching the C API constants.
Handle
A node handle string backed by an owned CString.
I32
See ArgData for details.
I64
See ArgData for details.
I32Slice
See ArgData for details.
I64Slice
See ArgData for details.
Layer
Description of an OutputLayer node inside a flat, raw pixel.
MatrixF32
See ArgData for details.
MatrixF64
See ArgData for details.
MatrixF32Slice
See ArgData for details.
MatrixF64Slice
See ArgData for details.
Normal
See ArgData for details.
NormalSlice
See ArgData for details.
OpenCallback
Wrapper to pass an FnOpen closure to an OutputDriver node.
PixelFormat
Accessor for the pixel format the renderer sends in FnOpen, FnWrite and FnFinish
Point
See ArgData for details.
Point4F32Slice
Slice of weighted (rational) homogeneous 4-component f32 control points — backing for point4_f32_slice! (NURBS rational positions Pw, RGBA-style colour-with-alpha attributes, etc.).
PointSlice
See ArgData for details.
Reference
See ArgData for details. A reference to data that will be passed through FFI.
ReferenceSlice
See ArgData for details.
StatusCallback
Wrapper to pass a FnStatus closure to a Context.
String
See ArgData for details.
StringSlice
See ArgData for details.
Token
A token string backed by an interned Ustr.
Vector
See ArgData for details.
VectorSlice
See ArgData for details.
WriteCallback
Wrapper to pass an FnWrite closure to an OutputDriver node.

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.
LayerDepth
The depth (number and type of channels) a pixel in a Layer is composed of.
NodeType
Node types in the ɴsɪ scene graph.
RenderStatus
The status of a interactive render session.
ScalarType
The scalar type of pixel channel data.
Type
NSI data type discriminant, binary-compatible with NSIType_t from nsi.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 (currently bucketorder) — bucket traversal pattern ("horizontal", "spiral", …).
CALLBACK_ERROR
callback.error (currently errorhandler) — error-handler callback registered through NSIBegin.
CALLBACK_STOP
callback.stop (currently stoppedcallback) — 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 (currently fov) — perspective camera FOV in degrees.
FILENAME
filename (currently shaderfilename) — OSL shader filename.
FISHEYE_CAMERA
A fisheye camera. Documentation.
GLOBAL
Global settings node (.global). Documentation.
INSTANCES
Specifies instances of other nodes. Documentation.
MATRIX
matrix (currently transformationmatrix) — 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 outputdriver node. Documentation.
OVERSAMPLING
oversampling — pixel oversampling rate.
PARTICLES
Collection of particles. Documentation.
PERSPECTIVE_CAMERA
A perspective camera. Documentation.
PLANE
An infinite plane. Documentation.
POSITION
position (currently P) — Cartesian control points / vertices.
PROCEDURAL
Geometry to be loaded or generated in delayed fashion. Documentation.
RESOLUTION
resolution — pixel resolution of a screen node, [width, height].
ROOT
The scene’s root (.root). Documentation.
SCREEN
Describes how the view from a camera node will be rasterized into an outputlayer node. 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 (currently streamfilename) — output file path when NSIBegin is invoked in stream-to-file mode.
STREAM_FORMAT
stream.format (currently streamformat) — output stream format for NSIBegin ("nsi", "binarynsi", "autonsi").
STREAM_PATH_REPLACEMENT
stream.path-replacement (currently streampathreplace) — 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 (currently trimcurves.ncurves) — curves per loop.
TRIM_CURVES_CV_COUNT
trim-curves.cv-count (currently trimcurves.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 (currently trimcurves.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 (currently nu) — control-point count along u.
U_KNOT
u.knot (currently uknot) — knot vector along u; length = nu + uorder.
U_ORDER
u.order (currently uorder) — order along u (degree + 1, ≥ 2).
VOLUME
A volume loaded from an OpenVDB file. Documentation.
V_COUNT
v.count (currently nv) — control-point count along v.
V_KNOT
v.knot (currently vknot) — knot vector along v; length = nv + vorder.
V_ORDER
v.order (currently vorder) — order along v (degree + 1, ≥ 2).
WEIGHTED_POSITION
weighted-position (currently Pw) — rational (weighted homogeneous) control points: xyzw.

Statics§

FERRISDeprecated
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§

CallbackPtr
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 OutputDriver instance when rendering completes.
FnOpen
A closure which is called once per OutputDriver instance.
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 OutputDriver instance sends during rendering.
Nsi
Core ɴsɪ interface trait.
ParamValue
A single ɴsɪ parameter (name + typed data).
PixelType
Marker trait for pixel scalar types supported by ndspy.
StableDeref
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.
Color3F32
RGB color with f32 components.
Color4F32
RGBA color with f32 components.
Matrix3F32
3×3 matrix with f32 components.
Matrix4F32
4×4 matrix with f32 components.
Matrix4F64
4×4 matrix with f64 components.
Name
Plain String when the ustr feature is not enabled.
Normal3F32
3D normal with f32 components.
Parameter
Typed name of an ɴsɪ function-parameter — alias of Attribute<T>.
Point2F32
2D point with f32 components — typically a parametric (u, v) coordinate.
Point3F32
3D point with f32 components — Cartesian position.
Point4F32
4D point with f32 components — rational/weighted homogeneous (xyzw).
Vector2F32
2D vector with f32 components.
Vector3F32
3D vector with f32 components.