**Bella Core** [Bella for Rhino](../bella_rhino/index.html) | [Bella for Maya](../bella_maya/index.html) | [Bella for SketchUp](../bella_sketchup/index.html) | [Bella GUI](../bella_gui/index.html) | [Bella CLI](../bella_cli/index.html) | [Bella Core](../bella/index.html) | [Tutorials](../../tutorials) | [Node Definitions](../nodes/index.html) | [Main site](https://bellarender.com) | [Discord](https://discord.gg/AaQtpWt5aT) Introduction =================================================================================================== Bella uses a node-based scene model, which is very generic and flexible, to allow interoperation with a wide range of third-party applications. Its Scene SDK is written in c++, and provides safe, simple, and error-resistant usage by means of a ref-counted hidden-implementation design. ## Scope This document discusses core concepts and functionalities of Bella at a fairly technical level. It will be useful if you wish to understand how Bella scenes are constructed, how various core Bella nodes are defined, and why. System Requirements =================================================================================================== Bella supports running on 64-bit machines and operating systems only. It is recommended to have at least 8GB of memory, but generally preferable to have 16GB or more. Bella itself is quite compact, but using it may involve large files, so you should have plenty of disk space (preferably SSD) available. Note that we do not officially support running in virtual machines, or other such emulated environments. For example, we do not support running under Parallels, VMware, VirtualBox, Wine, or similar. Bella may work in these environments, and you may use the freely-available Bella demo to check this, but we do not test on them, and therefore do not officially support them. ## Windows - OS: Windows 10 or greater, 64-bit - CPU: Intel Sandy Bridge or greater - Bella may work on earlier OS versions, but we do not test on these !!! NOTE: if you encounter any error when attempting to use Bella, see the section at the end of the [downloads](https://bellarender.com/downloads) page, instructing how to install the Microsoft Visual C++ runtime. ## MacOS - OS: MacOS Monterey (minimum target is Catalina, but we do not test this) - CPU: Intel Sandy Bridge or greater, or Apple Silicon - Machine: a genuine Apple computer (i.e. not a Hackintosh) - Bella may work on earlier OS versions, or a Hackintosh, but we do not test on these ## Linux - OS: Ubuntu 16.04 LTS 64-bit - CPU: Intel Sandy Bridge or greater - Contact us if you require a different distribution for your production Concepts =================================================================================================== ## Node A node is a data structure which is defined at runtime, to contain a collection of input and output attributes. In the following diagram, we consider inputs to be on the left, and outputs to to be on the right, and we adopt the convention that output names always begin with the string "out".  A node may be just a container for data, in which case it has no outputs, or it may be a "black box" for computing output values, based on the values of its inputs. In the latter case there is expected to be code associated with the node, to perform the computation; this may be code contained in the Bella engine itself, for internal Bella nodes, or in a shared library, for third-party nodes. The node itself also has some inherent properties which are neither inputs nor outputs, the foremost being a permanent name (a string). A node's name will never change, and will persist through file IO. To facilitate user-friendly usage of the node, it is possible to set its displayName, which itself is implemented internally using a "name" input (which is therefore common to all nodes). Nodes are defined using a .bnd file, which is a json file that is parsed at runtime, to create node types, and endow them with their inputs and outputs. It is also possible to entirely define a node type at runtime, using c++ (or any supported interop language). Nodes in Bella are allowed to inherit the attributes of multiple other nodes. ## Attribute An attribute represents a named value of a given type, and may be either an input or an output attribute. The supported attribute types are as follows: type | Description ---------------------|-------------------------- Bool | Boolean. Int | Signed 64-bit integer. UInt | Unsigned 64-bit integer. Real | Double-precision float. Vec2 | 2-component real vector Vec3 | 3-component real vector Vec4 | 4-component real vector Pos2 | 2-component real position vector (i.e. point). Pos3 | 3-component real position vector (i.e. point) Quat | Quaternion (4 reals). Rgba | RGBA vector (4 reals, range 0-1). Mat3 | 3x3 matrix (9 reals). Mat4 | 4x4 matrix (16 reals). String | Null-terminated UTF-8 string. Node | Reference to a node. Input only. Buffer | Buffer of primitive values. Array | Array of input attributes. Input only. Object | Container of child input attributes. Input only. [Attribute types.] Input attributes have an immediate value -- that is to say, if you are working with a Vec3 input, and you set it to (1,2,3), this value is stored in the attribute, and may be read back out at a later time. Output attributes have no such immediate value, and can only return values computed by the node from its inputs. As mentioned above, it is possible to add inputs to a node at runtime -- it is also possible to remove them, but care should be taken in doing so, since code may exist which depends on the names and types of inputs for known nodes. ## Connection Such a system would be of limited usefulness if it were only possible to set input values, and compute output values -- what we are after is the ability to drive input values with computed output values, which themselves are used to drive other inputs, and so forth. This is accomplished by allowing connections between inputs and outputs:  This raises the question of how to know when to read an input's immediate value, and when to follow its connection (if connected) to get the value of a connected output. And the answer is: it depends. If you are (for example) writing a UI element that allows showing an input's immediate value while it is connected, then you would obviously need to query it for its immediate value. But if you are writing the internal implementation of a node, then it is almost always the case that you would want to follow, or evaluate, the connection. ## Evaluation Attributes, both input and output, provide a full set of both *is* and *as* methods -- isInt()/asInt() and so forth, for the above-listed attribute types -- which work according to their type. Calling asInt() on an output necessarily calls code in the output's node, which may in turn cause inputs of that node to be evaluated, in a chain of evaluation. The system ensures that cycles cannot be created, and that consequently, the evaluation will halt at some point. For an input, however, the corresponding *as* methods take an optional bool *eval* argument, to allow either retrieving the input's immediate value, or evaluating the output to which it is connected, if connected. ## The xform Node One fundamental node type in the system is the transform, or xform node. The xform node is defined to have an array of children, which is an attribute of type node[], and which accepts nodes deriving from xform itself, from camera, or from the abstract node, geometry. It also has an array of (4x4 matrix) transforms, each associated with a particular time value. Together with input/output connections, xform therefore describes a DAG structure, and in Bella, this structure has its root in the so-called *world* xform, which is the singular xform to which all other xforms and geometry in the visible scene are ultimately parented:  Other xforms or geometry may exist in the scene, which are not ultimately parented to the world xform, but these will not be part of the visual, rendered scene. Through the ability to parent one xform to another, it is made possible to create as many instances of a particular piece of geometry as desired, or even of entire sub-hierarchies of xforms and geometry. As such, another key related concept is that of a *path*, which describes a particular route from the world xform, through its children, to a particular instance. The need for such a concept is implied by the fact that no piece of geometry necessarily has a single parent, and may indeed be parented to an arbitrary number of xforms, whether directly or indirectly. ## Smart Nodes The smart node is an abstract base node type, inherited by other nodes, to indicate that they present one (generally simplified) set of inputs, and output the name of a node (which is generally more complicated) that they have built using those inputs. They are called to do this prior to rendering, or at other times (e.g. when building a user interface), with the engine then finding and using the generated node in their place. Scene =================================================================================================== A Bella scene consists of a list of nodes, arranged and connected in a particular way; at minimum it must have a certain configuration of global, state, settings, and world xform nodes. ## Node List The node list is a simple, flat list of all of the nodes currently contained in the scene. Any nodes in the list may have input/output connections between them. Nodes in the list are not allowed to have duplicate names, so when creating new nodes, the requested name may be altered by the scene, by appending a numeric suffix. For programmers, note that it can be expensive to search names in some export scenarios, and that you may improve export performance by ensuring that names are already unique when you request the scene to create a node. ## Global The global node serves as the root of a Bella scene. It contains a list of state nodes, one of which is current at any given time. It is not supported to "switch" the global node, and indeed, it exists mainly to avoid hard-coding similar functionality into the Bella scene code. In general, a user will rarely have reason to interact with the global node, since switching state may involve much rebuilding of (likely custom) GUI structure. ## State The state node holds references to a settings node, and a world xform. Its purpose is to allow a Bella scene to contain multiple sets of settings/world pairs. Though there is not yet any use of this functionality, it may be exposed in the future, for example, by the Bella CLI allowing to select from among multiple states, for rendering. !!! as of the time of this writing, the Bella GUI is not yet prepared to deal with switching states. ## Settings A settings node holds references to a camera, environment, beautyPass, default & override materials, and other attributes (base output path, and so forth) which define how the scene is rendered. !!! As of the time of this writing, the Bella GUI is not yet prepared to deal with switching settings. ## World (xform) The world xform is a particular xform, which as described above, has been designated as the root of the visual scene by being referenced by the current state node. Bella contains functions neither for setting global scene scale, nor axis (left-handed YXZ, right- handed YZX, etc) configuration -- these are both encoded in the world xform, which is therefore expected to be an axis-aligned orthogonal matrix, by which all children will be transformed for rendering. !!! As of the time of this writing, the Bella GUI is not yet prepared to deal with switching the world xform. ## Environment An environment is a node optionally linked in the current settings node, which produces a dome of color with gradient from horizon to zenith (colorDome node), an image dome that uses an HDRI for lighting (imageDome node), or a sky dome to simulate a physical sky & sun (skyDome node). It is also supported to render with no environment, though you will encounter an error if there are also no other light sources found in the scene. ## Render Pass Output images in Bella are created using a render pass node, of which there are several types: Pass | Notes ---------------------|-------------------------- Albedo | The albedo (diffuse reflectance) of the first impacted material. Alpha | The opacity of the first impacted object. Beauty | The traditional production "beauty" output. Material | The material ID color of the first impacted material. Normal | The normalized surface normal per pixel, in world coords. Object | The color ID of the first impacted object. Shadow | The shadows for objects with "Capture Shadows" render flag enabled. Tangent | The normalized surface x-axis tangent per pixel, in world coords. Z | The projected-to-film distance from the first impact to the camera position, normalized to the specified range. [Render passes.] Each pass type uses a particular solver to produce its output image, and multiple passes may be rendered by adding them to settings:extraPasses. Usually, there is a beautyPass referenced at settings:beautyPass, and it is rendered before extra passes. However, you may opt to render extra passes first, by also adding your beautyPass to the extra passes (you do not need to remove it from settings:beautyPass). It is also supported to render with no beautyPass at all (except in IPR) if desired. Materials =================================================================================================== The Bella material system is based on rendering materials composed of an optional substrate (conductor, dielectric, orenNayar, subsurface), along with a layer, which essentially simulates a very thin layer of dielectric material. With optional thin film and scattering nodes, a cross-section of the model looks like this:  All Bella materials share a common set of basic attributes: | ---------------------|-------------------------- Opacity | A global opacity applied to the material as a whole. Normal | A bump or normal map (OpenGL format) applied to the material as a whole. Priority | Decides which geometry takes precedence, when dielectric volumes are nested. Material ID | The color used for objects assigned this material, in the materialPass. [Common material attributes.] Normal maps in Bella use OpenGL format, but you can easily use other formats by using the Flip R/G attributes on the Normal Map (or PBR material) node. ## Substrate The Bella substrate nodes are these: | ---------------------|-------------------------- Conductor | Represents an opaque surface, with reflectance color. Dielectric | Represents a refractive surface, with transmittance, IOR, dispersion. Oren-Nayar | A diffuse substrate which implements the Oren-Nayar reflectance model. Subsurface | A substrate which implements random walk subsurface scattering. [Substrate materials.] In addition to these type-specific attributes, all of the substrates also share a common set of surface-related attributes: | ---------------------|-------------------------- Thin Film | An optional thin film node to be applied over the substrate. Roughness | The micro-geometrical roughness of the surface. Anisotropy | Determines to what degree roughness is biased in one direction (produces a brushed look). Rotation | Rotates the tangent frame (essentially, rotates anisotropy effect). [Surface attributes.] ## Layer Over a Bella substrate, we may optionally apply a layer, which simulates a thin dielectric layer. Like the dielectric, a layer also has the common surface-related attributes, as well as the dielectric medium-related ones (IOR, transmittance). Additionally, the layer supports referencing a scattering node, to control scattering of light within the layer medium (as shown in the diagram). ## Thin Film A thin film represents a very thin (nanometer scale) film over a substrate or layer surface, by which thin-film interference effects are simulated. As depicted in the diagram above, the thin film follows the micro-geometrical form (i.e. roughness) of the surface to which it is applied. ## Scattering Currently supported in the layer, the scattering node is used to simulate scattering of light within the layer medium. ## Sheet The sheet material is essentially a layer used on its own as a material, with no substrate at all. It is therefore useful for simulating thin surfaces like paper or leaves, or for obtaining a glass- like appearance from window panes that have no volume. As it inherits both the material and layer nodes, it may be used anywhere that either of those types may be used. ## Emitter The Bella emitter material is used to emit light from arbitrary geometry. It allows setting output power using one of several different units, for convenience in matching real-world light sources. It also supports some advanced rendering-related features: | ---------------------|-------------------------- Caustics | Connect an optional filterCaustics node, to control caustics for this emitter. Radius | Connect an optional rampInOut node, to define the distances (from geometry) at which light begins and ends for this emitter. Diffuse | Reduce the contribution of this emitter to diffuse reflections. Specular | Reduce the contribution of this emitter to specular reflections. [Emitter features.] ## Complex (IOR) Bella supports using complex IOR data through the complexIor node, which may be attached to the reflectance color of a conductor, or the transmittance color of a dielectric. This node provides a built-in selection of common material types, as well as the ability to reference an external file, or to assign data directly in the node (as may be obtained [here](https://refractiveindex.info)). File Formats =================================================================================================== Bella uses several file formats, to hold Bella scenes, rendering data, and node defintions. ## BSA BSA stands for Bella Scene ASCII, the text-based Bella scene file format. Technically it is UTF-8, not strictly ASCII. ## BSX BSX does not stand for anything specific; it is generally a binary-format Bella scene, but it is also allowed to hold a text-based scene. We generally refer to any scene file as "BSX" in common conversation, whether it is actually BSA, BSX, or BSZ. ## BSZ BSZ stands for Bella Scene Zip, and is a zip archive containing a BSX file, along with all of the external file resources it references. Anywhere you can open a BSA or BSX file, you can also open a BSZ file, as the scene's read function will handle unzipping it. When it does so, it will write (or overwrite, so be careful, and warn users if necessary) the zipped BSX file, as well as the BSZ file's res directory, next to the BSZ. ## BSI BSI stands for Bella Spectral Image, and it is our internal format for holding rendered data. It is currently used to support resume render. ## BND BND stands for Bella Node Definition, and it is our json-format file for defining Bella nodes. It is read at runtime by the Bella scene, which then provides access to all of its definitions (nodes like any other, except stored in a special list, and used as prototypes for creating nodes in the scene) through the scene's definitions list.