Skip to content

Procedural Assemblies Design Document

François Beaune edited this page Mar 1, 2014 · 16 revisions

A highly anticipated feature of appleseed is the support for procedurally generated geometry and on-the-fly, on-demand generation of scene data. appleseed was designed from the ground up to support this workflow via the concept of assemblies.

This is a DRAFT for the design of procedural assemblies. Comments and feedback are welcome.

Design

A procedural assembly is an assembly with a program bound to it.

The program attached to an assembly is executed as soon as the renderer requires to know what this assembly contains, typically when a ray hit the assembly.

There are two kinds of programs:

  1. Those that populate the assembly or alter its contents.
  2. Those that manufacture ray-assembly intersection points.

The program bound to the assembly is typically written in C++ and packaged as a shared library (a DLL on Windows).

Here is how a program could be bound to an assembly:

<assembly name="myAssembly">
    <parameter name="program" value="path/to/procedural" />
</assembly>

path/to/procedural is the path to a shared library (extension .so on Linux, .dylib on OS X and .dll on Windows). The extension is omitted for the sake of portability of project files across platforms.

A procedural assembly has an initial bounding box.

The bounding box is defined as an assembly parameter:

<assembly name="myAssembly">
    <parameter name="program" value="path/to/procedural" />
    <parameter name="bounding_box" value="-1.0 -3.0 1.0 3.0" />
</assembly>

If no bounding box is specified, it is assumed to be infinite (the assembly is assumed to cover the entire space). This implies that the program of this assembly will be executed as soon as rendering starts.

A procedural assembly can have arbitrarily many user parameters.

Just like any appleseed entity:

<assembly name="myAssembly">
    <parameter name="program" value="path/to/procedural" />
    <parameter name="bounding_box" value="-1.0 -3.0 1.0 3.0" />
    <parameter name="color_variation" value="0.7" />
</assembly>

The program has full access to the parameters set on the assembly.

A procedural assembly need not be initially empty.

This is a valid procedural assembly:

<assembly name="myAssembly">
    <parameter name="program" value="path/to/procedural" />
    <parameter name="bounding_box" value="-1.0 -3.0 1.0 3.0" />
    <object name="myObject" model="mesh_object">
        <parameter name="filename" value="myObject.abc" />
    </object>
    <!-- Many more entities such as object instances, BSDFs, etc. -->
</assembly>

A procedural assembly may contain light emitters.

In that case, it must be marked as such so that the renderer can collect its light emitters before rendering starts:

<assembly name="myAssembly">
    <parameter name="program" value="path/to/procedural" />
    <parameter name="bounding_box" value="-1.0 -3.0 1.0 3.0" />
    <parameter name="has_light_emitters" value="true" />
</assembly>

If the renderer finds light emitters in an assembly that was not marked as such, it will emit a warning message.

The program of a procedural assembly can update the bounding box initially defined in the project file.

Imagine an Alembic procedural:

<assembly name="myAssembly">
    <parameter name="program" value="path/to/alembicProcedural" />
    <parameter name="bounding_box" value="-1.0 -3.0 1.0 3.0" />
    <parameter name="filepath" value="/path/to/animatedOctopus.abc" />
    <parameter name="frame" value="27" />
</assembly>

There is no way to know the actual bounding box of the assembly in advance. The program has an entry point to update the bounding box initially set in the assembly with the actual bounds.

API of a procedural assembly shared library

To be defined.

Clone this wiki locally