NVIDIA Iray API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
mi::ICompound_shader_class Class Referenceabstract

This interfaces represents a compound shader class, a description of a set of compound shaders --shaders implemented by an encapsula behaviors. More...

Inheritance diagram for mi::ICompound_shader_class:
Inheritance graph
[legend]

Public Member Functions

virtual Sint32  add_node (const char *node_name, const char *class_name)=0
  Create a node within this compound shader class named node_name and of type class_name. More...
 
virtual IShader edit_shader (const char *node_name) const =0
  Returns a non-const shader instance node or NULL if there exists no such shader instance node. More...
 
virtual const IShader access_shader (const char *node_name) const =0
  Returns a const shader instance node or NULL if there exists no such shader instance node. More...
 
virtual IShader_graph edit_shader_graph (const char *node_name) const =0
  Returns a non-const shader graph instance node or NULL if there exists no such shader graph instance node. More...
 
virtual const IShader_graph access_shader_graph (const char *node_name) const =0
  Returns a const shader graph instance node or NULL if there exists no such shader graph instance node. More...
 

Additional Inherited Members

- Public Types inherited from mi::base::Interface_declare< 0xbbfc8692, 0xaa49, 0x4fd5, 0xbb, 0x1b, 0x86, 0x22, 0xeb, 0x72, 0xc0, 0x0a, IShader_class >
typedef Interface_declare< id1,
id2, id3, id4, id5, id6, id7,
id8, id9, id10, id11,
IShader_class
Self
  Own type. More...
 
typedef Uuid_t< id1, id2, id3,
id4, id5, id6, id7, id8, id9,
id10, id11 > 
IID
  Declares the interface ID (IID) of this interface. More...
 
- Static Public Member Functions inherited from mi::base::Interface_declare< 0xbbfc8692, 0xaa49, 0x4fd5, 0xbb, 0x1b, 0x86, 0x22, 0xeb, 0x72, 0xc0, 0x0a, IShader_class >
static bool  compare_iid (const Uuid &iid)
  Compares the interface ID iid against the interface ID of this interface and of its ancestors. More...
 

Detailed Description

This interfaces represents a compound shader class, a description of a set of compound shaders --shaders implemented by an encapsula behaviors.

Note
MetaSL is deprecated. Support for MetaSL might be removed in future releases. Use MDL instead.

Introduction

An mi::ICompound_shader_class is a subclass of an mi::IShader_class. Thus, it inherits all the behaviors of mi::IShader_class. However, it also adds extra functionality. In particular, an mi::ICompound_shader_class, in contrast to an mi::IShader_class, allows you, through its API, to explicitly specify the program this mi::ICompound_shader_class corresponds to. An mi::IShader_class, in contrast, corresponds to a fixed program that is not able to be specified through this API. (Usually, the program corresponding to an mi::IShader_class is specified through various input files or built-in mi::IShader_class's.)

The program an mi::ICompound_shader_class corresponds to is built from various smaller programs by connecting the output of one of these programs to the input of another program. Each of these smaller programs corresponds to an mi::IShader or an mi::IShader_graph. So, roughly, a mi::ICompound_shader_class can be thought of as a named adhoc shader graph. (For more information on adhoc shader graphs refer to the mi::IShader documentation.)

Building an mi::ICompound_shader_class

Building an mi::ICompound_shader_class consists of four phases:

  1. Creating an mi::ICompound_shader_class
  2. Collecting the smaller program segments
  3. Connecting the smaller program segments
  4. Storing the mi::ICompound_shader_class

You first create an mi::ICompound_shader_class using a call to mi::neuraylib::ITransaction::create(const char* type_name,Uint32 argc = 0, const base::IInterface* argv[] = 0). (Note, unlike most uses of this method, creation here requires you pass non-trivial values for argc and argv.)

You then collect together the small program segments you wish to use in the newly created mi::ICompound_shader_class. This is done through calls to the method add_node(). Upon success, each such call adds a named program segment to the collection of program segments available to this newly created mi::ICompound_shader_class.

Next you connect these small program segments together. This consists of indicating which program segments process the inputs of the mi::ICompound_shader_class, which program segments process the outputs of this first set of program segments, which program segments process the outputs of this second set of program segments etc. until, eventually, the outputs of a final set of program segments are connected to the outputs of the mi::ICompound_shader_class.

Finally, you store the newly created mi::ICompound_shader_class in the database under the name you wish to assign to the newly created compound shader class. This store ends the build process. In particular, after you store this newly created mi::ICompound_shader_class in the database, you can no longer edit it. In contrast to other mi::IScene_element's, editing an mi::ICompound_shader_class after it has been stored in the database is expressly forbidden.

Creating an mi::ICompound_shader_class

Creation of an mi::ICompound_shader_class is done through use of the method mi::neuraylib::ITransaction::create(const char* type_name,Uint32 argc = 0, const base::IInterface* argv[] = 0). When calling this method to create an mi::ICompound_shader_class, the first argument type_name is the string "Compound_shader_class". The second argument argc is 2, and the final argument is an array of two mi::IAttribute_container's. The first mi::IAttribute_container specifies the set of allowed input parameters for the new compound shader class as well as their default values. The second mi::IAttribute_container specifies the set of allowed output parameters for the new compound shader class.

So, for example, creation of an mi::ICompound_shader_class will generally be of the form:

// Create Input IAttribute_container
transaction->create<mi::IAttribute_container>("Attribute_container"));
// Populate input_parameters with input parameters and default values
// Create Ouput IAttribute_container
transaction->create<mi::IAttribute_container>("Attribute_container"));
// Populate output_parameters with output parameters
// Set up argc and argv
mi::Uint32 argc = 2;
const mi::base::IInterface* argv[2] = { input_parameters.get(), output_parameters.get() };
// Create IShader_graph_class
transaction->create<mi::ICompound_shader_class>(
"Compound_shader_class",argc,argv));

Collecting the Smaller Program Segments

Collecting together the small program segments you wish to use in the newly created mi::ICompound_shader_class is done through calls to the method add_node(). Each successful call to the method add_node() adds a new, named program segment to the collection of program segments available to this newly created mi::ICompound_shader_class.

Each successful call to add_node() adds a named mi::IShader or mi::IShader_graph instance node to the newly created mi::ICompound_shader_class. It is these instances that are the small programs out of which the larger mi::ICompound_shader_class program is built. (As mentioned in the documentation of mi::IShader and mi::IShader_graph, an mi::IShader instance is a program and an mi::IShader_graph instance also is a program.)

So, for example, if through an import you have loaded an mi::IShader_class named "shader2", then you can add a small program segment named "surface" of type "shader2", an mi::IShader instance, to the newly created mi::ICompound_shader_class as follows:

// Add an mi::IShader instance node named "surface" of type "shader2"
mi::Sint32 result = compound_shader_class->add_node("surface",
"shader2");

where compound_shader_class is the mi::ICompound_shader_class created in the last code snippet.

In addition, you can add instances of predefined mi::IShader_class's. For example, there exists a predefined mi::IShader_class named "Bsdf_phong". So, you can add a small program segment named "volume" of type "Bsdf_phong" to the newly created mi::ICompound_shader_class as follows:

// Add an mi::IShader instance node named "volume" of type "Bsdf_phong"
mi::Sint32 result = compound_shader_class->add_node("volume",
"Bsdf_phong");

where compound_shader_class is your mi::ICompound_shader_class.

Also, you can add mi::IShader_graph instances. Assume that you defined an mi::IShader_graph_class "TestShaderGraphClass". You can then add a small program segment named "displacement" of type "TestShaderGraphClass", an mi::IShader_graph instance, to the newly created mi::ICompound_shader_class as follows:

// Add an mi::IShader_graph instance node named "displacement" of type "TestShaderGraphClass"
mi::Sint32 result = compound_shader_class->add_node("displacement",
"TestShaderGraphClass");

where compound_shader_class is your mi::ICompound_shader_class.

Connecting the Smaller Program Segments

There are two means of connecting the smaller program segments:

Connecting using mi::IShader_connections

mi::ICompound_shader_class supports the mi::IShader_connections interface. It is through this interface that you can connect together the small program segments within an mi::ICompound_shader_class.

For example, assume that you wanted to connect the output of one mi::IShader instance node to the input of a second mi::IShader instance node. Concretely, assume that you have an mi::IShader instance node named "node1" and an mi::IShader instance node named "node2" both within the same compound shader class. Furthermore, assume that "node1" has an output named "result" of type Color and "node2" has an input named "input" of type Color. You can then connect the "result" output of "node1" to the "input" input of "node2" as follows:

// Obtain IShader_connections interface of compound_shader_class
compound_shader_class->get_interface<mi::IShader_connections>());
// Connect the "result" output of "node1" to the "input" input of "node2"
mi::Sint32 result = shader_connections->add_connection("node2.input",
"node1.result");

where compound_shader_class is your mi::ICompound_shader_class.

Similarly, in the same situation, if you only wished to connect the "r" component of "result" to the "r" component of "input", then you can do so as follows:

// Obtain IShader_connections interface of compound_shader_class
compound_shader_class->get_interface<mi::IShader_connections>());
// Connect the "result.r" output of "node1" to the "input.r" input of "node2"
mi::Sint32 result = shader_connections->add_connection("node2.input.r",
"node1.result.r");

again compound_shader_class is your mi::ICompound_shader_class.

As another example, assume you wanted to connect the output of one mi::IShader instance node to the output of the mi::ICompound_shader_class. Concretely, assume that you have an mi::IShader instance node named "node1" with an output named "result" of type Color. Assume also that the mi::ICompound_shader_class has an output named "result" of type Color. You can then connect the "result" output of "node1" to the "result" output of the compound shader class as follows:

// Obtain IShader_connections interface of compound_shader_class
compound_shader_class->get_interface<mi::IShader_connections>());
// Connect the "result" output of "node1" to the "result" output of the compound shader class
mi::Sint32 result = shader_connections->add_connection("result",
"node1.result");

where compound_shader_class is your mi::ICompound_shader_class.

Similarly, in the same situation, if you only wished to connect the "r" component of the "result" of "node1" to the "r" component of the compound shader "result", then you can do so as follows:

// Obtain IShader_connections interface of compound_shader_class
compound_shader_class->get_interface<mi::IShader_connections>());
// Connect the "result.r" output of "node1" to "result.r" output of the compound shader class
mi::Sint32 result = shader_connections->add_connection("result.r",
"node1.result.r");

again compound_shader_class is your mi::ICompound_shader_class. (Note, using the mi::IShader_connections interface of a compound shader class is the only way to target the output parameter of a compound shader class for a connection.)

Connecting using mi::IShader's and mi::IShader_graph's

You can obtain a non-const mi::IShader node using edit_shader() and you can obtain non-const mi::IShader_graph node using edit_shader_graph(). Using the mi::IShader_connections interface of mi::IShader or mi::IShader_graph you can then connect together the small program segments within an mi::ICompound_shader_class.

As in our previous example, assume that you wanted to connect the output of one mi::IShader instance node to the input of a second mi::IShader instance node. Concretely, assume that you have an mi::IShader instance node named "node1" and an mi::IShader instance node named "node2" both within the same compound shader class. Furthermore, assume that "node1" has an output named "result" of type Color and "node2" has an input named "input" of type Color. You can then connect the "result" output of "node1" to the "input" input of "node2" as follows:

// Edit the IShader "node2"
compound_shader_class->edit_shader("node2"));
// Obtain IShader_connections interface of shader
shader->get_interface<mi::IShader_connections>());
// Connect the "result" output of "node1" to the "input" input of "node2"
mi::Sint32 result = shader_connections->add_connection("input",
"node1.result");

where compound_shader_class is your mi::ICompound_shader_class. You can also write a similar snippet using an mi::IShader_graph and edit_shader_graph().

Similarly, in the same situation, if you only wished to connect the "r" component of "result" to the "r" component of "input", then you can do so as follows:

// Edit the IShader "node2"
compound_shader_class->edit_shader("node2"));
// Obtain IShader_connections interface of shader
shader->get_interface<mi::IShader_connections>());
// Connect the "result.r" output of "node1" to the "input.r" input of "node2"
mi::Sint32 result = shader_connections->add_connection("input.r",
"node1.result.r");

again compound_shader_class is your mi::ICompound_shader_class. You can also write a similar snippet using an mi::IShader_graph and edit_shader_graph().

As another example, assume you wanted to connect the input of the compound shader class to the input of an mi::IShader instance node. Concretely, assume that the compound shader class has an input named "cs_input" of type Color. Assume also that you have an mi::IShader instance node named "node1" with an input named "s_input" of type Color. You can then connect the "cs_input" input of the compound shader class to the "s_input" input of the "node1" as follows:

// Edit the IShader "node1"
compound_shader_class->edit_shader("node1"));
// Obtain IShader_connections interface of shader
shader->get_interface<mi::IShader_connections>());
// Connect the "cs_input" input of the compound shader class to the "s_input" input of "node1"
mi::Sint32 result = shader_connections->add_connection("s_input",
"cs_input");

where compound_shader_class is your mi::ICompound_shader_class and you can write a similar snippet using an mi::IShader_graph and edit_shader_graph(). (Note, using the mi::IShader_connections interface of a shader or shader graph is the only way to source the input parameter of a compound shader class for a connection.)

Storing an mi::ICompound_shader_class

When one is finished collecting and connecting the smaller program segments, the final phase of building an mi::ICompound_shader_class is storing the compound shader class in the database. Storing the compound shader class makes it available to be used like any other mi::IShader_class.

Storing an mi::ICompound_shader_class is like storing any other mi::IScene_element in the database . You employ an mi::neuraylib::ITransaction as follows:

// Store the compound_shader_class in the database
mi::Sint32 result = transaction->store(compound_shader_class.get(),
"MyCompoundShaderClass");

where compound_shader_class is an mi::ICompound_shader_class. The name under which the compound shader class is stored is then the name of the compound shader class. (In the case above we have introduced a compound shader class with the name "MyCompoundShaderClass".)

Note that, unlike other mi::IScene_element classes, after storing a compound shader in the database, you can no longer edit it only access it. This constraint is imposed to keep the the class and its instances in sync. If it were not imposed, it would lead to many strange and undesirable behaviors that are best avoided.

Using an mi::ICompound_shader_class

To use an mi::ICompound_shader_class you access it from the database and then proceed to call the desired methods on the retrieved compound shader class.

For example, if you, as above, have a compound shader class named "MyCompoundShaderClass" and wish to create an mi::IShader instance "MyCompoundShader" of the type "MyCompoundShaderClass", then you would do so as follows:

// Access the ICompound_shader_class from the DB
compound_shader_class(
transaction->access<mi::ICompound_shader_class>(
"MyCompoundShaderClass"));
// Create compound shader "MyCompoundShader" of type "MyCompoundShaderClass"
mi::Sint32 result = compound_shader_class->create_shader("MyCompoundShader");

Note, create_shader() behaves just like mi::IShader_class::create_shader(). A similar statement is true for create_function().

Member Function Documentation

virtual const IShader* mi::ICompound_shader_class::access_shader ( const char *  node_name) const
pure virtual

Returns a const shader instance node or NULL if there exists no such shader instance node.

Note, you can not use this method to obtain a const mi::IShader_graph node instance.

This const mi::IShader instance node is usually used to examine the connections and input parameters of the specified mi::IShader node instance.

Parameters
node_name The name of the mi::IShader node to obtain
Returns
The mi::IShader instance node or NULL if no such node exists
virtual const IShader_graph* mi::ICompound_shader_class::access_shader_graph ( const char *  node_name) const
pure virtual

Returns a const shader graph instance node or NULL if there exists no such shader graph instance node.

Note, you can not use this method to obtain a const mi::IShader instance node.

This const mi::IShader_graph instance node is usually used to examine the connections and input parameters of the specified mi::IShader_graph node instance.

Parameters
node_name The name of the mi::IShader_graph node to obtain
Returns
The mi::IShader_graph instance node or NULL if no such node exists
virtual Sint32 mi::ICompound_shader_class::add_node ( const char *  node_name,
const char *  class_name 
)
pure virtual

Create a node within this compound shader class named node_name and of type class_name.

The created node will have all input parameters present and set to their default values or 0 if there is no apropos default value.

The name node_name must not be the name of an existing input parameter, output parameter, or node. In addition, the name node_name must be a valid MetaSL identifier.

The type class_name must be the name of an existing mi::IShader_class or mi::IShader_graph_class.

Parameters
node_name The name of the new node.
class_name The type of the new node
Returns
  • 0: Success.
  • -1: Invalid parameters (NULL pointer).
  • -2: Invalid class name
  • -3: Internal error
virtual IShader* mi::ICompound_shader_class::edit_shader ( const char *  node_name) const
pure virtual

Returns a non-const shader instance node or NULL if there exists no such shader instance node.

Note, you can not use this method to obtain a non-const mi::IShader_graph node instance.

This non-const mi::IShader instance node is usually used to modify an mi::IShader input parameter, to connect this mi::IShader to another node, or to connect this mi::IShader to an input parameter of this mi::ICompound_shader_class.

Parameters
node_name The name of the mi::IShader node to obtain
Returns
The mi::IShader instance node or NULL if no such node exists
virtual IShader_graph* mi::ICompound_shader_class::edit_shader_graph ( const char *  node_name) const
pure virtual

Returns a non-const shader graph instance node or NULL if there exists no such shader graph instance node.

Note, you can not use this method to obtain a non-const mi::IShader instance node.

This non-const mi::IShader_graph instance node is usually used to modify an mi::IShader_graph input parameter, to connect this mi::IShader_graph to another node, or to connect this mi::IShader_graph to an input parameter of this mi::ICompound_shader_class.

Parameters
node_name The name of the mi::IShader_graph node to obtain
Returns
The mi::IShader_graph instance node or NULL if no such node exists