Classes

ExposureMaterialControl: How to Implement

Classes

class   ExposureMaterialControl
  This is the inteface class to implement in order to support exposure controls. More...
class   ExposureMaterialControlDesc
  This implementation of ClassDesc is to be used to implement the ExposureMaterialControl interface. More...
class   ExposureMaterialControlImp< T, B >
  This class implements the virtual methods in ExposureMaterialControl. More...
class   AddExposureMaterialControl< B >
  This class implements a small hack to get around issues in the VS2005 compiler. More...

Detailed Description

Group Classes:
Class ExposureMaterialControl, Class ExposureMaterialControlImp, Class ExposureMaterialControlDesc, Class AddExposureMaterialControl
See also:
Class Mtl, Class ClassDesc2
Description
These classes are helpers for material developers that want to add ExposureMaterialControl to a material.
Implementation:
Step 1: Derive the Material from both ExposureMaterialControl and ExposureMaterialControlImp. There are two ways to do this depending on whether you are using a common base class for several materials, or whether you are implementing a single material.

If you are implementing a single material that was:
     class MyMaterial : public Mtl
the do this:
     class MyMaterial : public ExposureMaterialControlImp<
                                   MyMaterial,
                                   AddExposureMaterialControl<Mtl> >
this derives MyMaterial pretty directly from both ExposureMaterialControlImp and ExposureMaterialControl.

If you are implementing several materials from a common base class:
     class MyBase : public Mtl
     class MyMaterial1 : public MyBase
     class MyMaterial2 : public MyBase
then do this:
     class MyBase : public Mtl, public ExposureMaterialControl
     class MyMaterial1 : public ExposureMaterialControlImp<MyMaterial1, MyBase>
     class MyMaterial2 : public ExposureMaterialControlImp<MyMaterial2, MyBase>
Each material you want to add ExposureMaterialControl to that has a class descriptor should be derived from ExposureMaterialControlImp separately. This allows MAX Script to connect up the interface with the class.

Step 2: Add these lines to each material class that you derive from ExposureMaterialControlImp:
     typedef ExposureMaterialControlImp<MyMaterial,
                 AddExposureMaterialControl<Mtl> > BaseClass;
     static ExposureMaterialControlDesc msExpMtlControlDesc;
or
     typedef ExposureMaterialControlImp<MyMaterial1, MyBase> BaseClass;
     static ExposureMaterialControlDesc msExpMtlControlDesc;
Chose the typedef based on the base class of your material.

The definition of msExpMtlControlDesc should look like:
     ExposureMaterialControlDesc MyMaterial::msExpMtlControlDesc(myMaterialClassDesc,
         IDS_EXPOSURE_MATERIAL_CONTROL,
         IDS_NO_EXPOSURE,
         IDS_INVERTSELFILLUM,
         IDS_INVERTREFLECT,
        IDS_INVERTREFRACT
     );
myMaterialClassDesc is the class descriptor that is used to create MyMaterial. The rest of the parameters are string ids in your resource file:

IDS_EXPOSURE_MATERIAL_CONTROL is the desription string for the interface and should be a localization of Exposure Material Control.
IDS_NO_EXPOSURE is the name of the No Exposure Control property.
IDS_INVERTSELFILLUM is the name of the Exposure Control Invert SelfIllum property.
IDS_INVERTREFLECT is the name of the Exposure Control Invert Reflect property.
IDS_INVERTREFRACT is the name of the Exposure Control Invert Refract property.

Step 3: Modify LocalRequirements, Requirements and GetRequirements. Or isNoExposure() in with your other material requirement flags. If the class is a material always modify LocalRequirements and also modify Requirements if you override it and don't call LocalRequirements to get the local flags. In shaders for StdMat2 you need to modify GetRequirements.

Step 4: Modify GetInterface. If you are already using GetInterface(Interface_Id id), then you need to call the ExposureMaterialControlImp implementation when you get and id that you don't recognize. If you setup the BaseClass typedef use:
     return BaseClass::GetInterface(id);
Step 5: Modify your save and load code to save and load the values in the interface. Save and Load methods are provided. You should Save the interface in a separate chunk.

Step 6: Modify your Shade method. This is an example of how you can do that.

    if (sc.globContext != NULL && sc.globContext->pToneOp != NULL) {
         if (isInvertSelfIllum())
             sc.globContext->pToneOp->RGBToScaled(selfIllumOut);
         if (isInvertReflect())
             sc.globContext->pToneOp->RGBToScaled(reflIllumOut);
         if (isInvertRefract())
             sc.globContext->pToneOp->RGBToScaled(transIllumOut);
     }
Step 7: Modify the Clone method for the material to copy the interface values to the cloned material. I used:
      mnew->ExposureMaterialControl::operator=(*this);