Metashaders

Metashaders

What Is A Metashader?

A metashader just an .args file with its own, unique name. It is not a shader. In other words, it is not a .cpp file that compiles to a .so file. In its .args file it references an existing RIS shader (e.g. PxrSeExpr) and provides customized user interface and defaults for the desired functionality.

A metashader can be created for any type of shader plugin. When a metashader is loaded it appears like a regular shader plugin. Users won't able to tell the difference between a metashader and a real shader, but, in the RIB file, the PRMan plugin injects the shader plugin name that the metashader referenced, not the name of the metashader.

When To Create A Metashader

Unlike a preset, which stores a set of shader defaults, a metashader allows us to customize the user interface plus more! While writing C++ plugin RIS shaders for PRMan is powerful, it can be time-consuming to add endless variations of utility shaders. The PxrSeExpr pattern shader is able to fill the role of many of these shaders, but it requires users to type in technical expressions with non-intuitive syntax in order to make it work. This process vsn be time consuming. Metashaders provide a way around this problem.

Metashaders serve two fundamental purposes:

  1. They allow technical directors to write a pattern metashader using PxrSeExpr expressions (or PxrOSL) and present them like regular shaders to the users. Users do not need to know the implementation details.

  2. They can provide a customized shader user interface for an existing plugin. Shader widgets, defaults, min, max, and labels can all be tailored to a production's needs. (See the ArgFiles documentation for more information.)

    Also, any shader parameters that are not specified in the metashader will be hidden from the user interface. This makes it easy to simplify a shader interface that has a lot of parameters.

  • Important

    Metashaders are convenient, but if a metashader becomes more computational than simple pattern generation it may be better to convert the metashader to a plugin. Otherwise, it can slow down the rendering process.

    Additionally, if you only need to create a set of defaults without needing to customize the shader user interface or sharing PxSeExpr expressions, creating a preset is a simpler approach.

How To Install Metashaders

RenderMan for Maya

The location of the metashaders must be specified in your RenderMan_for_Maya.ini file via RISArgsSearchPath. For example, let's say your metashader .args files are in /home/smith/mypatterns/Args, then your RISArgsSearchPath should be amended like so:

set RISArgsSearchPath [list \
                         [file join $rmantree lib RIS pattern Args] \
                         [file join $rmantree lib RIS bxdf Args] \
                         [file join $cfg ris customNodes] \
                         [file join $cfg ris mayaNodes] \
                         {/home/smith/mypatterns/Args}
                      ]
  • Important

    We highly recommend that, rather than editing the RenderMan_for_Maya.ini file in your installation directory ($RMSTREE/etc), users should create a duplicate file containing your site-specific overrides and place it in a separate directory, which must then be referenced via the $RMS_SCRIPT_PATHS environment variable.

RenderMan for Katana

For RenderMan for Katana, metashaders are loaded just like an actual RIS plugin and need to be included in the shader manifest file. The shader manifest file resides in the same directory as the actual shaders. The .args files also reside in the same directory as the actual shaders' .args files.

Here is an example of a shader manifest file to load your metashaders:

  1. In a directory that is in the shader search path, make a new file called shaderManifestMyMetaShader.xml, and add to it:

    <shaderManifest format='1.0' label="Example metashader manifest">
        <plugins relative="False" basepath="${SHOWASSETS}/ExampleMetashaders/">
            <shader name="ExampleOver"                  path="pattern"/>
            <shader name="ExampleFbm"                   path=""/>
            <shader name="ExampleVoronoi"               path="pattern"/>
            <shader name="ExampleBxdf"                  path="bxdf"/>
        </plugins>
    </shaderManifest>
    
  2. In this example, "plugins relative=False" means that the base path will be used as an absolute path. Otherwise, the basePath is relative to the location of the shader manifest file for the actual plugin.

    basepath= specifies the base path for the .args files.

    path= specifies the subdirectory under the base path. Katana will look for .args file in <basepath>/<path>/Args/, e.g. ${SHOWASSETS}/ExampleMetashaders/pattern/Args/ for pattern metashaders. If path is set to an empty string, as in ExampleFbm above, then the .args file will be ${SHOWASSETS}/ExampleMetashaders/Args/ExampleFbm.args.

The Metashader .Args File

The only difference between a metashader .args file and one for a real plugin is the existence of this block:

<args>
    <metashader shader="myRealShader"/>
    ...
</args>.

Note that the <metashader name> above needs to be inside the <args> ... </args> block.

NodeId And Classification (RenderMan for Maya-Only)

For RenderMan for Maya, metashader .args files need to specify a nodeid and a classification, like a custom plugin. The nodeid specified must not be an existing nodeid, or there will be conflicts in Maya. Maya sets aside the range from 0 to 524288 for sites to use for their own custom nodes.

The classification indicates where in Maya Hypershade the metashader will appear. You need to pick an established category (as seen in another valid .args file) or it won't be recognized. Here's what the tag looks like:

<rfmdata nodeid="524244"
         classification="rendernode/RenderMan/pattern"/>

Examples

Pattern Metashader

Here is an example of using the metashader mechanism to transform the PxrSeExpr shader into ExampleOver. To do this we author a new .args file called ExampleOver.args and place it in the appropriate location. Note that if we create a PxrSeExpr node interactively, we cannot rename the parameters nor remove unused parameters. Using a metashader, it allows us to name the parameters that would make sense to the users, and it only shows the parameters specified in the metashader file .

<args format="1.0">
    <metashader shader="PxrSeExpr" />

    <param name="inputTop" type="color" default="1.0 1.0 1.0">
        <tags>
            <tag value="color"/>
        </tags>
    </param>
    <param name="inputBottom" type="color" default="1.0 1.0 1.0">
        <tags>
            <tag value="color"/>
        </tags>
    </param>
    <param name="mask" type="float" default="1">
        <tags>
            <tag value="float"/>
        </tags>
    </param>
    <param name="expression"
           type="string"
           default="$result=mix($inputBottom,$inputTop,$mask);$result"
           widget="null"/>

    <output name="resultRGB">
        <tags>
            <tag value ="color"/>
            <tag value ="vector"/>
            <tag value ="normal"/>
            <tag value ="point"/>
        </tags>
    </output>
    <output name="resultR">
        <tags>
            <tag value ="float"/>
        </tags>
    </output>
    <output name="resultG">
        <tags>
            <tag value ="float"/>
        </tags>
    </output>
    <output name="resultB">
        <tags>
            <tag value ="float"/>
        </tags>
    </output>
    <output name="resultF">
        <tags>
            <tag value ="float"/>
        </tags>
    </output>
    <typeTag>
        <tag value="pattern"/>
    </typeTag>

    <!-- NOTE: This is required for RenderMan for Maya but is ignored by RenderMan for Katana. -->
    <rfmdata nodeid="524244"
             classification="rendernode/RenderMan/pattern"/>
</args>

In the example above, the shader parameter expression's widget is set to null. That means it is hidden from the user interface. When this metashader is loaded the user will not see the underlying expression - "$result=mix($inputBottom,$inputTop,$mask);$result" - for creating this pattern. If you want the user to see the expression, set widget="text". As you can see, it is a basic .args file, but the metashader node tells the the PRMan plugin to inject "PxrSeExpr" when the RIB is generated for the shader, instead of "ExampleOver".

Bxdf Metashader

PxrSeExpr is especially well-suited to metashaders, due to its dynamic nature, but metashaders can be used with any shader, including a Bxdf shader. Here is an example of using the metashader mechanism to transform the PxrDisney shader into ExampleChrome. To do this we author a new .args file called ExampleChrome.args and place it in the appropriate location. The .args file would then look something like this:

<args format="1.0">
    <metashader shader="PxrDisney" />
    <param name="baseColor" label="Base Color" type="color"
           default="1.0 1.0 1.0" widget="color">
      <tags>
          <tag value="color"/>
      </tags>
  </param>
  <param name="specular" label="Specular" type="float"
         default=".5" widget="default"
         slider="True" slidermin="0" slidermax="1" >
      <tags>
          <tag value="float"/>
      </tags>
  </param>
  <param name="specularTint" label="Specular Tint" type="float"
         default="0" widget="default">
      <tags>
          <tag value="float"/>
      </tags>
  </param>
  <param name="roughness" label="Roughness" type="float" default=".25"
         widget="default"
         min="0.001" max="1.0"
         slider="True" slidermin="0.001" slidermax="1" slidersensitivity="0.1">
      <tags>
          <tag value="float"/>
      </tags>
  </param>
  <param name="anisotropic" label="Anisotropic" type="float"
         default="0" widget="default">
      <tags>
          <tag value="float"/>
      </tags>
  </param>
  <param name="clearcoat" type="float" label="Clearcoat"
         default="0" widget="default">
      <tags>
          <tag value="float"/>
      </tags>
  </param>
  <param name="clearcoatGloss" type="float" label="Clearcoat Gloss"
         default="1" widget="default">
      <tags>
          <tag value="color"/>
      </tags>
  </param>
  <typeTag>
      <tag value="bxdf"/>
  </typeTag>

  <!-- NOTE: This is required for RenderMan for Maya but is ignored by RenderMan for Katana. -->
  <rfmdata nodeid="524242"
           classification="rendernode/RenderMan/pattern"/>

</args>
  • NOTE

    Any shader parameters that are not specified in the metashader will be hidden.

Here we have made a new interface for the PxrDisney shader. One could add labels to the parameters to further customize it. Setting defaults can be used to override the real defaults of the plugin because metashaders will always emit the parameters into the RIB stream. For RenderMan for Katana, this is different than the regular Katana behavior of only emitting edited values, but it is necessary because for some shaders there may not be a built-in default. Such is the case for the PxrSeExpr shader, where there are not even any predefined parameters, let alone defaults that could be accessed in the expression.