MoonRay Scene Formats
MoonRay’s native scene description format is called RDL2. There are two primary file formats for RDL2:
- RDLA is a readable text format based on the programming language Lua
- RDLB is a binary format
You can use the program rdl2_convert to translate between the two formats, for example:
rdl2_convert -in scene_binary.rdlb -out scene_text.rdla
You can also read and write both formats from code using the scene_rdl2 library.
RDLA Format
An RDLA file is actually a Lua script, with some extensions to support RDL2 scene objects. It is intended primarily for authoring test data : you can use Lua features like functions and loops to automate and simplify the creation of test scenes. RDLA is less appropriate for large production scenes, since RDLB is much more efficient and compact in this situation.
Objects, classes and attributes
An RDL2 scene is just a set of scene objects : each object having a name, class and attributes. In RDLA, an object is defined like this:
DwaSolidDielectricMaterial("/scene/sphere/mtl/yellow") {
["refractive_index"] = 1.5,
["albedo"] = Rgb(0.8, 0.8, 0.2)
}
DwaSolidDielectricMaterial
is the class of the object- “/scene/sphere/mtl/yellow” is the object name
- refractive_index and albedo are attributes supported by the
DwaSolidDielectricMaterial
class
In most cases, classes are implemented as shared library plugins. MoonRay searches for plugins on a path defined by the environment variable RDL2_DSO_PATH
. In this case, assuming RDL2_DSO_PATH
is set correctly, MoonRay will find the library DwaSolidDielectricMaterial.so somewhere on the path.
DwaSolidDielectricMaterial
has about 90 attributes in total. Attributes that you don’t explicitly set take a default value defined by the class.
You can see the attributes of a class using the rdl2_print command:
$ rdl2_print -c DwaSolidDielectricMaterial
DwaSolidDielectricMaterial("DwaBaseLayerable") {
["albedo"] = Rgb(1, 1, 1), -- Rgb, bindable
-- comment: the overall surface color as seen from a distance (ie. diffuse color)
["anisotropy"] = 0, -- Float, bindable
-- comment: controls the shape of the primary reflection
["bssrdf"] = 0, -- Int, enumerable (normalized diffusion)
-- 0 = normalized diffusion
-- 1 = dipole
-- 2 = random walk
-- comment: 0 for NormalizedDiffuse, 1 for Dipole, 2 for random walk
["casts_caustics"] = false, -- Bool
-- comment: allows continuation of caustic light paths.
-- label: casts caustics
...
Compound values
Compound values like Rgb
are created using a construction function, as shown in the example. Some other examples of compound types are Rgba
, Vec2
, Vec3
and Mat4
.
There are some additional functions to construct transform matrices:
translate(x, y, z)
rotate(degrees, axis_x, axis_y, axis_z)
scale(x, y, z)
All of the compound types have arithmetic operators defined. This is especially useful when setting transformation attributes:
SphereGeometry("/scene/sphere") {
["node xform"] = translate(4, 5, 6)*rotate(45, 0, 0, 1)*scale(2, 2, 2)
}
A few MoonRay attributes expect a list of values. These are set using curly braces, like this:
RampMap("/scene/ramp") {
["colors"] = {Rgb(0.1, 0.2, 0.3), Rgb(0.4, 0.5, 0.6), Rgb(0.7, 0.8, 0.9)}
}
Sets and object references
Some built-in classes are used to define a set of objects : GeometrySet
and LightSet
are examples. Sets are defined using curly braces, like lists, but the members are references to other objects.
A simple way to reference an existing object is ClassName("name")
– using the actual class of the object instead of “ClassName”, of course. This is exactly the same as the expression used to create an object : for any RDL2 class, ClassName
is a Lua function that creates an object with the given name if it doesn’t already exist, and returns the existing object if it does.
AreaSpotLight("/scene/key") {
...
}
AreaSpotLight("/scene/fill") {
...
}
LightSet("/scene/lights") {
AreaSpotLight("/scene/key"),
AreaSpotLight("/scene/fill")
}
You can also use Lua variables to hold objects:
key = AreaSpotLight("/scene/key") {
...
}
fill = AreaSpotLight("/scene/fill") {
...
}
-- Sets the LightSet to contain key and fill.
lights = LightSet("/scene/lights") {
key,
fill
}
Comment lines in Lua begin with two dashes (--
)
Layers
A layer contains a set of assignments to geometry objects or parts.
The most general form of a layer entry specifies a geometry object, part name, material, light set, displacement and volume shader. However, you can leave out items from the end of this list, and it is common to just set geometry, material and light set. In RDLA, a layer looks like this:
sphere1 = SphereGeometry("/scene/sphere1")
sphere2 = SphereGeometry("/scene/sphere2")
sphere1_mat = DwaBaseMaterial("/scene/sphere1/mat")
sphere2_mat = DwaBaseMaterial("/scene/sphere2/mat")
lights = LightSet("/scene/lights")
layer = Layer("/scene/layer") {
{sphere1, "", sphere1_mat, lights},
{sphere2, "", sphere2_mat, lights}
}
In this example, the “part name” component of the layer assignments is set to an empty string (""
), making the assignment affect the entire object. The set of part names available for partial object assignment depends on the geometry class being used.
Bindings
Some attributes can accept a map binding as well as a value. Maps are 2 or 3 dimensional patterns that are evaluated for each sample. Bindings are created using the bind
function:
DwaBaseMaterial("/scene/sphere/base") {
["albedo"] = bind(CheckerboardMap("/seq/shot/checkermap"), Rgb(0.8, 0.8, 0.2))
}
The CheckerboardMap
will be evaluated per sample during shading, and the resulting color value multiplied by the base value Rgb(0.8,0.8,0.2)
to obtain the value for albedo.
Each class implementation can decide how to combine the evaluated map value and the attribute’s base value : it is not required that the class multiply one by the other, although that is usually the case.
Motion Blur
Motion blur requires two attribute values to be set : one for the start time and one for the end. In RDLA the blur
function is used:
Camera("/Scene/rendering/camera") {
["node xform"] = blur(
translate(-1.0, 0.3, 12) * rotate(-30, 1, 0, 0) * rotate(0, 0, 0, 1),
translate(0.0, 0.3, 12) * rotate(-30, 1, 0, 0) * rotate(0, 0, 0, 1)),
}
Scene Variables
The scene variables object contains overall settings for the render. It can be accessed through the global variable SceneVariables
. This is how to set scene variables in an RDLA file:
SceneVariables {
["image width"] = 1920
["image height"] = 1080
}
There are just over 100 different scene variables in total. You can list them all using the rdl2_print command:
SceneVariables("SceneObject") {
$ rdl2_print -c SceneVariables
["aperture_window"] = IntVector(-2147483648, -2147483648, -2147483648, -2147483648), -- IntVector
-- comment: Window of the camera aperture. Overrides image width / height. Order: xmin ymin xmax ymax, with origin at left bottom.
-- label: aperture window
["athena_debug"] = false, -- Bool
-- label: athena debug
["batch_tile_order"] = 4, -- Int, enumerable (morton)
-- 0 = top
-- 1 = bottom
-- 2 = left
-- 3 = right
-- 4 = morton
...
Scene Structure
RDL2 has no scene hierarchy : each scene object is independent and transforms are always defined in world space. By convention we often use /-separated paths as object names, creating an implicit structure, but this has no effect on MoonRay’s interpretation of the data.
To be renderable, a scene must contain a layer, camera and geometry set. MoonRay will use the first of each that it finds in the scene. The camera and layer to render with can also be specified using scene variables.
To light anything, lights need to be added to a light set and assigned to geometry in the layer.
RDLB Format
RDLB files encode the scene objects in an optimized binary format. RDLB is faster to load and more compact than RDLA.