shade (lx_shade.hpp)

From The Foundry MODO SDK wiki
Jump to: navigation, search
There are security restrictions on this page


Introduction

Shading is a complex operation used for rendering and display. This module implements the texture layer items which are the building blocks of shaders. It also implements the texture layer interfaces and the evaluation pathways needed for mesh partitioning, display and rendering.

Value Textures

A value texture is a simple type of texture, also called procedural although that's incorrect since value textures can come from data sources other than algorithms. A value texture provides a scalar, color or vector value at every point on a surface.

SetupChannels
This is called when the item type is first defined to determine the channels that should be added to the item definition.
LinkChannels
This is called with an ILxEvaluation interface and the texture should add any channels that it wants to read.
ReadChannels
This is called with an ILxAttributes interface so the texture can read any of the values that it needs at the current time. The values read should be cached (along with any other needed scratch space) to an allocated block of data returned indirectly.
Customize
After channels are read the value texture can request surface features and sample vector packets. No guarantees.
Evaluate
This is called during rendering for every sample where the value texture applies. The function should use the spot parameters of the sample in the input packet, and write results to the output packet.
Cleanup
Frees the data block allocated by ReadChannels() method.

(1) SDK: ILxValueTexture1 interface
         LXxMETHOD( LxResult,
 SetupChannels) (
         LXtObjectID              self,
         LXtObjectID              addChan);
 
         LXxMETHOD( LxResult,
 LinkChannels) (
         LXtObjectID              self,
         LXtObjectID              eval,
         LXtObjectID              item);
 
         LXxMETHOD( LxResult,
 ReadChannels) (
         LXtObjectID              self,
         LXtObjectID              attr,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Customize) (
         LXtObjectID              self,
         LXtObjectID              custom,
         void                   **ppvData);
 
         LXxMETHOD( void,
 Evaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         LXpTextureOutput        *tOut,
         void                    *data);
 
         LXxMETHOD( void,
 Cleanup) (
         LXtObjectID              self,
         void                    *data);

The new and current version of the interface support the 'LinkSampleChannels', 'IsSampleDriven' and 'Setup' methods.

LinkSampleChannels
This is called with an ILxEvaluation/ILxAttributes interface and the texture should add any channels that it wants to read on a per-sample basis. This method should also be used to store a copy of the CLxUser_Attributes derived from the nodalEtor passed in. If your 'evalData' is derived from the CLxSampleRendData user class, then you can simply perform an 'rd->at.set (nodalEtor)' as shown in the example below.
IsSampleDriven
For efficiency, it helps if the shading system knows if a texture has any channels that are per-sample driven. If not, much of the per-sample setup can be skipped, making rendering faster. This will be called to ask if the texture is in any way sample-driven for the current pass. This can be determined by using the CLxUser_NodalService::AnyDrivenChans() method.
Setup
This is called when a new shader slice is created. It may be called multiple times when setting up a render or preview - once for each new slice.

(2) SDK: ILxValueTexture interface
         LXxMETHOD( LxResult,
 SetupChannels) (
         LXtObjectID              self,
         LXtObjectID              addChan);
 
         LXxMETHOD( LxResult,
 LinkChannels) (
         LXtObjectID              self,
         LXtObjectID              eval,
         LXtObjectID              item);
 
         LXxMETHOD( LxResult,
 LinkSampleChannels) (
         LXtObjectID              self,
         LXtObjectID              nodalEtor,
         LXtObjectID              item,
         int                     *idx);
 
         LXxMETHOD( LxResult,
 ReadChannels) (
         LXtObjectID              self,
         LXtObjectID              attr,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Customize) (
         LXtObjectID              self,
         LXtObjectID              custom,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Setup) (
         LXtObjectID              self,
         void                    *data);
 
         LXxMETHOD( void,
 Evaluate) (
         LXtObjectID              self,
         LXtObjectID              etor,
         int                     *idx,
         LXtObjectID              vector,
         LXpTextureOutput        *tOut,
         void                    *data);
 
         LXxMETHOD( void,
 Cleanup) (
         LXtObjectID              self,
         void                    *data);
 
         LXxMETHOD( int,
 IsSampleDriven) (
         LXtObjectID              self,
         int                     *idx);

Empty ValueTexture Python user class.

(3) PY: ValueTexture method
 pass

This interface is passed to the Customize() method.

(4) SDK: ILxValueTextureCustom interface
         LXxMETHOD( LxResult,
 AddFeature) (
         LXtObjectID              self,
         LXtID4                   type,
         const char              *name);
 
         LXxMETHOD( LxResult,
 AddPacket) (
         LXtObjectID              self,
         const char              *name);

(5) SDK: Declarations
 #define LXu_VALUETEXTURE1       "CA0E3524-6F82-44B8-AAC9-DC258F548C02"
 #define LXa_VALUETEXTURE1       "valueTexture" 
 #define LXu_VALUETEXTURE        "9A2DD931-F442-488a-8C6A-AF6BDDC30B32"
 #define LXa_VALUETEXTURE        "valueTexture2"
 #define LXu_VALUETEXTURECUSTOM  "DE3298A6-1607-4338-B061-185528E6FB51"

(6) User Class: ValueTextureCustom method

Empty ValueTextureCustom Python user class.

(7) PY: ValueTextureCustom method
 pass

The following is a stripped down example structure of a value texture:

(8) Using CLxSampleRendData
 class CTestTexture : public CLxImpl_ValueTexture
 {
         CLxUser_NodalService    nodalSvc;
         LXtSampleIndex          idx_someData;
 
         class RendData {
             public:
                 double          someLayerData;
         };
 
         // for efficiency, let shading system know if any channels are sample driven.
         // pass the address of our first channel index, and their count
         int vtx_IsSampleDriven (int *idx)
         {
                 return nodalSvc.AnyDrivenChannels (&idx[idx_someData.chan], 1);
         }
 
         LxResult vtx_LinkChannels (
                 ILxUnknownID             eval,
                 ILxUnknownID             item)
         {
                 CLxUser_Evaluation       ev (eval);
                 CLxUser_Item             it (item);
 
                 // get the channel indexes for each of your item channels
                 idx_someData.chan  = it.ChannelIndex (CHANs_SomeChannel);
 
                 // add the channels to the per-layer evaluator
                 idx_someData.layer = ev.AddChan (item, idx_someData.chan);
 
                 tin_offset = pkt_service.GetOffset (LXsCATEGORY_SAMPLE, LXsP_TEXTURE_INPUT);
 
                 return LXe_OK;
         }
 
         LxResult vtx_ReadChannels (
                 ILxUnknownID             attr,
                 void                   **ppvData)
         {
                 RendData                *rd = new RendData;
 
                 CLxUser_Attributes       at (attr);
 
                 // read your per-layer and initial per-sample data here
                 rd->someLayerData = at.Float (idx_someData.layer);
 
                 ppvData[0] = rd;
                 return LXe_OK;
         }
 
         LxResult vtx_LinkSampleChannels (
                 ILxUnknownID             nodalEtor,
                 ILxUnknownID             item,
                 int                     *idx)
         {
                 // add the per-sample channels to the per-sample evaluator
                 nodalSvc.AddSampleChan (eval, item, idx_someData.chan, idx, LXfECHAN_READ);
 
                 return LXe_OK;
         }
 
         void vtx_Evaluate (
                 ILxUnknownID             etor,
                 int                     *idx,
                 ILxUnknownID             vector,
                 LXpTextureOutput        *tOut,
                 void                    *data)
         {
                 RendData                *rd              = (RendData *) data;
 
                 // read you sample-specific data here
                 float                    someSampleValue = nodalSvc.GetFloat (etor, idx, idx_someData.chan, rd->someLayerData);
 
                 // use the value in your shader
         }
 };

Component Shaders

A component shader is a simple type of shader that sets the shading component and output packets.

SetupChannels
This is called when the item type is first defined to determine the channels that should be added to the item definition.
LinkChannels
This is called with an ILxEvaluation interface and the texture should add any channels that it wants to read.
ReadChannels
This is called with an ILxAttributes interface so the texture can read any of the values that it needs at the current time. The values read should be cached (along with any other needed scratch space) to an allocated block of data returned indirectly.
Customize
After channels are read the value texture can request surface features and sample vector packets. No guarantees.
Evaluate
This is called during rendering for every sample where the shader applies. The function gets the raycast object and the shade component and output packets that it can alter.
SetShadeFlags
This is called before rendering and allows a component shader to set the shading flags, which allows it do things like be transparent to shadow rays or be double sided, or set a light linking group.
SetOpaque
This allows the shader to override its "opaqueness". For shaders that use other shaders as inputs, such as the cel and halftone shader, it is necessary that they are not opaque.
CustomPacket
This allows the shader to specify a custom packet it GETS.
Cleanup
Frees the data block allocated by ReadChannels() method.

(9) SDK: ILxCompShader1 interface
         LXxMETHOD( LxResult,
 SetupChannels) (
         LXtObjectID              self,
         LXtObjectID              addChan);
 
         LXxMETHOD( LxResult,
 LinkChannels) (
         LXtObjectID              self,
         LXtObjectID              eval,
         LXtObjectID              item);
 
         LXxMETHOD( LxResult,
 ReadChannels) (
         LXtObjectID              self,
         LXtObjectID              attr,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Customize) (
         LXtObjectID              self,
         LXtObjectID              custom,
         void                   **ppvData);
 
         LXxMETHOD( void,
 Evaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         LXtObjectID              rayObj,
         LXpShadeComponents      *sCmp,
         LXpShadeOutput          *sOut,
         void                    *data);
 
         LXxMETHOD( LxResult,
 SetShadeFlags) (
         LXtObjectID              self,
         LXpShadeFlags           *sFlg);
 
         LXxMETHOD( LxResult,
 SetOpaque) (
         LXtObjectID              self,
         int                     *opaque);
 
         LXxMETHOD( LxResult,
 CustomPacket) (
         LXtObjectID              self,
         const char              **packet);
 
         LXxMETHOD( void,
 Cleanup) (
         LXtObjectID              self,
         void                    *data);

(10) SDK: Declarations
 #define LXu_COMPSHADER1         "06717e9d-610d-439f-935b-af0805827ede"
 #define LXa_COMPSHADER1         "compShader"

The new and current version of the interface support the 'Flags' method.

Flags
This returns some of the LXfSHADERFLAGS_ to describe basic shader behaviors.

(11) SDK: ILxCompShader interface
         LXxMETHOD( LxResult,
 SetupChannels) (
         LXtObjectID              self,
         LXtObjectID              addChan);
 
         LXxMETHOD( LxResult,
 LinkChannels) (
         LXtObjectID              self,
         LXtObjectID              eval,
         LXtObjectID              item);
 
         LXxMETHOD( LxResult,
 ReadChannels) (
         LXtObjectID              self,
         LXtObjectID              attr,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Customize) (
         LXtObjectID              self,
         LXtObjectID              custom,
         void                   **ppvData);
 
         LXxMETHOD( void,
 Evaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         LXtObjectID              rayObj,
         LXpShadeComponents      *sCmp,
         LXpShadeOutput          *sOut,
         void                    *data);
 
         LXxMETHOD( LxResult,
 SetShadeFlags) (
         LXtObjectID              self,
         LXpShadeFlags           *sFlg);
 
         LXxMETHOD( LxResult,
 SetOpaque) (
         LXtObjectID              self,
         int                     *opaque);
 
         LXxMETHOD( LxResult,
 CustomPacket) (
         LXtObjectID              self,
         const char              **packet);
 
         LXxMETHOD( void,
 Cleanup) (
         LXtObjectID              self,
         void                    *data);
 
         LXxMETHOD( int,
 Flags) (
         LXtObjectID              self);

(12) SDK: Declarations
 #define LXu_COMPSHADER          "371e8b57-3a1e-444b-91f8-5e43c75bf1cb"
 #define LXa_COMPSHADER          "compShader2"

Empty CompShader Python user class.

(13) PY: CompShader method
 pass

Custom Materials

A custom material is a more advanced type of shader. It can change material attributes AND perform its own shading. The custom material looks like a material item in the shader tree but it also has an implicit shader that is evaluated after the base shader. Because it is a material item it can textured, the texturing works by defining a custom packet (in which the texturable attributes are stored) and number of texture effects, one for each texturable attribute. The easiest way to add such effects is through the ILxPacketEffect.

SetupChannels
This is called when the item type is first defined to determine the channels that should be added to the item definition.
LinkChannels
This is called with an ILxEvaluation interface and the texture should add any channels that it wants to read.
ReadChannels
This is called with an ILxAttributes interface so the texture can read any of the values that it needs at the current time. The values read should be cached (along with any other needed scratch space) to an allocated block of data returned indirectly.
Customize
After channels are read the value texture can request surface features and sample vector packets. No guarantees.
MaterialEvaluate
This is called during rendering for every sample where the material applies.
ShaderEvaluate
This is called during rendering for every sample where the material applies. The function gets the raycast object and the shade component and output packets that it can alter.
SetShadeFlags
This is called before rendering and allows a component shader to set the shading flags, which allows it do things like be transparent to shadow rays or be double sided, or set a light linking group.
SetBump
This is called before rendering and allows a component shader to set its own bump amplitude, so it is evaluate for bump mapping.
SetDisplacement
This works like set bump, but for displacement height.
SetOpaque
This allows the shader to override its "opaqueness". For shaders that use other shaders as inputs, such as the cel and halftone shader, it is necessary that they are not opaque.
SetSmoothing
This allows the shader to set its material smoothing amount and angle.
CustomPacket
This allows the shader to specify a custom packet it SETS.
Cleanup
Frees the data block allocated by ReadChannels() method.
UpdatePreview
This allows the shader to specify the update flags it might trigger for Preview.

(14) SDK: ILxCustomMaterial1 interface
         LXxMETHOD( LxResult,
 SetupChannels) (
         LXtObjectID              self,
         LXtObjectID              addChan);
 
         LXxMETHOD( LxResult,
 LinkChannels) (
         LXtObjectID              self,
         LXtObjectID              eval,
         LXtObjectID              item);
 
         LXxMETHOD( LxResult,
 ReadChannels) (
         LXtObjectID              self,
         LXtObjectID              attr,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Customize) (
         LXtObjectID              self,
         LXtObjectID              custom,
         void                   **ppvData);
 
         LXxMETHOD( void,
 MaterialEvaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         void                    *data);
 
         LXxMETHOD( void,
 ShaderEvaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         LXtObjectID              rayObj,
         LXpShadeComponents      *sCmp,
         LXpShadeOutput          *sOut,
         void                    *data);
 
         LXxMETHOD( LxResult,
 SetShadeFlags) (
         LXtObjectID              self,
         LXpShadeFlags           *sFlg);
 
         LXxMETHOD( LxResult,
 SetBump) (
         LXtObjectID              self,
         float                   *bumpAmplitude,
         int                     *clearBump);
 
         LXxMETHOD( LxResult,
 SetDisplacement) (
         LXtObjectID              self,
         float                   *dispDist);
 
         LXxMETHOD( LxResult,
 SetOpaque) (
         LXtObjectID              self,
         int                     *opaque);
 
         LXxMETHOD( LxResult,
 SetSmoothing) (
         LXtObjectID              self,
         double                  *smooth,
         double                  *angle);
 
         LXxMETHOD( LxResult,
 CustomPacket) (
         LXtObjectID              self,
         const char              **packet);
 
         LXxMETHOD( void,
 Cleanup) (
         LXtObjectID              self,
         void                    *data);
 
         LXxMETHOD( LxResult,
 UpdatePreview) (
         LXtObjectID              self,
         int                      chanIdx,
         int                     *flags);

(15) SDK: Declarations
 #define LXu_CUSTOMMATERIAL1             "d0c4106c-dfd5-4a58-ad48-45b50ae63f59"
 #define LXa_CUSTOMMATERIAL1             "customMaterial"

The previous version of the interface support the 'Flags' method.

Flags
This returns some of the LXfSHADERFLAGS_ to describe basic shader behaviors.

(16) SDK: ILxCustomMaterial2 interface
         LXxMETHOD( LxResult,
 SetupChannels) (
         LXtObjectID              self,
         LXtObjectID              addChan);
 
         LXxMETHOD( LxResult,
 LinkChannels) (
         LXtObjectID              self,
         LXtObjectID              eval,
         LXtObjectID              item);
 
         LXxMETHOD( LxResult,
 ReadChannels) (
         LXtObjectID              self,
         LXtObjectID              attr,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Customize) (
         LXtObjectID              self,
         LXtObjectID              custom,
         void                   **ppvData);
 
         LXxMETHOD( void,
 MaterialEvaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         void                    *data);
 
         LXxMETHOD( void,
 ShaderEvaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         LXtObjectID              rayObj,
         LXpShadeComponents      *sCmp,
         LXpShadeOutput          *sOut,
         void                    *data);
 
         LXxMETHOD( LxResult,
 SetShadeFlags) (
         LXtObjectID              self,
         LXpShadeFlags           *sFlg);
 
         LXxMETHOD( LxResult,
 SetBump) (
         LXtObjectID              self,
         float                   *bumpAmplitude,
         int                     *clearBump);
 
         LXxMETHOD( LxResult,
 SetDisplacement) (
         LXtObjectID              self,
         float                   *dispDist);
 
         LXxMETHOD( LxResult,
 SetOpaque) (
         LXtObjectID              self,
         int                     *opaque);
 
         LXxMETHOD( LxResult,
 SetSmoothing) (
         LXtObjectID              self,
         double                  *smooth,
         double                  *angle);
 
         LXxMETHOD( LxResult,
 CustomPacket) (
         LXtObjectID              self,
         const char              **packet);
 
         LXxMETHOD( void,
 Cleanup) (
         LXtObjectID              self,
         void                    *data);
 
         LXxMETHOD( LxResult,
 UpdatePreview) (
         LXtObjectID              self,
         int                      chanIdx,
         int                     *flags);
 
         LXxMETHOD( int,
 Flags) (
         LXtObjectID              self);

(17) SDK: Declarations
 #define LXu_CUSTOMMATERIAL2             "64e2dd96-ff7f-4c9b-967e-24dec83bfb72"
 #define LXa_CUSTOMMATERIAL2             "customMaterial2"

The new and current version of the interface support the 'LinkSampleChannels' and 'IsSampleDriven' methods.

LinkSampleChannels
This is called with an ILxEvaluation/ILxAttributes interface and the texture should add any channels that it wants to read on a per-sample basis. This method should also be used to store a copy of the CLxUser_Attributes derived from the nodalEtor passed in. If your 'evalData' is derived from the CLxSampleRendData user class, then you can simply perform an 'rd->at.set (nodalEtor)' as shown in the example below.
IsSampleDriven
For efficiency, it helps if the shading system knows if a texture has any channels that are per-sample driven. If not, much of the per-sample setup can be skipped, making rendering faster. This will be called to ask if the texture is in any way sample-driven for the current pass. This can be determined by using the CLxUser_NodalService::AnyDrivenChans() method.

(18) SDK: ILxCustomMaterial interface
         LXxMETHOD( LxResult,
 SetupChannels) (
         LXtObjectID              self,
         LXtObjectID              addChan);
 
         LXxMETHOD( LxResult,
 LinkChannels) (
         LXtObjectID              self,
         LXtObjectID              eval,
         LXtObjectID              item);
 
         LXxMETHOD( LxResult,
 LinkSampleChannels) (
         LXtObjectID              self,
         LXtObjectID              nodalEtor,
         LXtObjectID              item,
         int                     *idx);
 
         LXxMETHOD( int,
 IsSampleDriven) (
         LXtObjectID              self,
         int                     *idx);
 
         LXxMETHOD( LxResult,
 ReadChannels) (
         LXtObjectID              self,
         LXtObjectID              attr,
         void                   **ppvData);
 
         LXxMETHOD( LxResult,
 Customize) (
         LXtObjectID              self,
         LXtObjectID              custom,
         void                   **ppvData);
 
         LXxMETHOD( void,
 MaterialEvaluate) (
         LXtObjectID              self,
         LXtObjectID              etor,
         int                     *idx,
         LXtObjectID              vector,
         void                    *data);
 
         LXxMETHOD( void,
 ShaderEvaluate) (
         LXtObjectID              self,
         LXtObjectID              vector,
         LXtObjectID              rayObj,
         LXpShadeComponents      *sCmp,
         LXpShadeOutput          *sOut,
         void                    *data);
 
         LXxMETHOD( LxResult,
 SetShadeFlags) (
         LXtObjectID              self,
         LXpShadeFlags           *sFlg);
 
         LXxMETHOD( LxResult,
 SetBump) (
         LXtObjectID              self,
         float                   *bumpAmplitude,
         int                     *clearBump);
 
         LXxMETHOD( LxResult,
 SetDisplacement) (
         LXtObjectID              self,
         float                   *dispDist);
 
         LXxMETHOD( LxResult,
 SetOpaque) (
         LXtObjectID              self,
         int                     *opaque);
 
         LXxMETHOD( LxResult,
 SetSmoothing) (
         LXtObjectID              self,
         double                  *smooth,
         double                  *angle);
 
         LXxMETHOD( LxResult,
 CustomPacket) (
         LXtObjectID              self,
         const char             **packet);
 
         LXxMETHOD( void,
 Cleanup) (
         LXtObjectID              self,
         void                    *data);
 
         LXxMETHOD( LxResult,
 UpdatePreview) (
         LXtObjectID              self,
         int                      chanIdx,
         int                     *flags);
 
         LXxMETHOD( int,
 Flags) (
         LXtObjectID              self);

(19) SDK: Declarations
 #define LXu_CUSTOMMATERIAL              "B6297ECF-CFE9-4923-A70C-DB87279B0411"
 #define LXa_CUSTOMMATERIAL              "customMaterial3"

Empty CustomMaterial Python user class.

(20) PY: CustomMaterial method
 pass