liqLightHandle Renderer::shader_light(
		const liqShader &shader,
		const std::vector<liqTokenPointer> &tokenPointerArray
		)
	{
		CM_TRACE_FUNC("Renderer::shader_light("<<shader.getName()<<", tokenPointerArray)");

		int shaderParamCount = tokenPointerArray.size() - 1;
		boost::scoped_array< liqToken > tokenArray( new liqToken[ tokenPointerArray.size() ] );
		boost::scoped_array< liqPointer > pointerArray( new liqPointer[ tokenPointerArray.size() ] );
		assignTokenArrays( tokenPointerArray.size(), &tokenPointerArray[ 0 ], tokenArray.get(), pointerArray.get() );

		return RiLightSourceV( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() );
	}
	void Renderer::shader_lens(
		const liqShader &shader,
		const std::vector<liqTokenPointer> &tokenPointerArray
		)
	{
		CM_TRACE_FUNC("Renderer::shader_lens("<<shader.getName()<<",tokenPointerArray)");

		_UserDefinedShader(shader, tokenPointerArray);
	}
	void Renderer::shader_surface(
		const liqShader &shader,
		const std::vector<liqTokenPointer> &tokenPointerArray
		)
	{
		CM_TRACE_FUNC("Renderer::shader_surface("<<shader.getName()<<", tokenPointerArray)");

		int shaderParamCount = tokenPointerArray.size() - 1;
		boost::scoped_array< liqToken > tokenArray( new liqToken[ tokenPointerArray.size() ] );
		boost::scoped_array< liqPointer > pointerArray( new liqPointer[ tokenPointerArray.size() ] );
		assignTokenArrays( tokenPointerArray.size(), &tokenPointerArray[ 0 ], tokenArray.get(), pointerArray.get() );

		if ( shader.useVisiblePoints ){
			//RiVPSurfaceV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() );
			RiArchiveRecord( RI_COMMENT, "RiVPSurfaceV is not implemented in maya2renderer, useVisiblePoints is added by ymesh in r777" );
		}else{
			RiSurfaceV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get() , pointerArray.get() );
		}
	}
	liqLightHandle Renderer::shader_light(
		const liqShader &shader,
		const std::vector<liqTokenPointer> &tokenPointerArray
	)
	{
		CM_TRACE_FUNC("Renderer::shader_light("<<shader.getName()<<", tokenPointerArray)");

		_UserDefinedShader(shader, tokenPointerArray);

		return (liqLightHandle)0;//dummy value
	}
	void Renderer::shader_volume(
		const liqShader &shader, 
		const std::vector<liqTokenPointer> &tokenPointerArray
		)
	{
		CM_TRACE_FUNC("Renderer::shader_volume("<<shader.getName()<<", tokenPointerArray)");

		int shaderParamCount = tokenPointerArray.size() - 1;
		boost::scoped_array< liqToken > tokenArray( new liqToken[ tokenPointerArray.size() ] );
		boost::scoped_array< liqPointer > pointerArray( new liqPointer[ tokenPointerArray.size() ] );
		assignTokenArrays( tokenPointerArray.size(), &tokenPointerArray[ 0 ], tokenArray.get(), pointerArray.get() );

		//RiAtmosphereV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount,  tokenArray.get(), pointerArray.get() );
		switch ( shader.volume_type )
		{
		case VOLUME_TYPE_INTERIOR:
			if ( shader.useVisiblePoints ){
				//RiVPInteriorV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() ); 
				RiArchiveRecord( RI_COMMENT, "RiVPInteriorV is not implemented in maya2renderer, useVisiblePoints is added by ymesh in r777" );
			}else{
				RiInteriorV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() ); 
			}break;
		case VOLUME_TYPE_EXTERIOR:
			if ( shader.useVisiblePoints ){
				RiArchiveRecord( RI_COMMENT, "useVisiblePoints is added by ymesh in r777" );
#ifdef GENERIC            
				RiVPExteriorV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() );
#else
				// Atleast Prman 16.x haven't this function
				RiExteriorV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() );  
#endif  
			}else{
				RiExteriorV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() ); 
			}break;
		case VOLUME_TYPE_ATMOSPHERE:
		default:
			if ( shader.useVisiblePoints ){
				//RiVPAtmosphereV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() ); 
				RiArchiveRecord( RI_COMMENT, "RiVPAtmosphereV is not implemented in maya2renderer, useVisiblePoints is added by ymesh in r777" );
			}else{
				RiAtmosphereV ( const_cast<char *>(shader.getShaderFileName().c_str()), shaderParamCount, tokenArray.get(), pointerArray.get() ); 
			}break;
		}
	}
	void Renderer::_UserDefinedShader(
		const liqShader &shader,
		const std::vector<liqTokenPointer> &tokenPointerArray
	)
	{	
		CM_TRACE_FUNC("Renderer::_UserDefinedShader("<<shader.getName()<<", tokenPointerArray)");

		std::string const& liquidShaderName=shader.getName();
		std::string const& rmSloFilePath=shader.getShaderFileName();
		std::string const& mayaShaderName=rmSloFilePath.substr(rmSloFilePath.find_last_of('/')+1);
		_s( "// shader("<<mayaShaderName<<","<<", ...)" );//Renderman slo file name, e.g."your_shader_dir/test_type2"
		//_s( "// shader("<<liquidShaderName<<","<<", ...)" );//e.g."lambert1", or "liquidSurface1", NOTE: it is liquidShader, not maya shader.

		_S( ei_shader(liquidShaderName.c_str()) );

		_s("ei_shader_param_string( \"desc\",\""<<mayaShaderName<<"\");");
		ei_shader_param_string("desc", mayaShaderName.c_str()); // //"opaque"

		//tokenPointerArray only store parameters of user-defined shader
		size_t parameterNum =  tokenPointerArray.size() - 1;
		for(size_t i=0; i<parameterNum; ++i)
		{
 			//_s("//- "
 			//	<<const_cast<liqTokenPointer*>(&tokenPointerArray[i])->getDetailedTokenName()<<","//uniform float intensity
 			//	<<tokenPointerArray[i].getDetailType()<<","
 			//	<<"//tokenPointerArray[i].getTokenFloatArray()"<<","
 			//	<<"//[error]tokenPointerArray[i].getTokenString()"<<","
 			//	<<tokenPointerArray[i].getTokenName()<<","//intensity,
 			//	<<tokenPointerArray[i].getParameterType()<<","//rFloat,
 			//	<<tokenPointerArray[i].getRiDeclare()<<","//uniform float,
 			//	);
// 			_s("// "<<tokenPointerArray[i].getTokenName());

			liqTokenPointer* vp = const_cast< liqTokenPointer* >( &tokenPointerArray[i] );
			switch( tokenPointerArray[i].getParameterType() )
			{
			case rFloat:
				{
					const liqFloat *v = vp->getTokenFloatArray();
					_s("ei_shader_param_scalar(\""<<vp->getTokenName()<<"\"," <<v[0]<<");");
					ei_shader_param_scalar( vp->getTokenName().c_str(), v[0] );
				}
				break;
			case rPoint: case rVector: case rNormal: case rColor:
				{
					const liqFloat *v = vp->getTokenFloatArray();
					_s("ei_shader_param_vector(\""<<vp->getTokenName()<<"\"," <<v[0]<<","<<v[1]<<","<<v[2]<<");");
					ei_shader_param_vector( vp->getTokenName().c_str(), v[0] ,v[1], v[2] );
				}
				break;
			case rString: case rShader:
				{
					const std::string &v = vp->getTokenString();
					_s("ei_shader_param_string(\""<<vp->getTokenName()<<"\"," <<v<<");");
					ei_shader_param_string( vp->getTokenName().c_str(), v.c_str() );
				}
				break; 
			case rHpoint:
				{
					const liqFloat *v = vp->getTokenFloatArray();
					_s("ei_shader_param_vector4(\""<<vp->getTokenName()<<"\"," <<v[0]<<","<<v[1]<<","<<v[2]<<","<<v[3]<<");");
					ei_shader_param_vector4( vp->getTokenName().c_str(), v[0] ,v[1], v[2], v[3] );
				}
				break;
			case rMatrix:
				{
					const liqFloat *v = vp->getTokenFloatArray();
					_s("//matrix:"
						<<v[0]<<","<<v[1]<<","<<v[2]<<","<<v[3]
						<<v[4]<<","<<v[5]<<","<<v[6]<<","<<v[7]
						<<v[8]<<","<<v[9]<<","<<v[10]<<","<<v[11]
						<<v[12]<<","<<v[13]<<","<<v[14]<<","<<v[15]
					);
				}
				;break;
			default :
				assert(0);
			}

		}//for
		_S( ei_end_shader() );


	}