00001 /*============================================================================== 00002 00003 file: imrShaderTranslation.h 00004 00005 author: Daniel Levesque 00006 00007 created: 10feb2003 00008 00009 description: 00010 00011 Defition of the mental ray shader translation interface. 00012 00013 modified: 00014 00015 [dl] 28 April 2004. Added advanced translation of parameters, incremented 00016 interface IDs to distinguish between the old (MAX 6) interface and the new (MAX 7) 00017 interface. 00018 00019 (c) 2004 Autodesk 00020 ==============================================================================*/ 00021 #pragma once 00022 00023 #include "..\maxheap.h" 00024 #include "..\strbasic.h" 00025 #include "..\baseinterface.h" 00026 #include "..\ifnpub.h" 00027 #include "..\plugapi.h" // for classdesc 00028 #include "imrAdvancedTranslation.h" 00029 00030 // forward declarations 00031 class imrShader; 00032 class imrShaderCreation; 00033 class Texmap; 00034 class imrMaterialCustAttrib; 00035 class ReferenceTarget; 00036 class Point3; 00037 00038 #define IMRSHADERTRANSLATION_INTERFACE_ID Interface_ID(0x1c396abd, 0x5f964e0c) 00039 #define IMRMTLPHENTRANSLATION_INTERFACE_ID Interface_ID(0x5f970a9c, 0x65e75de4) 00040 #define IMRGEOMSHADERTRANSLATION_INTERFACE_ID Interface_ID(0x31882a12, 0x2102a73) 00041 #define IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID Interface_ID(0x17a76fd6, 0x5ab32bcd) 00042 00043 //============================================================================== 00044 // class imrShaderTranslation 00045 // 00046 // Interface to be implemented by the MAX plugin which translates to a mental 00047 // ray shader. Materials do not use this interface. Instead, they use the 00048 // imrMaterialTranslation interface. 00049 // 00050 // For example: 00051 // A 3rd party implements a MAX texmap pluggin for a brick effect. By default, 00052 // the mental ray translator does not support this texture and will be unable to 00053 // render it. If the 3rd party has also implemented a mental ray shader for this 00054 // effect, then this interface may be used to tell the mental ray translator 00055 // which shader is to be used. 00056 //============================================================================== 00057 class imrShaderTranslation : public BaseInterface { 00058 00059 public: 00060 00061 // List of requirements that may be queried on this translation interface 00062 enum Requirement { 00063 // This shader requires tangent basis vectors. 00064 // The tangent basis vectors will be translated for the object on which 00065 // this shader is used. 00066 // Return true if the vectors are needed, false otherwise. 00067 // The 't', and 'valid' parameters are not used. 00068 // The 'arg' variable is a pointer to an 'int', to which to map channel 00069 // to be used should be assigned. 00070 kReq_TangentBasisVectors = 0, 00071 }; 00072 00073 struct AdditionalDependency : public MaxHeapOperators { 00074 00075 AdditionalDependency(ReferenceTarget* rt, bool assign = true) : refTarg(rt), assignAsChild(assign) {} 00076 00077 // The reference target that is to be translated as a dependency 00078 ReferenceTarget* refTarg; 00079 // This should be true in all but exceptional cases where the translator 00080 // could run into potential problems with reference looping. 00081 bool assignAsChild; 00082 }; 00083 00084 typedef Tab<AdditionalDependency> AdditionalDependencyTable; 00085 00086 // Called by the mental ray translator to get the mental ray shader which 00087 // is to be used. The method may return a shader which was already created, 00088 // or create a new one via the imrShaderCreation interface. 00089 // This method will never be called more than once per render. 00090 virtual imrShader* GetMRShader(imrShaderCreation& shaderCreation) = 0; 00091 00092 // This may be called when rendering is finished to discard the mental ray shaders. 00093 // If the derived class holds a reference to the shader created by the call to GetMRShader(), 00094 // then it may release that reference in this call. This is not an obligation, 00095 // but it can free memory and/or resolve issues such as the "Make Unique" 00096 // button always being enabled in the material editor. 00097 virtual void ReleaseMRShader() = 0; 00098 00099 // Should the translator automatically copy the parameters based on the param 00100 // block 2 system? 00101 // NOTE: The metnal ray translator will correctly handle automatic translation 00102 // of the parameters IF the 3rd party plugin's parameters all use the ParamBlock2 00103 // system AND if the names & types of the parameters match the shader definition 00104 // (names are not case sensitive). 00105 // If this returns 'true', then the automatic translation will take place 00106 // after the call to TranslateParameters(). 00107 virtual bool NeedsAutomaticParamBlock2Translation() = 0; 00108 00109 // Translates the parameters of this plugin to the mental ray shader. Called 00110 // for the first frame, and for each subsequent frame that is not in the 00111 // validity interval. The method must store the validity interval of the 00112 // translated parameters in 'valid'. 00113 // **The parameters must be stored in the shader at time 0. 00114 virtual void TranslateParameters(imrTranslation& translationInterface, imrShader* shader, TimeValue t, Interval& valid) = 0; 00115 00116 // If this class needs any ReferenceTarget to be translated, but which are not 00117 // sub-references or within a parameter block of the plugin class, then these 00118 // ReferenceTarget's may be given here. The mental ray translator will automatically 00119 // create a dependency between the plugin and the given ReferenceTarget's. 00120 virtual void GetAdditionalReferenceDependencies(AdditionalDependencyTable& refTargets) = 0; 00121 00122 // This method is meant for advanced users for whom TranslateParameters() either is not 00123 // sufficient or causes performance issues. 00124 // Whereas TranslateParameters() translates parameters using the ParamBlock2 system, 00125 // this method is used to send parameters directly to mental ray, bypassing the ParamBlock2 system. 00126 // If TranslateParameters() is enough for you, or if you do not understand why you would need 00127 // this advanced translation method, then do not implement this method. 00128 // See the documentation of class imrAdvancedTranslation for more details. 00129 virtual void TranslateParameters_Advanced(imrAdvancedTranslation& advancedTranslation, TimeValue t, Interval& valid); 00130 00131 // This method is meant to query specific requirements from the translation interface. 00132 // Look at the documentation for each requirement flag for more information. 00133 // Note that 'arg' may or may not be used, depending on the requirement. 00134 virtual bool HasRequirement(Requirement requirement, TimeValue t, Interval& valid, void* arg = NULL); 00135 00136 // -- from BaseInterface 00137 virtual Interface_ID GetID(); 00138 }; 00139 00140 inline imrShaderTranslation* GetIMRShaderTranslation(InterfaceServer* iserver) { 00141 00142 return static_cast<imrShaderTranslation*>(iserver->GetInterface(IMRSHADERTRANSLATION_INTERFACE_ID)); 00143 } 00144 00145 //============================================================================== 00146 // class imrMaterialPhenomenonTranslation 00147 // 00148 // A material plugin that wishes to have a custom translation to a material 00149 // phenomenon must derive from this interface. The interface is identical to 00150 // imrShaderTranslation, except that: 00151 // - the interface ID is different 00152 // - only material phenomenon may be created via the imrShaderCreation interface. 00153 // 00154 // SPECIAL CASE: Using the mental ray material directly. 00155 // To translate a material to a mental ray material directly, without actually 00156 // using a phenomenon of your own, create an instance of the phenomenon called 00157 // "max_default_mtl_phen". Even though this is a phenomenon, it is not translated 00158 // as one, but instead it is translated as a material. NOTE, however, that this 00159 // particular phenomenon does NOT support the automatic ParamBlock2 translation, 00160 // so NeedsAutomaticParamBlock2Translation() should return false. 00161 //============================================================================== 00162 class imrMaterialPhenomenonTranslation : public imrShaderTranslation { 00163 00164 public: 00165 00166 // Returns whether this material supports the 'mental ray connection' custom 00167 // attributes rollup. This rollup allows users to override any of the 10 shaders 00168 // on the material. Note that only materials that translate to the default 00169 // material phenomenon ("max_default_mtl_phen") may return true here, since 00170 // the translator needs that phenomenon to translate the shader overrides. 00171 // If the material does not return the default material phenomenon but still 00172 // wishes to support the overrides, then it will have to do so itself. 00173 virtual bool SupportsMtlOverrides() = 0; 00174 00175 // Initializes the mtl overrides custom attribute, if necessary. Only called 00176 // if SupportsMtlOverrides() returned true. 00177 // All that this function should do is enable/disable the shader locks of the custom 00178 // attribute. 00179 // A material may simply do nothing here, or it may disable some of the shader locks 00180 // that don't apply. 00181 virtual void InitializeMtlOverrides(imrMaterialCustAttrib* mtlCustAttrib) = 0; 00182 00183 // -- from BaseInterface 00184 virtual Interface_ID GetID(); 00185 }; 00186 00187 inline imrMaterialPhenomenonTranslation* GetIMRMaterialPhenomenonTranslation(InterfaceServer* iserver) { 00188 00189 return static_cast<imrMaterialPhenomenonTranslation*>(iserver->GetInterface(IMRMTLPHENTRANSLATION_INTERFACE_ID)); 00190 } 00191 00192 //============================================================================== 00193 // class imrGeomShaderTranslation 00194 // 00195 // A geometry object plugin that wishes to have a custom translation to a mental 00196 // ray shader must derive from this interface. The interface is used to retrieve 00197 // an instance of the geometry shader to be used. 00198 // Derive your GeomObject or ShapeObject from this class to have it translated 00199 // to a geometry shader. 00200 //============================================================================== 00201 class imrGeomShaderTranslation : public BaseInterface { 00202 00203 public: 00204 00205 // Returns the geometry shader to be used with this object. The ReferenceTarget 00206 // returned by this method should be a Texmap plugin that translates to a mental 00207 // ray geometry shader. You may need to implement your own Texmap plugin that 00208 // uses the imrShaderTranslation interface to translate itself to a mental ray 00209 // shader. 00210 virtual ReferenceTarget* GetGeomShader() = 0; 00211 00212 // Returns a scale for the geometry shader, to be applied on the instance transform. 00213 // This is useful in the case that a geometry shader produces objects of a fixed 00214 // size (e.g. the mib_geo_* shaders), but you still want to be able to expose 00215 // a size parameter in the UI. 00216 // If you don't care about scaling, just return a scale of (1,1,1). 00217 virtual void GetScale(Point3& scale) = 0; 00218 00219 // -- from BaseInterface 00220 virtual Interface_ID GetID(); 00221 }; 00222 00223 inline imrGeomShaderTranslation* GetIMRGeomShaderTranslation(InterfaceServer* iserver) { 00224 00225 return static_cast<imrGeomShaderTranslation*>(iserver->GetInterface(IMRGEOMSHADERTRANSLATION_INTERFACE_ID)); 00226 } 00227 00228 //============================================================================== 00229 // class imrShaderCreation 00230 // 00231 // Interface used to create new shader instances. 00232 // 00233 // A reference to this interface is passed to the "GetMRShader()" method of the 00234 // imrShaderTranslation interface. If one tries to create a shader which does 00235 // nto exist, CreateShader() outputs an error in the mental ray message window 00236 // and returns NULL. 00237 // 00238 // IMPORTANT: If the implementation of this interface holds a pointer to 00239 // a shader, to avoid re-creating it every time, then it MUST make a reference 00240 // to that shader. Otherwise, the shader will be deleted when the render ends. 00241 //============================================================================== 00242 class imrShaderCreation: public MaxHeapOperators { 00243 00244 public: 00245 00246 // Creates an instance of a shader with the given name. The name must be as it 00247 // appears in the .mi declaration. 00248 // This method may return NULL if the shader is not found, and the caller 00249 // should check for NULL values. 00250 virtual imrShader* CreateShader( 00251 const MCHAR* declarationName, 00252 const MCHAR* mtlName // The material's name is used when reporting errors. 00253 // (Tip: Pass the result of MtlBase::GetFullName()) 00254 // Passing NULL suppresses error messages. 00255 ) = 0; 00256 }; 00257 00258 //============================================================================== 00259 // class imrShaderTranslation_ClassInfo 00260 // 00261 // IMPLEMENTATION INSTRUCTIONS: 00262 // 00263 // To be subclassed by a ClassDesc or ClassDesc2 of a Texmap plugin. 00264 // The subclass HAS TO call Init(*this) from its constructor. 00265 // 00266 // DESCRIPTION: 00267 // 00268 // This class is used to provide additional 'ApplyType' information for texmaps 00269 // that translate to a custom shaders. 00270 // 00271 // All mental ray shaders have an 'apply' type. This type classifies shaders into 00272 // different categories (e.g. texture shader, light shader, environment shader, etc.). 00273 // The apply type restricts where and how a shader may be used. By default, if 00274 // this interface is not implemented, a Texmap plugin will have the 00275 // imrShaderClassDesc::kApplyFlag_Default apply type. If this is incorrect, then 00276 // this interface should be implemented - otherwise it may be impossible to use 00277 // the shader and crashes could occur if the shader is not used correctly. 00278 //============================================================================== 00279 class imrShaderTranslation_ClassInfo : public FPStaticInterface { 00280 00281 public: 00282 00283 // Initialization method. MUST be called from the constructor of the subclass. i.e. "Init(*this);". 00284 void Init( 00285 ClassDesc& classDesc 00286 ); 00287 00288 // Get the types to which this shader may be applied (combination of 00289 // imrShaderClassDesc::ApplyFlags values). 00290 virtual unsigned int GetApplyTypes() = 0; 00291 }; 00292 00293 //============================================================================== 00294 // class imrShaderTranslation_ClassInfo inlined methods 00295 //============================================================================== 00296 00297 // Given the class descriptor of a Mtl/Texmap plugin, this returns its compatibility interface (if it exists). 00298 inline imrShaderTranslation_ClassInfo* Get_imrShaderTranslation_ClassInfo(ClassDesc& mtlBaseClassDesc) { 00299 00300 return static_cast<imrShaderTranslation_ClassInfo*>(mtlBaseClassDesc.GetInterface(IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID)); 00301 } 00302 00303 //============================================================================== 00304 // class imrShaderTranslation inlined methods 00305 //============================================================================== 00306 00307 inline Interface_ID imrShaderTranslation::GetID() { 00308 00309 return IMRSHADERTRANSLATION_INTERFACE_ID; 00310 } 00311 #pragma warning(push) 00312 #pragma warning(disable:4100) 00313 inline void imrShaderTranslation::TranslateParameters_Advanced(imrAdvancedTranslation& advancedTranslation, TimeValue t, Interval& valid) { 00314 00315 // Default implementation does nothing 00316 } 00317 00318 inline bool imrShaderTranslation::HasRequirement(Requirement, TimeValue t, Interval& valid, void* arg) { 00319 00320 // Default implementation has no requirements 00321 return 0; 00322 } 00323 #pragma warning(pop) 00324 //============================================================================== 00325 // class imrMaterialPhenomenonTranslation inlined methods 00326 //============================================================================== 00327 00328 inline Interface_ID imrMaterialPhenomenonTranslation::GetID() { 00329 00330 return IMRMTLPHENTRANSLATION_INTERFACE_ID; 00331 } 00332 00333 //============================================================================== 00334 // class imrGeomShaderTranslation inlined methods 00335 //============================================================================== 00336 00337 inline Interface_ID imrGeomShaderTranslation::GetID() { 00338 00339 return IMRGEOMSHADERTRANSLATION_INTERFACE_ID; 00340 } 00341 00342 //============================================================================== 00343 // class imrShaderTranslation_ClassInfo inlined methods 00344 //============================================================================== 00345 00346 inline void imrShaderTranslation_ClassInfo::Init(ClassDesc& classDesc) { 00347 00348 LoadDescriptor(IMRSHADERTRANSLATION_CLASSINFO_INTERFACE_ID, _M("imrShaderTranslation_ClassInfo"), 0, &classDesc, 0, end); 00349 } 00350