/*============================================================================== file: imrShaderTranslation.h author: Daniel Levesque created: 10feb2003 description: Defition of the mental ray shader translation interface. modified: [dl] 28 April 2004. Added advanced translation of parameters, incremented interface IDs to distinguish between the old (MAX 6) interface and the new (MAX 7) interface. © 2004 Autodesk ==============================================================================*/ #ifndef _IMRSHADERTRANSLATION_H_ #define _IMRSHADERTRANSLATION_H_ #include #include #include class imrShader; class imrShaderCreation; class Texmap; class imrMaterialCustAttrib; #define IMRSHADERTRANSLATION_INTERFACE_ID Interface_ID(0x1c396abd, 0x5f964e0c) #define IMRMTLPHENTRANSLATION_INTERFACE_ID Interface_ID(0x5f970a9c, 0x65e75de4) #define IMRGEOMSHADERTRANSLATION_INTERFACE_ID Interface_ID(0x31882a12, 0x2102a73) #define IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID Interface_ID(0x17a76fd6, 0x5ab32bcd) //============================================================================== // class imrShaderTranslation // // Interface to be implemented by the MAX plugin which translates to a mental // ray shader. Materials do not use this interface. Instead, they use the // imrMaterialTranslation interface. // // For example: // A 3rd party implements a MAX texmap pluggin for a brick effect. By default, // the mental ray translator does not support this texture and will be unable to // render it. If the 3rd party has also implemented a mental ray shader for this // effect, then this interface may be used to tell the mental ray translator // which shader is to be used. //============================================================================== class imrShaderTranslation : public BaseInterface { public: // List of requirements that may be queried on this translation interface enum Requirement { // This shader requires tangent basis vectors. // The tangent basis vectors will be translated for the object on which // this shader is used. // Return true if the vectors are needed, false otherwise. // The 't', and 'valid' parameters are not used. // The 'arg' variable is a pointer to an 'int', to which to map channel // to be used should be assigned. kReq_TangentBasisVectors = 0, }; struct AdditionalDependency { AdditionalDependency(ReferenceTarget* rt, bool assign = true) : refTarg(rt), assignAsChild(assign) {} // The reference target that is to be translated as a dependency ReferenceTarget* refTarg; // This should be true in all but exceptional cases where the translator // could run into potential problems with reference looping. bool assignAsChild; }; typedef Tab AdditionalDependencyTable; // Called by the mental ray translator to get the mental ray shader which // is to be used. The method may return a shader which was already created, // or create a new one via the imrShaderCreation interface. // This method will never be called more than once per render. virtual imrShader* GetMRShader(imrShaderCreation& shaderCreation) = 0; // This may be called when rendering is finished to discard the mental ray shaders. // If the derived class holds a reference to the shader created by the call to GetMRShader(), // then it may release that reference in this call. This is not an obligation, // but it can free memory and/or resolve issues such as the "Make Unique" // button always being enabled in the material editor. virtual void ReleaseMRShader() = 0; // Should the translator automatically copy the parameters based on the param // block 2 system? // NOTE: The metnal ray translator will correctly handle automatic translation // of the parameters IF the 3rd party plugin's parameters all use the ParamBlock2 // system AND if the names & types of the parameters match the shader definition // (names are not case sensitive). // If this returns 'true', then the automatic translation will take place // after the call to TranslateParameters(). virtual bool NeedsAutomaticParamBlock2Translation() = 0; // Translates the parameters of this plugin to the mental ray shader. Called // for the first frame, and for each subsequent frame that is not in the // validity interval. The method must store the validity interval of the // translated parameters in 'valid'. // **The parameters must be stored in the shader at time 0. virtual void TranslateParameters(imrShader* shader, TimeValue t, Interval& valid) = 0; // If this class needs any ReferenceTarget to be translated, but which are not // sub-references or within a parameter block of the plugin class, then these // ReferenceTarget's may be given here. The mental ray translator will automatically // create a dependency between the plugin and the given ReferenceTarget's. virtual void GetAdditionalReferenceDependencies(AdditionalDependencyTable& refTargets) = 0; // This method is meant for advanced users for whom TranslateParameters() either is not // sufficient or causes performance issues. // Whereas TranslateParameters() translates parameters using the ParamBlock2 system, // this method is used to send parameters directly to mental ray, bypassing the ParamBlock2 system. // If TranslateParameters() is enough for you, or if you do not understand why you would need // this advanced translation method, then do not implement this method. // See the documentation of class imrAdvancedTranslation for more details. virtual void TranslateParameters_Advanced(imrAdvancedTranslation& advancedTranslation, TimeValue t, Interval& valid); // This method is meant to query specific requirements from the translation interface. // Look at the documentation for each requirement flag for more information. // Note that 'arg' may or may not be used, depending on the requirement. virtual bool HasRequirement(Requirement requirement, TimeValue t, Interval& valid, void* arg = NULL); // -- from BaseInterface virtual Interface_ID GetID(); }; inline imrShaderTranslation* GetIMRShaderTranslation(InterfaceServer* iserver) { return static_cast(iserver->GetInterface(IMRSHADERTRANSLATION_INTERFACE_ID)); } //============================================================================== // class imrMaterialPhenomenonTranslation // // A material plugin that wishes to have a custom translation to a material // phenomenon must derive from this interface. The interface is identical to // imrShaderTranslation, except that: // - the interface ID is different // - only material phenomenon may be created via the imrShaderCreation interface. // // SPECIAL CASE: Using the mental ray material directly. // To translate a material to a mental ray material directly, without actually // using a phenomenon of your own, create an instance of the phenomenon called // "max_default_mtl_phen". Even though this is a phenomenon, it is not translated // as one, but instead it is translated as a material. NOTE, however, that this // particular phenomenon does NOT support the automatic ParamBlock2 translation, // so NeedsAutomaticParamBlock2Translation() should return false. //============================================================================== class imrMaterialPhenomenonTranslation : public imrShaderTranslation { public: // Returns whether this material supports the 'mental ray connection' custom // attributes rollup. This rollup allows users to override any of the 10 shaders // on the material. Note that only materials that translate to the default // material phenomenon ("max_default_mtl_phen") may return true here, since // the translator needs that phenomenon to translate the shader overrides. // If the material does not return the default material phenomenon but still // wishes to support the overrides, then it will have to do so itself. virtual bool SupportsMtlOverrides() = 0; // Initializes the mtl overrides custom attribute, if necessary. Only called // if SupportsMtlOverrides() returned true. // All that this function should do is enable/disable the shader locks of the custom // attribute. // A material may simply do nothing here, or it may disable some of the shader locks // that don't apply. virtual void InitializeMtlOverrides(imrMaterialCustAttrib* mtlCustAttrib) = 0; // -- from BaseInterface virtual Interface_ID GetID(); }; inline imrMaterialPhenomenonTranslation* GetIMRMaterialPhenomenonTranslation(InterfaceServer* iserver) { return static_cast(iserver->GetInterface(IMRMTLPHENTRANSLATION_INTERFACE_ID)); } //============================================================================== // class imrGeomShaderTranslation // // A geometry object plugin that wishes to have a custom translation to a mental // ray shader must derive from this interface. The interface is used to retrieve // an instance of the geometry shader to be used. // Derive your GeomObject or ShapeObject from this class to have it translated // to a geometry shader. //============================================================================== class imrGeomShaderTranslation : public BaseInterface { public: // Returns the geometry shader to be used with this object. The ReferenceTarget // returned by this method should be a Texmap plugin that translates to a mental // ray geometry shader. You may need to implement your own Texmap plugin that // uses the imrShaderTranslation interface to translate itself to a mental ray // shader. virtual ReferenceTarget* GetGeomShader() = 0; // Returns a scale for the geometry shader, to be applied on the instance transform. // This is useful in the case that a geometry shader produces objects of a fixed // size (e.g. the mib_geo_* shaders), but you still want to be able to expose // a size parameter in the UI. // If you don't care about scaling, just return a scale of (1,1,1). virtual void GetScale(Point3& scale) = 0; // -- from BaseInterface virtual Interface_ID GetID(); }; inline imrGeomShaderTranslation* GetIMRGeomShaderTranslation(InterfaceServer* iserver) { return static_cast(iserver->GetInterface(IMRGEOMSHADERTRANSLATION_INTERFACE_ID)); } //============================================================================== // class imrShaderCreation // // Interface used to create new shader instances. // // A reference to this interface is passed to the "GetMRShader()" method of the // imrShaderTranslation interface. If one tries to create a shader which does // nto exist, CreateShader() outputs an error in the mental ray message window // and returns NULL. // // IMPORTANT: If the implementation of this interface holds a pointer to // a shader, to avoid re-creating it every time, then it MUST make a reference // to that shader. Otherwise, the shader will be deleted when the render ends. //============================================================================== class imrShaderCreation { public: // Creates an instance of a shader with the given name. The name must be as it // appears in the .mi declaration. // This method may return NULL if the shader is not found, and the caller // should check for NULL values. virtual imrShader* CreateShader( const TCHAR* declarationName, const TCHAR* mtlName // The material's name is used when reporting errors. // (Tip: Pass the result of MtlBase::GetFullName()) // Passing NULL suppresses error messages. ) = 0; }; //============================================================================== // class imrShaderTranslation_ClassInfo // // IMPLEMENTATION INSTRUCTIONS: // // To be subclassed by a ClassDesc or ClassDesc2 of a Texmap plugin. // The subclass HAS TO call Init(*this) from its constructor. // // DESCRIPTION: // // This class is used to provide additional 'ApplyType' information for texmaps // that translate to a custom shaders. // // All mental ray shaders have an 'apply' type. This type classifies shaders into // different categories (e.g. texture shader, light shader, environment shader, etc.). // The apply type restricts where and how a shader may be used. By default, if // this interface is not implemented, a Texmap plugin will have the // imrShaderClassDesc::kApplyFlag_Default apply type. If this is incorrect, then // this interface should be implemented - otherwise it may be impossible to use // the shader and crashes could occur if the shader is not used correctly. //============================================================================== class imrShaderTranslation_ClassInfo : public FPStaticInterface { public: // Initialization method. MUST be called from the constructor of the subclass. i.e. "Init(*this);". void Init( ClassDesc& classDesc ); // Get the types to which this shader may be applied (combination of // imrShaderClassDesc::ApplyFlags values). virtual unsigned int GetApplyTypes() = 0; }; //============================================================================== // class imrShaderTranslation_ClassInfo inlined methods //============================================================================== // Given the class descriptor of a Mtl/Texmap plugin, this returns its compatibility interface (if it exists). inline imrShaderTranslation_ClassInfo* Get_imrShaderTranslation_ClassInfo(ClassDesc& mtlBaseClassDesc) { return static_cast(mtlBaseClassDesc.GetInterface(IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID)); } //============================================================================== // class imrShaderTranslation inlined methods //============================================================================== inline Interface_ID imrShaderTranslation::GetID() { return IMRSHADERTRANSLATION_INTERFACE_ID; } inline void imrShaderTranslation::TranslateParameters_Advanced(imrAdvancedTranslation& advancedTranslation, TimeValue t, Interval& valid) { // Default implementation does nothing } inline bool imrShaderTranslation::HasRequirement(Requirement, TimeValue t, Interval& valid, void* arg) { // Default implementation has no requirements return 0; } //============================================================================== // class imrMaterialPhenomenonTranslation inlined methods //============================================================================== inline Interface_ID imrMaterialPhenomenonTranslation::GetID() { return IMRMTLPHENTRANSLATION_INTERFACE_ID; } //============================================================================== // class imrGeomShaderTranslation inlined methods //============================================================================== inline Interface_ID imrGeomShaderTranslation::GetID() { return IMRGEOMSHADERTRANSLATION_INTERFACE_ID; } //============================================================================== // class imrShaderTranslation_ClassInfo inlined methods //============================================================================== inline void imrShaderTranslation_ClassInfo::Init(ClassDesc& classDesc) { LoadDescriptor(IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID, _T("imrShaderTranslation_ClassInfo"), 0, &classDesc, 0, end); } #endif