NVIDIA Iray API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Shaders (MetaSL)

Shaders comprise a set of interfaces related to the MetaSL. More...

Classes

class   mi::ICompound_shader_class
  This interfaces represents a compound shader class, a description of a set of compound shaders --shaders implemented by an encapsula behaviors. More...
 
class   mi::IMaterial
  Materials reference shaders of certain types. More...
 
class   mi::IShader
  This interface represents shaders. More...
 
class   mi::IShader_class
  This interfaces represents a shader class, a description of a set of shaders with common characteristics and behaviors. More...
 
class   mi::IShader_connections
  A shared interface for all shader, shader graph, shader graph class, and compound shader class interfaces that allow connections to their input parameters or on their contained shader or shader graph nodes. More...
 
class   mi::IShader_graph
  This interfaces represents shader graphs. More...
 
class   mi::IShader_graph_class
  This interface represents a shader graph class, a formalized description of a set of adhoc shader graphs with common characteristics and behaviors. More...
 

Detailed Description

Shaders comprise a set of interfaces related to the MetaSL.

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

The shaders module contains all the classes involved with creating and manipulating shaders, user supplied programs that allow parts of the graphics pipeline to be customized.

Of the myriad of classes contained in this module, the class mi::IShader is perhaps the most important to understand. It provides the foundation upon which all other classes in this module are built. So, we start this module overview with an overview of the class mi::IShader.

mi::IShader

An mi::IShader instance can be thought of as a small program. It takes inputs, processes these inputs, and produces outputs. The inputs are named and can be of a wide variety of types. mi::IBoolean, mi::IFloat32, mi::IFloat64... are all allowed. (The full set of allowed input types can be found here Types.) Similarly, the outputs are named and can also be of a wide variety of types. (The full set of allowed output types can be found here Types.) Beyond inputs and outputs that are named and typed, an mi::IShader instance encapsulates a small program that processes the inputs, resulting in the outputs. This small program is specified by the next class we will examine, mi::IShader_class.

mi::IShader_class

An mi::IShader_class instance can be thought of as an instance specifying of a set of mi::IShader instances with common characteristics and behaviors. Specifically, the relation between an mi::IShader_class instance and its set of mi::IShader instances is analogous to the relation between a C++ class and its set of instances.

Introduction

Small Programs

A C++ class specifies the small program that is run in response to a method on one of its instances being executed. Analogously, an mi::IShader_class instance specifies the small program that is run in response to an mi::IShader instance being executed. There are many ways to associate such a small program with an mi::IShader_class. For example, the small program could be built in to Iray, loaded from a file, or created programmatically at runtime. The most apropos means of establishing this association depends upon the problem and resources at hand.

Inputs

In analogy to a C++ class specifying the names, types, and default values for a C++ method, an mi::IShader_class instance specifies the names, types, and default values for the inputs of any corresponding mi::IShader instances. (The default value of an input is the value an input acquires when an mi::IShader is executed and no value is explicitly specified for this input.)

Outputs

In analogy to a C++ class specifying the return type for a C++ method, an mi::IShader_class instance specifies the names and types for the outputs of any corresponding mi::IShader instances. (Outputs do not have default values. Output values are always computed at runtime when an mi::IShader is executed.)

Specifying Small Programs

The association between a small program and an mi::IShader_class can arise in many different ways. The small program could, for example, be built in to Iray, loaded from a file, or created programmatically at runtime. We will cover each of these cases below.

Built In's

The Iray library ships with a wide variety of built in small programs, commonly referred to as "built in shader classes" or simply "built-in's". This set of built-in's cover a wide variety of common use cases and is provided as a convenience to users of the Iray library. For example, as part of the MetaSL implementation, the built-in's "Bsdf_lambert", "Bsdf_phong", "Bsdf_oren_nayar", and "Bsdf_ashikhmin_shirley" are included. Other built-in's, that are not part of the MetaSL implementation, are also included. However, we will not touch upon them here.

Load From File

To supplement the built in shader classes the Iray library allows for the user to load a small program, in fact an entire shader class, from a file. More often than not, this small program is specified using MetalSL, a domain-specific language for the writing the small programs encapsulated by shader classes. The details of loading such shader classes from a file are covered in the documentation for the methods mi::neuraylib::IImport_api::import_elements() and mi::neuraylib::IImport_api::import_elements_from_string().

Created Programmatically

In addition to specifying a small program using a built-in or a loaded file, the Iray library allows the user to programmatically create such a small program at runtime. As this requires an entirely new set of tools, not present in mi::IShader_class, a new class, mi::ICompound_shader_class, is introduced, in part, for just this purpose.

mi::ICompound_shader_class

mi::ICompound_shader_class is a subclass of mi::IShader_class; hence, all of the functionality present in mi::IShader_class is also present in mi::ICompound_shader_class. However, mi::ICompound_shader_class supplements the functionality of mi::IShader_class with the ability to programmatically create a shader class at runtime. In addition, the class mi::ICompound_shader_class allows the user to examine a compound shader class loaded into the database. We will now examine mi::ICompound_shader_class in a bit more detail.

An mi::ICompound_shader_class can be used in two distinct ways. First, it can be used to examine a compound shader class stored in the database. Second, it can be used to programmatically create a simple program, in fact an entire shader class, at runtime. As the simpler of these two use cases is the first, we begin by examining this use case.

Examination of Compound Shader Classes

A compound shader class can be loaded, through a myriad of means, into the database. These include importing ".mi" files, importing MetaSL files, and programmatic creation and storing of a compound shader class, as we shall see below. Assuming one of these means was used to load a compound shader class into the database, the question then arises how does the user examine this compound shader class? The answer is using mi::ICompound_shader_class.

Using mi::neuraylib::ITransaction::access() the user can access the compound shader class like any other scene element. As an mi::ICompound_shader_class is an mi::IShader_class, all of the functionality for examining an mi::IShader_class is present. However, additional functionality present in an mi::ICompound_shader_class allows the user to examine characteristics of a compound shader class not present in an mi::IShader_class.

mi::ICompound_shader_class allows the user to examine the nodes present in the compound shader class and the connections between these nodes. Examination of the nodes is accomplished through direct manipulation of the mi::ICompound_shader_class interface. Examination of the connections between these nodes is accomplished through manipulation of the interface mi::IShader_connections which mi::ICompound_shader_class implements. (The interface mi::IShader_connections will be covered in more detail below.)

Programmatic Creation of a Shader Class

As previously mentioned, an mi::ICompound_shader_class can be used to programmatically create a shader class at runtime. Creating a shader class requires specifying four pieces of information: inputs, outputs, a name, and a simple program. We now cover how each of these four pieces of information is specified when using mi::ICompound_shader_class to programmatically create a shader class at runtime.

Inputs and Output

To specify the inputs of a programmatically created a shader class the user must specify a set of names, types, and default values. The names name the inputs. The types specify the types of the inputs, and the default values specify the values the inputs take when their value is not explicitly given. All of this data is specified through an mi::IAttribute_container instance. The names of its attributes are the names of the inputs. The types of its attributes are the types of the inputs, and the values of its attributes are the default values of the inputs.

To specify the outputs of a programmatically created a shader class the user must specify a set of names and types. The names specify the names of the outputs, and the types specify the types of the outputs. All of this data is also presented through an mi::IAttribute_container instance. The names of its attributes are the names of the outputs, and the types of its attributes are the types of the outputs.

The two mi::IAttribute_container instances, one for inputs and one for outputs, are then used to create an mi::ICompound_shader_class instance. (The details of this are covered in the mi::ICompound_shader_class documentation.) This newly created mi::ICompound_shader_class then represents a shader class with the specified inputs and outputs.

Name

The name a user needs to specify is simply the name of the resulting shader class. This is simply the name under which the mi::ICompound_shader_class is stored in the database.

Simple Program

The most complicated step in programmatically creating a shader class at runtime is creating its simple program. Generally, creating this simple program is accomplished by connecting together several other small programs. The output of one small program is used as the input of a second small program, the output of this second small program is used as the input to a third small program.... With apropos building blocks, a diverse set of small programs, connecting together small programs in this manner allows the user to create an arbitrary simple program for a programmatically created shader class.

Creating these small programs, often called nodes, is accomplished through the mi::ICompound_shader_class interface. Each node, or small program, is an mi::IShader or mi::IShader_graph instance and is added to the simple program defined by the mi::ICompound_shader_class instance using the method mi::ICompound_shader_class::add_node().

Connecting together these small programs is accomplished through the interface mi::IShader_connections which mi::ICompound_shader_class implements. The interface mi::IShader_connections allows the user to connect the inputs of the mi::ICompound_shader_class to the inputs of any node, connect the outputs of any node to the inputs of any other node, and the outputs of any node to the outputs of the mi::ICompound_shader_class. (All of this is, of course, subject to typing restrictions.) The details of using the interface mi::IShader_connections to connect together these small programs is covered in the mi::ICompound_shader_class documentation.

mi::IShader_graph

The next class we will examine is mi::IShader_graph. Like an mi::IShader an mi::IShader_graph instance can be thought of as a small program. It takes inputs, processes these inputs, and exports the results. Like an mi::IShader the inputs are named and can be of a wide variety of types. (The full set of allowed input types can be found here Types.) Similarly, the exported results are named and can also be of a wide variety of types. An mi::IShader_graph instance also encapsulates a small program that processes the inputs resulting in exported results. This small program and more details on the exported results will be given as we examine the next class mi::IShader_graph_class.

mi::IShader_graph_class

An mi::IShader_graph_class instance can be thought of as an instance specifying of a set of mi::IShader_graph instances with common characteristics and behaviors. The relation between an mi::IShader_graph_class instance and its set of mi::IShader_graph instances is analogous to the relation between a C++ class and its set of instances.

Like an mi::ICompound_shader_class an mi::IShader_graph_class can be used in two distinct ways. First, it can be used to examine a shader graph class stored in the database. Second, it can be used to programmatically create a simple program, in fact an entire shader graph class, at runtime. As the simpler of these two use cases is the first, we begin with it.

Examination of Shader Graph Classes

Like a compound shader class, a shader graph class can be loaded, through various means, into the database. These include importing ".mi" files, importing MetaSL files, and programmatic creation and storing of such a shader graph class. If one of the previous channels is used to load a shader graph class into the database, then the question is: How does the user examine this shader graph class? The answer, using mi::IShader_graph_class.

Through mi::neuraylib::ITransaction::access() the user can access a shader graph class in the database. An mi::IShader_graph_class allows the user to examine characteristics of a shader graph class. Specifically, an mi::IShader_graph_class allows the user to examine the inputs, nodes, and exports present in the shader graph class as well as the connections between such elements. Examination of the inputs, nodes, and exports is done through the mi::IShader_graph_class interface, while examination of the connections between these inputs, nodes, and exports is done through the interface mi::IShader_connections which mi::IShader_graph_class implements.

Programmatic Creation of a Shader Graph Class

As mentioned previously, an mi::IShader_graph_class can be used to programmatically create a shader graph class at runtime. To create such a shader graph class a user must specify four pieces of information: inputs, a name, a simple program, and exports. Next, we will examine how each of these four pieces of information is specified when using mi::IShader_graph_class to programmatically create a shader graph class.

Inputs

To specify the inputs of a programmatically created a shader graph class the user must specify a set of names, types, and default values. As in the case of an mi::ICompound_shader_class, all of this data is specified through an mi::IAttribute_container instance. The names of its attributes are the names of the inputs. The types of its attributes are the types of the inputs, and the values of its attributes are the default values of the inputs.

This mi::IAttribute_container instance is then used to create an mi::IShader_graph_class instance. (The details of this are covered in the mi::IShader_graph_class documentation.) This newly created mi::IShader_graph_class then represents a shader graph class with the specified inputs.

Name

The name a user needs to specify is simply the name of the resulting shader graph class. This is the name under which the mi::IShader_graph_class is stored in the database.

Simple Program

The most complicated step is creating the simple program. As in the mi::ICompound_shader_class case, creating this simple program is done by connecting together several other small programs. The output of one small program is used as the input of a second small program, the output of this second small program is used as the input to a third small program....

Creating these small programs, often called nodes, is accomplished through the mi::IShader_graph_class interface. Each node is an mi::IShader or mi::IShader_graph instance and is added to the mi::IShader_graph_class simple program using the method mi::IShader_graph_class::add_node().

Connecting together these small programs is done through the interface mi::IShader_connections which mi::IShader_graph_class implements. The interface mi::IShader_connections allows the user to connect the inputs of the mi::IShader_graph_class to the inputs of any node and to connect the outputs of any node to the inputs of any other node. (This is, of course, subject to typing restrictions.) Using the interface mi::IShader_connections to connect together these small programs is covered in detail in the mi::IShader_graph_class documentation.

Exports

The exports of an mi::IShader_graph_class are similar the the outputs of an mi::ICompound_shader_class, yet different in some very important ways. An output of an mi::ICompound_shader_class is an attribute, where as an export of an mi::IShader_graph_class is an entire node. Thus, an export is an entire mi::IShader or mi::IShader_graph instance.

The distinction between a normal node and an export node is made through the manner in which the export node is added. A normal node is added through a call to mi::IShader_graph_class::add_node(). However, an export node is added through a call to mi::IShader_graph_class::add_export().

Like a normal node, the interface mi::IShader_connections can be used to connect the inputs of the mi::IShader_graph_class to the inputs of any export node and to connect the outputs of any non-export node to the inputs of any export node, subject to type restrictions. Note, however, the output(s) of an export node can not be connected to any other nodes. The output(s) of an export node are viewed as the output of running the corresponding mi::IShader_graph. Hence, they should not be connected to anything.