/* <copyright>
 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
 (c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
 </copyright> */



/////////////////////////////////////////////////////////////////////////
//// Class UberMaterial
////      RDGE representation of a material.
/////////////////////////////////////////////////////////////////////////
function UberMaterial()
{
    // initialize the inherited members
    this.inheritedFrom = GLMaterial;
    this.inheritedFrom();
   
    ///////////////////////////////////////////////////////////////////////
    // Instance variables
    ///////////////////////////////////////////////////////////////////////
	this._name = "UberMaterial";
	this._shaderName = "uber";
	this.getShaderName = function()	{  return this._shaderName;  };

	// set some default values
	this._ambientColor  = [ 0.0, 0.0, 0.0, 1.0 ];
	this._diffuseColor  = [ 1.0, 1.0, 1.0, 1.0 ];
	this._specularColor = [ 1.0, 1.0, 1.0, 1.0 ];
	this._specularPower = 32.0;
	this._environmentAmount = 0.2;		// 0 .. 1

	this._MAX_LIGHTS = 4;

	// set the default maps
	this._diffuseMapOb = { 'texture' : 'assets/images/rocky-diffuse.jpg', 'wrap' : 'REPEAT' };
	this._normalMapOb = { 'texture' : 'assets/images/rocky-normal.jpg', 'wrap' : 'REPEAT' };
	this._specularMapOb = { 'texture' : 'assets/images/rocky-spec.jpg', 'wrap' : 'REPEAT' };
	this._environmentMapOb = { 'texture' : 'assets/images/silver.png', 'wrap' : 'CLAMP', 'envReflection' : this._environmentAmount };

	this._useDiffuseMap		= true;
	this._useNormalMap		= true;
	this._useSpecularMap	= true;
	this._useEnvironmentMap	= true;
	this._useLights			= [true, true, true, true];

    ///////////////////////////////////////////////////////////////////////
    // Material Property Accessors
    ///////////////////////////////////////////////////////////////////////
	this._propNames			= ["ambientColor",	"diffuseColor",		"specularColor",	"specularPower"	,	"diffuseMap",	"normalMap",	"specularMap",		"environmentMap",		"environmentAmount" ];
	this._propLabels		= ["Ambient Color",	"Diffuse Color",	"Specular Color",	"Specular Power",	"Texture Map",	"Bump Map",		"Specular Map",		"Environment Map",		"Environment Map Amount" ];
	this._propTypes			= ["color",			"color",			"color",			"float",			"file",			"file",			"file",				"file",					"float"		];
	this._propValues		= [];

	this._propValues[ this._propNames[0] ] = this._ambientColor.slice(0);
	this._propValues[ this._propNames[1] ] = this._diffuseColor.slice(0);
	this._propValues[ this._propNames[2] ] = this._specularColor.slice(0);
	this._propValues[ this._propNames[3] ] = this._specularPower;
	this._propValues[ this._propNames[4] ] = this._diffuseMapOb['texture'];
	this._propValues[ this._propNames[5] ] = this._normalMapOb['texture'];
	this._propValues[ this._propNames[6] ] = this._specularMapOb['texture'];
	this._propValues[ this._propNames[7] ] = this._environmentMapOb['texture'];
	this._propValues[ this._propNames[8] ] = this._environmentMapOb['envReflection'];

	this.setProperty = function( prop, value )
	{
		if (prop == "color")  prop = "ambientColor";
		var valid = this.validateProperty( prop, value );
		if (valid)
		{
			this._propValues[prop] = value;

			switch (prop)
			{
				case "diffuseMap":
					this.updateDiffuseMap();
					break;
				case "normalMap":
					this.updateNormalMap();
					break;
				case "specularMap":
					this.updateSpecularMap();
					break;
				case "environmentMap":
					this.updateEnvironmentMap();
					break;
				case "environmentAmount":
					this.updateEnvironmentAmount( value );
					break;
				case "specularPower":
					this.updateSpecularPower( value );
					break;
				case "ambientColor":
					this.updateAmbientColor( value );
					break;
				case "diffuseColor":
					this.updateDiffuseColor( value );
					break;
				case "specularColor":
					this.updateSpecularColor( value );
					break;
			}
		}
	};
    ///////////////////////////////////////////////////////////////////////

	// define the 4 lights
	this._lights = [

		{
			'type' : 'point',                           // can be 'directional', 'point' or 'spot'
			'spotInnerCutoff' : 14.0,                   // fragments in the inner cutoff 'cone' are full intensity.
			'spotOuterCutoff' : 15.0,                   // fragments outside the outer cutoff 'cone' are unlit.
			'position' : [ 8.0, 2.0, 8.0 ],             // light position; ignored for directional lights
			'direction' : [ -1.0, -1.0, -1.0 ],         // light direction; ignored for point lights
			'attenuation' : [ 1.0, 0.025, 0.00125 ],    // light attenuation; constant, linear, quadratic 
			'diffuseColor' : [ 1.0, 0.5, 0.5, 1.0 ],    // diffuse light color
			'specularColor' : [ 1.0, 1.0, 1.0, 1.0 ]    // specular light color  
		},
		{
			'type' : 'point',
			'spotInnerCutoff' : 9.0,               
			'spotOuterCutoff' : 20.0,               
			'position' : [ -8.0, 2.0, 8.0 ],         
			'direction' : [ 1.0, -1.0, -1.0 ],
			'attenuation' : [ 1.0, 0.025, 0.00125 ],
			'diffuseColor' : [ 0.5, 1.0, 0.5, 1.0 ],
			'specularColor' : [ 1.0, 1.0, 1.0, 1.0 ]
		},
		{
			'type' : 'point',
			'spotInnerCutoff' : 9.0,               
			'spotOuterCutoff' : 20.0,               
			'position' : [ -8.0, 2.0, -8.0 ],
			'direction' : [ 1.0, -1.0, 1.0 ],
			'attenuation' : [ 1.0, 0.25, 0.0125 ], 
			'diffuseColor' : [ 0.5, 0.5, 1.0, 1.0 ],
			'specularColor' : [ 1.0, 1.0, 1.0, 1.0 ]
		},
		{
			'type' : 'point',
			'spotInnerCutoff' : 9.0,               
			'spotOuterCutoff' : 20.0,               
			'position' : [ 8.0, 4.0, -8.0 ],
			'direction' : [ -1.0, -1.0, 1.0 ],
			'attenuation' : [ 1.0, 0.25, 0.0125 ],
			'diffuseColor' : [ 1.0, 1.0, 0.5, 1.0 ],
			'specularColor' : [ 1.0, 1.0, 1.0, 1.0 ]
		}
	];

	this._ubershaderCaps =
	{
		// ubershader material properties. 
		'material' : {
			'ambientColor'    : this._ambientColor,    // material ambient color
			'diffuseColor'    : this._diffuseColor,    // material diffuse color
			'specularColor'   : this._specularColor,   // material specular color
			'specularPower'   : this._specularPower    // material specular power (shininess)
		},
 
		// ubershader supports up to four lights. 
		'lighting' : {
			'light0' : this._lights[0],
			'light1' : this._lights[1],
			'light2' : this._lights[2],        
			'light3' : this._lights[3]                                     
		},
    
		// uvTransform can be used to scale or offset the texture coordinates.
		'uvTransform' : [ 2.0, 0, 0, 0, 0, 2.0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1],
    
		// optional diffuse map
		'diffuseMap' : this._diffuseMapOb,
    
		// optional normal map
		'normalMap' : this._normalMapOb,
    
		// optional specular map
		'specularMap' : this._specularMapOb,
    
		// optional environment map
		'environmentMap' : this._environmentMapOb
	};

	this.updateAmbientColor = function()
	{
		this._ambientColor = this._propValues['ambientColor'].slice(0);
		var material = this._materialNode;
		if (material)
		{
			var technique = material.shaderProgram.defaultTechnique;    
			technique.u_ambientColor.set(this._ambientColor);
		}
	};

	this.updateDiffuseColor = function()
	{
		this._diffuseColor = this._propValues['diffuseColor'].slice(0);

		var material = this._materialNode;
		if (material)
		{
			var technique = material.shaderProgram.defaultTechnique;    
			technique.u_diffuseColor.set(this._diffuseColor);
		}
	};

	this.updateSpecularColor = function( value )
	{
		this._specularColor = this._propValues['specularColor'];

		var material = this._materialNode;
		if (material)
		{
			var technique = material.shaderProgram.defaultTechnique;    
			technique.u_specularColor.set(this._specularColor);
		}
	};

	this.updateSpecularPower = function( value)
	{
		this._specularPower = this._propValues['specularPower'];

		var material = this._materialNode;
		if (material)
		{
			var technique = material.shaderProgram.defaultTechnique;    
			technique.u_specularPower.set([this._specularPower]);
		}
	};

	this.updateEnvironmentAmount = function(value)
	{
		this._environmentMapOb.envReflectionAmount = value;

		var material = this._materialNode;
		if (material)
		{
			var technique = material.shaderProgram.defaultTechnique;
			technique.u_envReflection.set([this._environmentMapOb.envReflection]);
		}
	};

	this.updateEnvironmentMap = function()
	{
		var value = this._propValues[ "environmentMap" ];
		this._environmentMapOb.texture = value;

		if ((value == null) || (value.length == 0))
		{
			if (this._useEnvironmentMap)
			{
				this._useEnvironmentMap = false;
				this.rebuildShader();
			}
		}
		else
		{
			if (!this._useEnvironmentMap)
			{
				this._useEnvironmentMap = true;
				this.rebuildShader();
			}
			else
			{
				var material = this._materialNode;
				if (material)
				{
					var technique = material.shaderProgram.defaultTechnique;
					var renderer = g_Engine.getContext().renderer;
					if (renderer && technique)
					{
						var tex = renderer.getTextureByName(value, caps.environmentMap.wrap);
						this.registerTexture( tex );
						technique.s_environmentMap.set( tex );
					}
				}
			}
		}
	};

	this.updateDiffuseMap = function(value)
	{
		var value = this._propValues[ "diffuseMap" ];
		this._diffuseMapOb.texture = value;

		if ((value == null) || (value.length == 0))
		{
			if (this._useDiffuseMap)
			{
				this._useDiffuseMap = false;
				this.rebuildShader();
			}
		}
		else
		{
			if (!this._useDiffuseMap)
			{
				this._useDiffuseMap = true;
				this.rebuildShader();
			}
			else
			{
				var material = this._materialNode;
				if (material)
				{
					var technique = material.shaderProgram.defaultTechnique;
					var renderer = g_Engine.getContext().renderer;
					if (renderer && technique)
					{
						var tex = renderer.getTextureByName(value, caps.diffuseMap.wrap);
						this.registerTexture( tex );
						technique.s_diffuseMap.set( tex );
					}
				}
			}
		}
	};

	this.updateSpecularMap = function()
	{
		var value = this._propValues[ "specularMap" ];
		this._specularMapOb.texture = value;

		if ((value == null) || (value.length == 0))
		{
			if (this._useSpecularMap)
			{
				this._useSpecularMap = false;
				this.rebuildShader();
			}
		}
		else
		{
			if (!this._useSpecularMap)
			{
				this._useSpecularMap = true;
				this.rebuildShader();
			}
			else
			{
				var material = this._materialNode;
				if (material)
				{
					var technique = material.shaderProgram.defaultTechnique;
					var renderer = g_Engine.getContext().renderer;
					if (renderer && technique)
					{
						var tex = renderer.getTextureByName(value, caps.specularMap.wrap);
						this.registerTexture( tex );
						technique.s_specularMap.set( tex );
					}
				}
			}
		}
	};

	this.updateNormalMap = function(value)
	{
		var value = this._propValues[ "normalMap" ];
		this._normalMapOb.texture = value;

		if ((value == null) || (value.length == 0))
		{
			if (this._useNormalMap)
			{
				this._useNormalMap = false;
				this.rebuildShader();
			}
		}
		else
		{
			if (!this._useNormalMap)
			{
				this._useNormalMap = true;
				this.rebuildShader();
			}
			else
			{
				var material = this._materialNode;
				if (material)
				{
					var technique = material.shaderProgram.defaultTechnique;
					var renderer = g_Engine.getContext().renderer;
					if (renderer && technique)
					{
						var tex = renderer.getTextureByName(value, caps.normalMap.wrap);
						this.registerTexture( tex );
						technique.s_normalMap.set( tex );
					}
				}
			}
		}
	};
	
	// duplcate method requirde
	this.dup = function()
	{
		// allocate a new uber material
		var newMat = new UberMaterial();

		newMat._useDiffuseMap = this._useDiffuseMap;
		newMat._useEnvironmentMap = this._useEnvironmentMap;
		newMat._useLights = this._useLights;
		newMat._useNormalMap = this._useNormalMap;
		newMat._useSpecularMap = this._useSpecularMap;
		newMat.rebuildShader();

		// copy over the current values;
		var propNames = [],  propValues = [],  propTypes = [],  propLabels = [];
		this.getAllProperties( propNames,  propValues,  propTypes,  propLabels);
		var n = propNames.length;
		for (var i=0;  i<n;  i++)
			newMat.setProperty( propNames[i], propValues[i] );

		return newMat;
	};

	this.init = function( world )
	{
		// save the world
		if (world)  this.setWorld( world );

		// set up the shader
		this._shader = this.buildUberShader( this._ubershaderCaps );

		// set up the material node
		this._materialNode = createMaterialNode("uberMaterial_" + world.generateUniqueNodeID());
		this._materialNode.setShader(this._shader);
	};

	this.import = function( importStr )
	{
		// limit the key searches to this material
        var endKey = "endMaterial\n";
        var index = importStr.indexOf( endKey );
        index += endKey.length;
        importStr = importStr.substr( index );
	}

	this.export = function()
	{
		// every material needs the base type and instance name
		var exportStr = "material: " + this.getShaderName() + "\n";
		exportStr += "name: " + this.getName() + "\n";

		var caps = this._ubershaderCaps;
		
		// export the material properties
		if (typeof caps.material != 'undefined')
		{
			exportStr += "material: true\n";
			exportStr += "ambientColor: " + caps.material.ambientColor + "\n";
			exportStr += "diffuseColor: " + caps.material.diffuseColor + "\n";
			exportStr += "specularColor: " + caps.material.specularColor + "\n";
			exportStr += "specularPower: " + caps.material.specularPower + "\n";
		}

		if (typeof caps.lighting != 'undefined')
		{
			var light = caps.lighting['light' + i];
			var t;
			for (var i=0;  i<this._MAX_LIGHTS;  i++)
			{
				var light = caps.lighting["light" + i];
				if( typeof light != "undefined")
				{
					exportStr += "light" + i + ': ' + light.type + "\n";

					if (light.type === 'directional')
					{
						exportStr += 'light' + i + 'Dir: ' + light['direction'] + '\n';
					}
					else if (light.type === 'spot')
					{
						exportStr += 'light' + i + 'Pos: ' + light['position'] + '\n';

						var deg2Rad = Math.PI / 180;
						exportStr += 'light' + i + 'Spot: ' + [ Math.cos( ( light['spotInnerCutoff'] || 45.0 )  * deg2Rad ), 
																Math.cos( ( light['spotOuterCutoff'] || 90.0 ) * deg2Rad )] + '\n';
					}
					else		// light.type === 'point'
					{
						technique['u_light'+i+'Pos'].set(light['position'] || [ 0, 0, 0 ]);                        
						technique['u_light'+i+'Atten'].set(light['attenuation'] || [ 1,0,0 ]);                
					}
					exportStr += 'light' + i + 'Color: ' + light['diffuseColor'] || [ 1,1,1,1 ] + '\n';
					exportStr += 'light' + i + 'SpecularColor: ' + light['specularColor'] || [ 1, 1, 1, 1 ] + '\n'; 
					
					exportStr += "endlight\n";          
				}
			}
		}
		
		// every material needs to terminate like this
		exportStr += "endMaterial\n";

		return exportStr;
	}

	this.buildUberShader = function(caps)
	{
		var preproc = "";
		var paramBlock = {};
   
		paramBlock['u_uvMatrix'] = { 'type' : 'mat4' };    
    
		if (typeof caps.material != 'undefined') {
			preproc += '#define MATERIAL\n';   
			paramBlock['u_ambientColor'] = { 'type' : 'vec4' };
			paramBlock['u_diffuseColor'] = { 'type' : 'vec4' };
			paramBlock['u_specularColor'] = { 'type' : 'vec4' };
			paramBlock['u_specularPower'] = { 'type' : 'float' };
		}
		if (typeof caps.lighting != 'undefined')
		{
			preproc += '#define LIGHTING\n';
			preproc += '#define SPECULAR\n';
			for(var i = 0; i < 4; ++i) {
				var light = caps.lighting['light' + i];
				var t;
				if (typeof light != 'undefined') {
					switch(light.type) {
						case 'directional'  : t = 0;    break;
						case 'point'        : t = 1;    break;
						case 'spot'         : t = 2;    break;
					}
					preproc += '#define LIGHT_'+i+' '+t+'\n';
					preproc += '#define LIGHT_'+i+'_SPECULAR\n';
					if(t == 0 || t == 2) {
						paramBlock['u_light'+i+'Dir'] = { 'type' : 'vec3' };
					}
					if(t == 2) {
						paramBlock['u_light'+i+'Spot'] = { 'type' : 'vec2' };
					}			       
					paramBlock['u_light'+i+'Pos'] = { 'type' : 'vec3' };
					paramBlock['u_light'+i+'Color'] = { 'type' : 'vec4' };
					paramBlock['u_light'+i+'Atten'] = { 'type' : 'vec3' };
					paramBlock['u_light'+i+'Specular'] = { 'type' : 'vec4' };            
				}        
			}
		}  
		if(typeof caps.diffuseMap != 'undefined') {
			preproc += '#define DIFFUSE_MAP\n';
			paramBlock['s_diffuseMap'] = { 'type' : 'tex2d' };
		}
		if(typeof caps.normalMap != 'undefined') {
			preproc += '#define NORMAL_MAP\n';
			paramBlock['s_normalMap'] = { 'type' : 'tex2d' };
		}
		if(typeof caps.specularMap != 'undefined') {
			preproc += '#define SPECULAR_MAP\n';
			paramBlock['s_specMap'] = { 'type' : 'tex2d' };
		}
		if(typeof caps.environmentMap != 'undefined') {
			preproc += '#define ENVIRONMENT_MAP\n';
			paramBlock['s_envMap'] = { 'type' : 'tex2d' };
			paramBlock['u_envReflection'] = { 'type' : 'float' };
		}

		// load the shaders as text
		var uberVShader,  uberFShader;
		var r = new XMLHttpRequest();
		r.open('GET', "assets/shaders/ub_vshader.glsl", false);
		r.send(null);
		if (r.status == 200) {
			uberVShader = r.responseText;
		}
		r.open('GET', "assets/shaders/ub_fshader.glsl", false);
		r.send(null);
		if (r.status == 200) {
			uberFShader = r.responseText;
		}
    
		// prefix preprocessor settings
		var vshader = preproc + uberVShader; 
		var fshader = preproc + uberFShader;

		// build output jshader  
		var uberJShader = new jshader();
		uberJShader.def = {
			'shaders': {
				'defaultVShader': vshader,				
				'defaultFShader': fshader
			},
			'techniques': { 
				'defaultTechnique': [{
					'vshader' : 'defaultVShader',
					'fshader' : 'defaultFShader',
					'attributes' : {
						'a_pos' : { 'type' : 'vec3' },
						'a_normal' : { 'type' : 'vec3' },
						'a_texcoord' : { 'type' : 'vec2' }
					},
					'params' : paramBlock,
					 'states' : {	
						'depthEnable' : true,
						'blendEnable' : false,
						'culling' : true,
						'cullFace' : "FRONT"
					 }
				}]
			}												
		};
		// initialize the jshader
		try
		{
			uberJShader.init();
		}
		catch(e)
		{
			console.log( "error initializing the uber shader: " + e );
		}
	
		// initialize shader parameters
		var technique = uberJShader.defaultTechnique;
		if (typeof caps.material != 'undefined')
		{
			technique.u_ambientColor.set(caps.material.ambientColor);
			technique.u_diffuseColor.set(caps.material.diffuseColor);
			technique.u_specularColor.set(caps.material.specularColor);
			technique.u_specularPower.set([ caps.material.specularPower ]);
		}
		if (typeof caps.lighting != 'undefined')
		{    
			for(i = 0; i < 4; ++i)
			{
				var light = caps.lighting["light" + i];
				if( typeof light != "undefined")
				{ 
					if(light.type == 'directional')
					{
						paramBlock['u_light'+i+'Dir'] = { 'type' : 'vec3' };
						technique['u_light'+i+'Dir'].set(light['direction'] || [ 0, 0, 1 ]);
					}
					else if(light.type == 'spot')
					{
						paramBlock['u_light'+i+'Spot'] = { 'type' : 'vec2' };
						technique['u_light'+i+'Pos'].set(light['position'] || [ 0, 0, 0 ]);
						var deg2Rad = Math.PI / 180;
						technique['u_light'+i+'Spot'].set([ Math.cos( ( light['spotInnerCutoff'] || 45.0 )  * deg2Rad ), 
															Math.cos( ( light['spotOuterCutoff'] || 90.0 ) * deg2Rad )]);
						technique['u_light'+i+'Atten'].set(light['attenuation'] || [ 1,0,0 ]);                
					}
					else
					{
						technique['u_light'+i+'Pos'].set(light['position'] || [ 0, 0, 0 ]);                        
						technique['u_light'+i+'Atten'].set(light['attenuation'] || [ 1,0,0 ]);                
					}
					technique['u_light'+i+'Color'].set(light['diffuseColor'] || [ 1,1,1,1 ]);
					technique['u_light'+i+'Specular'].set(light['specularColor'] || [ 1, 1, 1, 1 ]);           
				}
			}
		}
		technique.u_uvMatrix.set(caps.uvTransform || mat4.identity());
	
		var renderer = g_Engine.getContext().renderer;
		if(this._useDiffuseMap) {
			var tex = renderer.getTextureByName(caps.diffuseMap.texture, caps.diffuseMap.wrap, caps.diffuseMap.mips);
			this.registerTexture( tex );
			technique.s_diffuseMap.set( tex );
		}
		if(this._useNormalMap) {
			var tex = renderer.getTextureByName(caps.normalMap.texture, caps.normalMap.wrap, caps.normalMap.mips);
			this.registerTexture( tex );
			technique.s_normalMap.set( tex );
		}    
		if(this._useSpecularMap) {
			var tex = renderer.getTextureByName(caps.specularMap.texture, caps.specularMap.wrap);
			this.registerTexture( tex );
			technique.s_specMap.set( tex );
		}
		if(this._useEnvironmentMap) {
			var tex = renderer.getTextureByName(caps.environmentMap.texture, caps.environmentMap.wrap);
			this.registerTexture( tex );
			technique.s_envMap.set( tex );
			technique.u_envReflection.set([ caps.environmentMap.envReflection || 1.0 ] );
		}

		return uberJShader;
	};

	this.rebuildShader = function()
	{
		this._ubershaderCaps['material']['ambientColor'] = this._ambientColor;
		this._ubershaderCaps['material']['diffuseColor'] = this._diffuseColor;
		this._ubershaderCaps['material']['specularColor'] = this._specularColor;
		this._ubershaderCaps['material']['specularPower'] = this._specularPower;
		var useDiffuse = this._useDiffuseMap;
		if( !useDiffuse )
		{
			if( typeof this._ubershaderCaps['diffuseMap'] != 'undefined' )
				delete this._ubershaderCaps['diffuseMap'];
		}
		else
			this._ubershaderCaps['diffuseMap'] = this._diffuseMapOb; 
    
		var useNormal = this._useNormalMap;    
		if( !useNormal )
		{
			if( typeof this._ubershaderCaps['normalMap'] != 'undefined' )
				delete this._ubershaderCaps['normalMap'];
		}
		else
			this._ubershaderCaps['normalMap'] = this._normalMapOb; 

		var useSpecular = this._useSpecularMap;    
		if( !useSpecular )
		{
			if( typeof this._ubershaderCaps['specularMap'] != 'undefined' )
				delete this._ubershaderCaps['specularMap'];
		}
		else
			this._ubershaderCaps['specularMap'] = this._specularMapOb; 
       
		var useEnvironment = this._useEnvironmentMap;    
		if( !useEnvironment )
		{
			if( typeof this._ubershaderCaps['environmentMap'] != 'undefined' )
				delete this._ubershaderCaps['environmentMap'];
		}
		else
			this._ubershaderCaps['environmentMap'] = this._environmentMapOb; 
    
		for( i = 0; i < 4; ++i )
		{
			var useLight = this._useLights[i];  
			if( !useLight )
			{
				if( typeof this._ubershaderCaps['lighting']['light'+i] != 'undefined' )
					delete this._ubershaderCaps['lighting']['light'+i];
			}
			else
				this._ubershaderCaps['lighting']['light'+i] = this._lights[i]; 
		}
        
		var material = this._materialNode;  
		if (material)  
			material.setShader( buildUbershader(this._ubershaderCaps) );
	};
}