BSDF and Surfaceshader Scene Objects

Open
#318 0 comments 0 reactions 1 assignee View on GitHub

@dmccann-dwa is already working on this.

Since Oct 2, 2026.

Assessment

This issue has not been assessed yet.

Description

Scope

We're implementing Mtlx_Surface with arbitrarily mixable and layerable BSDF components. It can be mixed with other Surfaceshaders, like Mtlx_Standard_Surface_Surfaceshader. These are usable in C++ and ISPC.

Upon scene creation, the assigned shader will walk its input graph to discover the Surfaceshader's lobes and ordering. It then creates a mapping from BSDF nodes to a data buffer. BSDFs using the same shading model are combined wherever possible, and their respective inputs blended accordingly.

During shading, this buffer will be populated by input data, then interpreted as BSDF components (see moonray/lib/rendering/shading/BsdfComponent.h) and sent to the BsdfBuilder for evaluation.

Development Branches

Branches are currently internal. Link coming soon!

Limitations

Core Moonray requires the following material models to be implemented to meet MaterialX specification:

  • Fuzz and Zeltner Fuzz
  • Burley Diffuse

A full implementation of the Add operator will require core Moonray changes. We currently only support adding individual lobes, as opposed to adding a physically-layered set of lobes.

Current Progress & Priority

Implemented several BSDF components, Mix, Layer, Multiply operators. Standard Surface, MixSurfaceshader.

The highest priority is testing and profiling. We need to understand the overhead of the API as it wraps MoonRay's existing BSDFBuilder. The first proposed test is to compare the following:

  • A graph of BSDFs and operators that constitutes the Autodesk Standard Material
  • The same material implemented as a single shader with direct calls to BSDFBuilder

API and algorithm design

BSDFs, or partial materials, are a new notion for MoonRay. As new scenegraph objects, the first definition is in Scene_RDL2. Surfaceshaders, as assignable materials, are simply defined in the Materialx_shaders repository to extend the material scenegraph object.

This section explains the basic API, and the utility objects to handle dynamic shading data.

All BSDF classes are responsible for implementing the following:

public:
    // save the type of this BSDF (or this shader's child BSDFs) and its path to the slab manager
    bool registerSlab(MtlxTreeTraversal& treeTraversal,
                      MtlxSlabManager& slabManager) const override;

private:
    // evaluate input data for shading
    static void resolveParameters(
        const MtlxBsdf* self,
        const moonray::shading::MtlxSlabManager& slabManager,
              moonray::shading::MtlxTreeTraversal& treeTraversal,
              moonray::shading::TLState *tls,
        const moonray::shading::State& state,
        const float weight,
        const Color& tint,
              moonray::shading::MtlxSlabShadingData& out);

Surfaceshaders must also implement analogous functions. In their material::shade() function, they instantiate all of the utility objects and begin traversing the BSDF tree.

Utility Objects: MtlxSlabShadingData & Others

MtlxSlabManager is the core of the dynamic shading API. The assignable material is conceptualized as a composite of horizontally-blended (mixed) or vertically-blended (layered) slabs. During scene creation, a MtlxSlabManager is instantiated in a surfaceshader then passed to child BSDF objects through registerSlab(), which builds a surjective mapping of BSDF shaders to slabs. This mapping is surjective in order to blend parameters of matching lobes, to minimize the number of lobes the path tracer must evaluate.

This mapping is made and accessed using the shading graph path from the MtlxSlabManager's owner and the respective BSDF, encoded by the MtlxTreeTraversal class.

During shading, this mapping is used to write into and read from MtlxSlabShadingData. This is a simple container of serialized data, made to be compatible with ISPC. When a shader writer implements resolveParameters(), it ends with the following pattern:

const BRDF myBRDF = ... // pack evaluated data into moonray/lib/rendering/shading/BsdfComponent.h struct
slabManager.addSample(myBrdf, weight, tint, treeTraversal.getPath(), out);

The MtlxSlabManager will then weight and tint the appropriate data as it is serialized. As the parent surfaceshader finishes querying all of the BSDF components it owns, MtlxSlabmanager will deserialize the data into components for MoonRay's BsdfBuilder (moonray/lib/rendering/shading/BsdfBuilder.h) in order of energy conservation (top layer slabs --> substrate layer slabs.)

Dominant language
CMake
Stars
4.7k
Forks
321
Avg merge
13m
Merged PRs (30d)
3

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from OpenMoonRay/openmoonray

All issues in OpenMoonRay/openmoonray

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.