Working with PxrOSL

Working with PxrOSL

PxrOSL implementation notes:

Note a number of OSL attributes are available to be set within a RIB file. The following attributes are supported:

  • Attribute "user" "uniform int osl:debug" [0]
  • Attribute "user" "uniform int osl:optimize" [1]
  • Attribute "user" "uniform int osl:lockgeom" [1]
  • Attribute "user" "uniform int osl:debug_nan" [0]
  • Attribute "user" "uniform int osl:debug_uninit" [0]
  • Attribute "user" "uniform int osl:compile_report" [0]
  • Attribute "user" "uniform int osl:statistics:level" [0]

Binding primvars on geometry in PRMan is fairly simple: just mark the parameters in the shader with metadata [[int lockgeom = 0]]. This will tell the shading system to consider this variable as varying input and it will bind the variable in the shader if it is present on the geometry. Also note you can bind outputs of other RiPattern nodes and the PxrOSL node will automatically bind the output of one RiPattern node to the parameter of the PxrOSL shader. Likewise the output of an OSL shader can be referenced by other nodes, be they RiPattern or RiBxdf nodes. Simply reference them by name.


The Network XML File Format

Grammar

The grammar for the Network XML file format is a BNF-like form. We don't use < > to denote non-terminals - since we're describing XML that could get confusing. Instead, capitalized symbols are non-terminal. We don't bother specifying the non-terminal String, etc.

element(name, attributes, sub-elements) is just a macro for specifying an XML element node - <name [attibutes]>sub-elements</name>.

POSN                    :== element('RenderManOSLNetwork', POSN_Attributes, POSN_Elements)

POSN_Attributes         :== 'Version' Integer

POSN_Elements           :== element('Label',,String),
                            NodeList [ , ConnectionList ]
                            [ , node('Meta',,Meta_Elements) ]

NodeList                :== element('NodeList',,NodeList_Elements)

NodeList_Elements       :== Node  [ Node, ... ]

ConnectionList          :== element('ConnectionList',,ConnectionList_Elements)

ConnectionList_Elements :== Connection  [ Connection, ... ]


Node                    :== element('Node', , Node_Elements)

Node_Elements           :== NodeId | NodeLayer | Label | Master | PropertList
                            [ Node_Elements ...]


Property_Elements       :== Visibility | Value | Default | Type | Access
                            [ Node_Elements ...]

Visibility              :== element('Visibility',, 'internal' | 'external')
Label                   :== element('Label',, String)
Value                   :== element('Value',, String)
Default                 :== element('Default',, String)
Type                    :== element('Type',, ParameterTypes)
Access                  :== element('Access',, 'input' | 'ouput')


Connection              :== element(Source, , ConnectionInfo),
                            element(Destination, , ConnectionInfo),

ConnectionInfo          :== NodeLayer, ParameterName

NodeId,NodeLayer        :== String

ParameterNode           :== String

ParameterTypes          :== 'int' | 'float' | 'color' | 'string' | 'struct'

Example

<!--
 This is a three node graph, two textures wired into a thing called a merge.
 in DOT this would be:

 digraph network2 {
     C/mixcolor [label="merge it"];
     B/texsimple [label="tex1"];
     A/texsimple [label="texture 2"];

     A/texsimple -> C/mixcolor;
     B/texsimple -> C/mixcolor;
 }

 Nomenclature: NodeId is the path to the OSL shader to load.
               NodeLayer is the name of this specific layer.
               There can be many NodeIds from the same source,
               but the NodeLayers will most likely be uniquely
               named.
-->

<RenderManOSLNetwork Version="1">
  <Label>texnetwork</Label>
  <NodeList>
      <Node>
        <NodeId>shaders/texsimple</NodeId>
        <NodeLayer>B</NodeLayer>
        <Label>tex1</Label>
        <Modified>1259106721</Modified>
        <Properties>
            <filename>
              <Value>ratGrid.tex</Value>
              <Type>string</Type>
            </filename>
            <Cout>
              <Access>output</Access>
              <Type>color</Type>
            </Cout>
          </Properties>
      </Node>
      <Node>
        <NodeId>shaders/texsimple</NodeId>
        <NodeLayer>A</NodeLayer>
        <Label>texture 2</Label>
        <Modified>1259106721</Modified>
        <Properties>
            <filename>
              <Value>flowers.tex</Value>
              <Type>string</Type>
            </filename>
            <Cout>
              <Access>output</Access>
              <Type>color</Type>
            </Cout>
          </Properties>
      </Node>
      <Node>
        <NodeId>shaders/mixcolor</NodeId>
        <NodeLayer>C</Layer>
        <Label>merge it</Label>
        <Properties>
            <inC1>
              <Visibility>internal</Visibility>
              <Type>color</Type>
            </inC1>
            <inC2>
              <Visibility>internal</Visibility>
              <Type>color</Type>
            </inC2>
            <Cout>
              <Access>output</Access>
              <Type>color</Type>
            </Cout>
          </Properties>
      </Node>
  </NodeList>
  <ConnectionList>
    <Connection>
       <Source>
        <NodeId>shaders/texsimple</NodeId>
        <NodeLayer>A</NodeLayer>
        <ParameterName>Cout</ParameterName>
       </Source>
       <Destination>
        <NodeId>shaders/mixcolor</NodeId>
        <NodeLayer>C</NodeLayer>
        <ParameterName>inC1</ParameterName>
       </Destination>
    </Connection>
    <Connection>
       <Source>
        <NodeId>shaders/texsimple</NodeId>
        <NodeLayer>B</NodeLayer>
        <ParameterName>Cout</ParameterName>
       </Source>
       <Destination>
        <NodeId>shaders/mixcolor</NodeId>
        <NodeLayer>C</NodeLayer>
        <ParameterName>inC2</ParameterName>
       </Destination>
    </Connection>
  </ConnectionList>
</RenderManOSLNetwork>

Aggregates Types

The XML format has some support for OSL's aggregate types array and struct. Arrays are declared in using the <Array> sub-node like this:

<Properties>
  <colors>
    <Type>color</Type>
    <Array>
        <Value>0.0 0.1 0.0</Value>
        <Value>0.2 0.3 0.0</Value>
        <Value>0.3 0.6 0.0</Value>
        <Value>0.7 0.9 0.2</Value>
    </Array>
  </colors>
  ...

Array parameters can be connected like simple parameters both in the XML network and are bound to arguments in RIB files. Here's how the above colors example could be overriden from RIB:

Pattern "PxrOSL" "expr3"
  "string network" "interparray"
  "color A.colors[4]" [ 0.0 0.0 0.0 0.2 0.2 0.2 0.5 0.5 0.5 0.9 0.9 0.9 ]

Support for struct is more restricted. The OSL network can internally connect struct parameters together but those parameters cannot be bound to RIB arguments. To indicate this, struct parameters must be declared internal using the <Visibility> tag. <Visibility> defaults to external which is why we haven't seen it in the examples so far. A struct parameter also does not have default values in the XML and simply is declared like this:

<Properties>
    <ms>
      <Visibility>internal</Visibility>
      <Type>struct</Type>
    </ms>
    ...
</Properties>

Connecting structs in the network is exactly the same as other parameter types. There is no way to connect fields within struct individually.


More Info

For more information on OSL, the oslc compiler, and oslquery please consult the OSL documentation from Sony Pictures ImageWorks.