使用 AdskShaderSDK 创建过程适应着色器

 
 
 

基于 AdskShaderSDK 创建着色器,以实施在着色器中产生的可自动支持多重渲染过程的组件。分量表示材质分解和光线交互,即,漫反射材质颜色组件、环境光组件,等等。

过程适应着色器由两个不同的部分组成:着色器 mi 声明和 C++ 实施,后者需要使用 mentalray API 和 AdskShaderSDK 来构建。

着色器声明文件定义 Maya 和 mentalray 之间的接口。还定义此着色器的受支持 MentalRay 版本。

使用 AdskShaderSDK 写入的过程适应着色器必须采用 C++ 来实施,以便利用框架的层次设计。

随后根据 mentalray API 和 AdskShaderSDK 编译和链接文件,从而创建可在 Maya 中使用的动态库。

可以在此处找到对 AdskShaderSDK 的完整引用。

采样着色器实现

着色器声明文件

采样 MayaPhong.mi 如下所示:

declare shader  
  # Return struct	
struct {
	color		    "outColor",	
	color		    "outGlowColor",		
	color		    "outMatteOpacity",		
	color		    "outTransparency",		
	# BRDF components		
	color		    "outAmbient",		
	color		    "outIncandescence",		
	color		    "outIrradiance",	
	color		    "outDiffuseShadowed",		
	color		    "outDiffuseNoShadow",		
	color		    "outShadow",		
	color		    "outSpecularShadowed",	
	color		    "outSpecularNoShadow",		
	color		    "outReflection",		
	color		    "outRefraction",		
	color		    "outScatter",		
	color		    "outOpacity"    }   
"MayaPhong" (        	
	# Render Pass Parameters        	
	array string        "FrameBufferNames",        
	array integer       "FrameBufferTypeCounts",        	
	boolean             "UsingPerLightContribution", 	
	string              "LightFrameBufferMapping",        	
	# Inherited from Base Material        	
	color               "color",        	
	color               "transparency",        	
	# Inherited from Matte Material	
	integer             "matteOpacityMode",	
	scalar              "matteOpacity",       	
	# Inherited from Glow Material
	scalar              "glowIntensity",
	# Inherited from Lambertian Material
	integer             "refractionLimit",	
	scalar              "refractiveIndex",	
	boolean             "refractions",	
	scalar              "diffuse",	
	color               "ambientColor",	
	color               "incandescence",	
	scalar              "translucence",	
	scalar              "translucenceFocus",	
	scalar              "translucenceDepth",	
	scalar              "opacityGain",        	
	Boolean             "hideSource",	
	scalar              "surfaceThickness",	
	scalar              "shadowAttenuation",	
	scalar              "transparencyDepth",	
	scalar              "lightAbsorbance",	
	boolean             "chromaticAberration",	
	vector              "normalCamera",	
	color               "irradiance",	
	color               "irradianceColor",	
	scalar              "refractionBlur",	
	integer             "refractionBlurLimit",	
	integer             "refractionRays",	
	color               "scatterColor",	
	scalar              "scatterRadius",	
	integer             "scatterAccuracy",	
	integer             "scatterFalloff",	
	integer             "scatterLimit",	
	integer             "scatterCache",	
	# Inherited from Reflective Material	
	integer             "reflectionLimit",	
	color               "specularColor",	
	color               "reflectedColor",	
	scalar              "reflectivity",	
	scalar              "reflectionSpecularity",        	
	scalar              "reflectionBlur",        	
	scalar              "reflectionBlurLimit",        	
	integer             "reflectionRays",     	
	# Phong parameters	
	scalar              "cosinePower"  
 ) 
version 1   
apply material
end declare

如上图所示,采样器声明包含两个部分,即返回结构和渲染过程参数。

在我们的示例中,返回结构包含传统 Maya 渲染过程的组件。渲染过程(对于多重渲染)会自动写入到 AdskShaderSDK 中命名的帧缓冲区。

有关如何编写着色器声明文件的更完整的手册,请参考文档 mental Ray 着色器语言扩展编写着色器声明文件

AdskShaderSDK 着色器 C++ 实现

着色器参数

需要在 C++ 文件的该部分中公布我们的着色器使用的参数。此参数列表的顺序必须与在着色器声明文件中定义的顺序匹配。

为实现此目的,将 MayaPhongParameters 结构定义为首先使用宏 ADSK_REFLECTIVE_MATERIAL_PARAMETERS 公布反射着色器的默认参数,接着公布实现 MayaPhong 所必需的自定义参数。在我们的示例中,miScalar cosPower 表示我们的采样着色器的 Phong 镜面反射指数。有关其他相关参数宏,请参考 adskShader.h

struct MayaPhongParameters {   
	ADSK_REFLECTIVE_MATERIAL_PARAMETERS    
	miScalar cosPower;
};

着色器组件定义

AdskShaderSDK 默认组件是在 adskComponent.h 中定义的。在该特定示例中,我们覆盖镜面反射组件,因为默认不含镜面反射度。作为覆盖编写的组件必须与默认声明精确匹配:

template <typename ParameterType>
class MayaPhongSpecularComponent {
  public:    
	MayaPhongSpecularComponent(miState *state, ParameterType *paras);
	~MayaPhongSpecularComponent() {};    
	miColor operator()(miState *state,    
 			   ParameterType *paras, 
 			   miColor &pLightColor, 
 			   miVector &pLightDirection,
			   miVector &pReflectionDirection);
};

该着色器组件实现

系统会为每个采样均调用 operator() 成员函数。在该函数中,可以调用 mental Ray 和 AdskShaderSDK 函数。如果需要任何动态分配的内存,则必须使用 mental Ray API 调用 mi_mem_allocate()mi_mem_release()

以下示例说明如何实现基本的 Phong 镜面反射度:

template<typename ParameterType>
miColor MayaPhongSpecularComponent<ParameterType>::operator()(miState *state,
	                                ParameterType *paras,
	                                miColor &pLightColor,
	                                miVector &pLightDirection,
	                                miVector &pReflectionDirection){
	// get the relevent parameters   
	miScalar specularExponent = *mi_eval_scalar(&paras->cosPower);
		miScalar reflectionSpecularity = *mi_eval_scalar(&paras->reflectionSpec);
	miColor materialSpecularColor = *mi_eval_color(&paras->specularColor);
	miScalar phongSpecular = compute_phong_specular(&pLightDirection,
						specularExponent,
						reflectionSpecularity,
						&pReflectionDirection,
						state);
	if (phongSpecular > 0.0){ 
		return phongSpecular * materialSpecularColor * pLightColor;
	} 
   	else{ 
       		return BLACK;  
  	}
} 

定义着色器类

我们的新着色器类是材质类的模板实例,因此我们需要指定模板参数:

typedef Material<    
	MayaPhongParameters,
	DefaultAmbientMaterialColorComponent<MayaPhongParameters>,    
	DefaultAmbientComponent<MayaPhongParameters>,
	DefaultDiffuseMaterialColorComponent<MayaPhongParameters>,   
	DefaultDiffuseComponent<MayaPhongParameters>,   
	MayaPhongSpecularComponent<MayaPhongParameters>
> MayaPhongClass;

最后,为了将我们的新着色器公布到 Maya,必须调用下面的宏。

EXPOSE_CUSTOM_MATERIAL(MayaPhong) 

必须命名宏参数,以使 MayaPhongParameters 和 MayaPhongClass 已定义,即,在查找相应类型时始终将“参数”和“类”字样附加到参数。

注意

有关 shaderSDK 示例,请参见 devkit 中的 adskShaderSDK\Samples\MayaPhong 文件夹。