PageRenderTime 929ms CodeModel.GetById 121ms app.highlight 384ms RepoModel.GetById 79ms app.codeStats 1ms

/src/away3d/materials/passes/DefaultScreenPass.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 1550 lines | 1182 code | 252 blank | 116 comment | 204 complexity | 899631cc92e582f6f1123e2fb8fa8517 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1package away3d.materials.passes
   2{
   3	import away3d.arcane;
   4	import away3d.cameras.Camera3D;
   5	import away3d.core.base.IRenderable;
   6	import away3d.core.managers.Stage3DProxy;
   7	import away3d.events.ShadingMethodEvent;
   8	import away3d.lights.DirectionalLight;
   9	import away3d.lights.LightProbe;
  10	import away3d.lights.PointLight;
  11	import away3d.materials.LightSources;
  12	import away3d.materials.MaterialBase;
  13	import away3d.materials.lightpickers.LightPickerBase;
  14	import away3d.materials.methods.BasicAmbientMethod;
  15	import away3d.materials.methods.BasicDiffuseMethod;
  16	import away3d.materials.methods.BasicNormalMethod;
  17	import away3d.materials.methods.BasicSpecularMethod;
  18	import away3d.materials.methods.ColorTransformMethod;
  19	import away3d.materials.methods.EffectMethodBase;
  20	import away3d.materials.methods.MethodVO;
  21	import away3d.materials.methods.ShadingMethodBase;
  22	import away3d.materials.methods.ShadowMapMethodBase;
  23	import away3d.materials.utils.ShaderRegisterCache;
  24	import away3d.materials.utils.ShaderRegisterElement;
  25	import away3d.textures.Texture2DBase;
  26
  27	import flash.display3D.Context3D;
  28	import flash.display3D.Context3DProgramType;
  29	import flash.display3D.Context3DVertexBufferFormat;
  30	import flash.geom.ColorTransform;
  31	import flash.geom.Matrix;
  32	import flash.geom.Vector3D;
  33
  34	use namespace arcane;
  35
  36	/**
  37	 * DefaultScreenPass is a shader pass that uses shader methods to compile a complete program.
  38	 *
  39	 * @see away3d.materials.methods.ShadingMethodBase
  40	 */
  41
  42	// TODO: Remove compilation from this class, gets messy. Only perform rendering here.
  43	public class DefaultScreenPass extends MaterialPassBase
  44	{
  45//		private var _cameraPositionData : Vector.<Number> = Vector.<Number>([0, 0, 0, 1]);
  46//		private var _lightData : Vector.<Number>;
  47//		private var _uvTransformData : Vector.<Number>;
  48
  49		// todo: create something similar for diffuse: useOnlyProbesDiffuse - ignoring normal lights?
  50		// or: for both, provide mode: LightSourceMode.LIGHTS = 0x01, LightSourceMode.PROBES = 0x02, LightSourceMode.ALL = 0x03
  51		private var _specularLightSources : uint = 0x01;
  52		private var _diffuseLightSources : uint = 0x03;
  53		private var _combinedLightSources : uint;
  54
  55		private var _colorTransformMethod : ColorTransformMethod;
  56		private var _colorTransformMethodVO : MethodVO;
  57		private var _normalMethod : BasicNormalMethod;
  58		private var _normalMethodVO : MethodVO;
  59		private var _ambientMethod : BasicAmbientMethod;
  60		private var _ambientMethodVO : MethodVO;
  61		private var _shadowMethod : ShadowMapMethodBase;
  62		private var _shadowMethodVO : MethodVO;
  63		private var _diffuseMethod : BasicDiffuseMethod;
  64		private var _diffuseMethodVO : MethodVO;
  65		private var _specularMethod : BasicSpecularMethod;
  66		private var _specularMethodVO : MethodVO;
  67		private var _methods : Vector.<MethodSet>;
  68		private var _registerCache : ShaderRegisterCache;
  69		private var _vertexCode : String;
  70		private var _fragmentCode : String;
  71		private var _projectionDependencies : uint;
  72		private var _normalDependencies : uint;
  73		private var _viewDirDependencies : uint;
  74		private var _uvDependencies : uint;
  75		private var _secondaryUVDependencies : uint;
  76		private var _globalPosDependencies : uint;
  77
  78		// registers
  79		protected var _uvBufferIndex : int;
  80		protected var _secondaryUVBufferIndex : int;
  81		protected var _normalBufferIndex : int;
  82		protected var _tangentBufferIndex : int;
  83		protected var _sceneMatrixIndex : int;
  84		protected var _sceneNormalMatrixIndex : int;
  85		protected var _lightDataIndex : int;
  86		protected var _cameraPositionIndex : int;
  87		protected var _uvTransformIndex : int;
  88
  89		private var _projectionFragmentReg : ShaderRegisterElement;
  90		private var _normalFragmentReg : ShaderRegisterElement;
  91		private var _viewDirFragmentReg : ShaderRegisterElement;
  92		private var _lightInputIndices : Vector.<uint>;
  93		private var _lightProbeDiffuseIndices : Vector.<uint>;
  94		private var _lightProbeSpecularIndices : Vector.<uint>;
  95
  96		private var _normalVarying : ShaderRegisterElement;
  97		private var _tangentVarying : ShaderRegisterElement;
  98		private var _bitangentVarying : ShaderRegisterElement;
  99		private var _uvVaryingReg : ShaderRegisterElement;
 100		private var _secondaryUVVaryingReg : ShaderRegisterElement;
 101		private var _viewDirVaryingReg : ShaderRegisterElement;
 102
 103		private var _shadedTargetReg : ShaderRegisterElement;
 104		private var _globalPositionVertexReg : ShaderRegisterElement;
 105		private var _globalPositionVaryingReg : ShaderRegisterElement;
 106		private var _localPositionRegister : ShaderRegisterElement;
 107		private var _positionMatrixRegs : Vector.<ShaderRegisterElement>;
 108		private var _normalInput : ShaderRegisterElement;
 109		private var _tangentInput : ShaderRegisterElement;
 110		private var _animatedNormalReg : ShaderRegisterElement;
 111		private var _animatedTangentReg : ShaderRegisterElement;
 112		private var _commonsReg : ShaderRegisterElement;
 113		private var _commonsDataIndex : int;
 114
 115//		private var _commonsData : Vector.<Number> = Vector.<Number>([.5, 0, 0, 1]);
 116		private var _vertexConstantIndex : uint;
 117		private var _vertexConstantData : Vector.<Number> = new Vector.<Number>();
 118		private var _fragmentConstantData : Vector.<Number> = new Vector.<Number>();
 119
 120		arcane var _passes : Vector.<MaterialPassBase>;
 121		arcane var _passesDirty : Boolean;
 122		private var _animateUVs : Boolean;
 123
 124		private var _numLights : int;
 125		private var _lightDataLength : int;
 126
 127		private var _pointLightRegisters : Vector.<ShaderRegisterElement>;
 128		private var _dirLightRegisters : Vector.<ShaderRegisterElement>;
 129		private var _diffuseLightIndex : int;
 130		private var _specularLightIndex : int;
 131		private var _probeWeightsIndex : int;
 132		private var _numProbeRegisters : uint;
 133		private var _usingSpecularMethod : Boolean;
 134		private var _usesGlobalPosFragment : Boolean = true;
 135		private var _tangentDependencies : int;
 136
 137		private var _ambientLightR : Number;
 138		private var _ambientLightG : Number;
 139		private var _ambientLightB : Number;
 140		
 141		private var _projectedTargetRegister : String;
 142
 143
 144
 145		/**
 146		 * Creates a new DefaultScreenPass objects.
 147		 */
 148		public function DefaultScreenPass(material : MaterialBase)
 149		{
 150			super();
 151			_material = material;
 152
 153			init();
 154		}
 155
 156		private function init() : void
 157		{
 158			_methods = new Vector.<MethodSet>();
 159			_normalMethod = new BasicNormalMethod();
 160			_ambientMethod = new BasicAmbientMethod();
 161			_diffuseMethod = new BasicDiffuseMethod();
 162			_specularMethod = new BasicSpecularMethod();
 163			_normalMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 164			_diffuseMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 165			_specularMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 166			_ambientMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 167			_normalMethodVO = _normalMethod.createMethodVO();
 168			_ambientMethodVO = _ambientMethod.createMethodVO();
 169			_diffuseMethodVO = _diffuseMethod.createMethodVO();
 170			_specularMethodVO = _specularMethod.createMethodVO();
 171		}
 172
 173		public function get animateUVs() : Boolean
 174		{
 175			return _animateUVs;
 176		}
 177
 178		public function set animateUVs(value : Boolean) : void
 179		{
 180			_animateUVs = value;
 181			if ((value && !_animateUVs) || (!value && _animateUVs)) invalidateShaderProgram();
 182		}
 183
 184		/**
 185		 * @inheritDoc
 186		 */
 187		override public function set mipmap(value : Boolean) : void
 188		{
 189			if (_mipmap == value) return;
 190			super.mipmap = value;
 191		}
 192
 193		public function get specularLightSources() : uint
 194		{
 195			return _specularLightSources;
 196		}
 197
 198		public function set specularLightSources(value : uint) : void
 199		{
 200			_specularLightSources = value;
 201		}
 202
 203		public function get diffuseLightSources() : uint
 204		{
 205			return _diffuseLightSources;
 206		}
 207
 208		public function set diffuseLightSources(value : uint) : void
 209		{
 210			_diffuseLightSources = value;
 211		}
 212
 213		/**
 214		 * The ColorTransform object to transform the colour of the material with.
 215		 */
 216		public function get colorTransform() : ColorTransform
 217		{
 218			return _colorTransformMethod ? _colorTransformMethod.colorTransform : null;
 219		}
 220
 221		public function set colorTransform(value : ColorTransform) : void
 222		{
 223			if (value) {
 224				colorTransformMethod ||= new ColorTransformMethod();
 225				_colorTransformMethod.colorTransform = value;
 226			}
 227			else if (!value) {
 228				if (_colorTransformMethod)
 229					colorTransformMethod = null;
 230				colorTransformMethod = _colorTransformMethod = null;
 231			}
 232		}
 233
 234		/**
 235		 * @inheritDoc
 236		 */
 237		override public function dispose() : void
 238		{
 239			super.dispose();
 240
 241			_normalMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 242			_normalMethod.dispose();
 243			_diffuseMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 244			_diffuseMethod.dispose();
 245			if (_shadowMethod) {
 246				_diffuseMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 247				_shadowMethod.dispose();
 248			}
 249			_ambientMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 250			_ambientMethod.dispose();
 251			if (_specularMethod) {
 252				_ambientMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 253				_specularMethod.dispose();
 254			}
 255			if (_colorTransformMethod) {
 256				_colorTransformMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 257				_colorTransformMethod.dispose();
 258			}
 259			for (var i : int = 0; i < _methods.length; ++i) {
 260				_methods[i].method.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 261				_methods[i].method.dispose();
 262			}
 263
 264			_methods = null;
 265		}
 266
 267		/**
 268		 * Adds a method to change the material after all lighting is performed.
 269		 * @param method The method to be added.
 270		 */
 271		public function addMethod(method : EffectMethodBase) : void
 272		{
 273			_methods.push(new MethodSet(method));
 274			method.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 275			invalidateShaderProgram();
 276		}
 277
 278		public function hasMethod(method : EffectMethodBase) : Boolean
 279		{
 280			return getMethodSetForMethod(method) != null;
 281		}
 282
 283		/**
 284		 * Inserts a method to change the material after all lighting is performed at the given index.
 285		 * @param method The method to be added.
 286		 * @param index The index of the method's occurrence
 287		 */
 288		public function addMethodAt(method : EffectMethodBase, index : int) : void
 289		{
 290			_methods.splice(index, 0, new MethodSet(method));
 291			method.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 292			invalidateShaderProgram();
 293		}
 294
 295		public function getMethodAt(index : int) : EffectMethodBase
 296		{
 297			return EffectMethodBase(_methods[index].method);
 298		}
 299
 300		public function get numMethods() : int
 301		{
 302			return _methods.length;
 303		}
 304
 305		/**
 306		 * Removes a method from the pass.
 307		 * @param method The method to be removed.
 308		 */
 309		public function removeMethod(method : EffectMethodBase) : void
 310		{
 311			var methodSet : MethodSet = getMethodSetForMethod(method);
 312			if (methodSet != null) {
 313				var index : int = _methods.indexOf(methodSet);
 314				_methods.splice(index, 1);
 315				method.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 316				invalidateShaderProgram();
 317			}
 318		}
 319
 320		/**
 321		 * The tangent space normal map to influence the direction of the surface for each texel.
 322		 */
 323		public function get normalMap() : Texture2DBase
 324		{
 325			return _normalMethod.normalMap;
 326		}
 327
 328		public function set normalMap(value : Texture2DBase) : void
 329		{
 330			_normalMethod.normalMap = value;
 331		}
 332
 333		/**
 334		 * @inheritDoc
 335		 */
 336
 337		public function get normalMethod() : BasicNormalMethod
 338		{
 339			return _normalMethod;
 340		}
 341
 342		public function set normalMethod(value : BasicNormalMethod) : void
 343		{
 344			_normalMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 345			value.copyFrom(_normalMethod);
 346			_normalMethod = value;
 347			_normalMethodVO = _normalMethod.createMethodVO();
 348			_normalMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 349			invalidateShaderProgram();
 350		}
 351
 352		public function get ambientMethod() : BasicAmbientMethod
 353		{
 354			return _ambientMethod;
 355		}
 356
 357		public function set ambientMethod(value : BasicAmbientMethod) : void
 358		{
 359			_ambientMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 360			value.copyFrom(_ambientMethod);
 361			_ambientMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 362			_ambientMethod = value;
 363			_ambientMethodVO = _ambientMethod.createMethodVO();
 364			invalidateShaderProgram();
 365		}
 366
 367		public function get shadowMethod() : ShadowMapMethodBase
 368		{
 369			return _shadowMethod;
 370		}
 371
 372		public function set shadowMethod(value : ShadowMapMethodBase) : void
 373		{
 374			if (_shadowMethod) _shadowMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 375			_shadowMethod = value;
 376			if (_shadowMethod) {
 377				_shadowMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 378				_shadowMethodVO = _shadowMethod.createMethodVO();
 379			}
 380			else
 381				_shadowMethodVO = null;
 382			invalidateShaderProgram();
 383		}
 384
 385		/**
 386		 * The method to perform diffuse shading.
 387		 */
 388		public function get diffuseMethod() : BasicDiffuseMethod
 389		{
 390			return _diffuseMethod;
 391		}
 392
 393		public function set diffuseMethod(value : BasicDiffuseMethod) : void
 394		{
 395			_diffuseMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 396			value.copyFrom(_diffuseMethod);
 397			_diffuseMethod = value;
 398			_diffuseMethodVO = _diffuseMethod.createMethodVO();
 399			_diffuseMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 400			invalidateShaderProgram();
 401		}
 402
 403		/**
 404		 * The method to perform specular shading.
 405		 */
 406		public function get specularMethod() : BasicSpecularMethod
 407		{
 408			return _specularMethod;
 409		}
 410
 411		public function set specularMethod(value : BasicSpecularMethod) : void
 412		{
 413			if (_specularMethod) {
 414				_specularMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 415				if (value) value.copyFrom(_specularMethod);
 416			}
 417
 418			_specularMethod = value;
 419			if (_specularMethod) {
 420				_specularMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 421				_specularMethodVO = _specularMethod.createMethodVO();
 422			}
 423			else _specularMethodVO = null;
 424
 425			invalidateShaderProgram();
 426		}
 427
 428
 429
 430		/**
 431		 * @private
 432		 */
 433		arcane function get colorTransformMethod() : ColorTransformMethod
 434		{
 435			return _colorTransformMethod;
 436		}
 437
 438		arcane function set colorTransformMethod(value : ColorTransformMethod) : void
 439		{
 440			if (_colorTransformMethod == value) return;
 441			if (_colorTransformMethod) _colorTransformMethod.removeEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 442			if (!_colorTransformMethod || !value) invalidateShaderProgram();
 443
 444			_colorTransformMethod = value;
 445			if (_colorTransformMethod) {
 446				_colorTransformMethod.addEventListener(ShadingMethodEvent.SHADER_INVALIDATED, onShaderInvalidated);
 447				_colorTransformMethodVO = _colorTransformMethod.createMethodVO();
 448			}
 449			else _colorTransformMethodVO = null;
 450		}
 451
 452		arcane override function set numPointLights(value : uint) : void
 453		{
 454			super.numPointLights = value;
 455			invalidateShaderProgram();
 456		}
 457
 458		arcane override function set numDirectionalLights(value : uint) : void
 459		{
 460			super.numDirectionalLights = value;
 461			invalidateShaderProgram();
 462		}
 463
 464		arcane override function set numLightProbes(value : uint) : void
 465		{
 466			super.numLightProbes = value;
 467			invalidateShaderProgram();
 468		}
 469
 470		/**
 471		 * @inheritDoc
 472		 */
 473		arcane override function getVertexCode(animatorCode : String) : String
 474		{
 475			var normal : String = _animationTargetRegisters.length > 1? _animationTargetRegisters[1] : null;
 476			var projectionVertexCode : String = getProjectionCode(_animationTargetRegisters[0], _projectedTargetRegister, normal);
 477			_vertexCode = animatorCode + projectionVertexCode + _vertexCode;
 478			return _vertexCode;
 479		}
 480
 481		private function getProjectionCode(positionRegister : String, projectionRegister : String, normalRegister : String) : String
 482		{
 483			var code : String = "";
 484			var pos : String = positionRegister;
 485
 486			// if we need projection somewhere
 487			if (projectionRegister) {
 488				code += "m44 "+projectionRegister+", " + pos + ", vc0		\n" +
 489						"mov vt7, " + projectionRegister + "\n" +
 490						"mul op, vt7, vc4\n";
 491			}
 492			else {
 493				code += "m44 vt7, "+pos+", vc0		\n" +
 494						"mul op, vt7, vc4\n";	// 4x4 matrix transform from stream 0 to output clipspace
 495			}
 496			return code;
 497		}
 498
 499		/**
 500		 * @inheritDoc
 501		 */
 502		arcane override function getFragmentCode() : String
 503		{
 504			return _fragmentCode;
 505		}
 506
 507		/**
 508		 * @inheritDoc
 509		 */
 510		override arcane function activate(stage3DProxy : Stage3DProxy, camera : Camera3D, textureRatioX : Number, textureRatioY : Number) : void
 511		{
 512			var context : Context3D = stage3DProxy._context3D;
 513			var len : uint = _methods.length;
 514
 515			super.activate(stage3DProxy, camera, textureRatioX, textureRatioY);
 516
 517			if (_normalDependencies > 0 && _normalMethod.hasOutput) _normalMethod.activate(_normalMethodVO, stage3DProxy);
 518			_ambientMethod.activate(_ambientMethodVO, stage3DProxy);
 519			if (_shadowMethod) _shadowMethod.activate(_shadowMethodVO, stage3DProxy);
 520			_diffuseMethod.activate(_diffuseMethodVO, stage3DProxy);
 521			if (_usingSpecularMethod) _specularMethod.activate(_specularMethodVO, stage3DProxy);
 522			if (_colorTransformMethod) _colorTransformMethod.activate(_colorTransformMethodVO, stage3DProxy);
 523
 524			for (var i : int = 0; i < len; ++i) {
 525				var set : MethodSet = _methods[i];
 526				set.method.activate(set.data, stage3DProxy);
 527			}
 528
 529			if (_cameraPositionIndex >= 0) {
 530				var pos : Vector3D = camera.scenePosition;
 531				_vertexConstantData[_cameraPositionIndex] = pos.x;
 532				_vertexConstantData[_cameraPositionIndex + 1] = pos.y;
 533				_vertexConstantData[_cameraPositionIndex + 2] = pos.z;
 534			}
 535		}
 536
 537		/**
 538		 * @inheritDoc
 539		 */
 540		arcane override function deactivate(stage3DProxy : Stage3DProxy) : void
 541		{
 542			super.deactivate(stage3DProxy);
 543			var len : uint = _methods.length;
 544
 545			if (_normalDependencies > 0 && _normalMethod.hasOutput) _normalMethod.deactivate(_normalMethodVO, stage3DProxy);
 546			_ambientMethod.deactivate(_ambientMethodVO, stage3DProxy);
 547			if (_shadowMethod) _shadowMethod.deactivate(_shadowMethodVO, stage3DProxy);
 548			_diffuseMethod.deactivate(_diffuseMethodVO, stage3DProxy);
 549			if (_usingSpecularMethod) _specularMethod.deactivate(_specularMethodVO, stage3DProxy);
 550			if (_colorTransformMethod) _colorTransformMethod.deactivate(_colorTransformMethodVO, stage3DProxy);
 551
 552			var set : MethodSet;
 553			for (var i : uint = 0; i < len; ++i) {
 554				set = _methods[i];
 555				set.method.deactivate(set.data, stage3DProxy);
 556			}
 557		}
 558
 559		/**
 560		 * @inheritDoc
 561		 */
 562		arcane override function render(renderable : IRenderable, stage3DProxy : Stage3DProxy, camera : Camera3D, lightPicker : LightPickerBase) : void
 563		{
 564			var i : uint;
 565			var context : Context3D = stage3DProxy._context3D;
 566			if (_uvBufferIndex >= 0) stage3DProxy.setSimpleVertexBuffer(_uvBufferIndex, renderable.getUVBuffer(stage3DProxy), Context3DVertexBufferFormat.FLOAT_2, renderable.UVBufferOffset);
 567			if (_secondaryUVBufferIndex >= 0) stage3DProxy.setSimpleVertexBuffer(_secondaryUVBufferIndex, renderable.getSecondaryUVBuffer(stage3DProxy), Context3DVertexBufferFormat.FLOAT_2, renderable.secondaryUVBufferOffset);
 568			if (_normalBufferIndex >= 0) stage3DProxy.setSimpleVertexBuffer(_normalBufferIndex, renderable.getVertexNormalBuffer(stage3DProxy), Context3DVertexBufferFormat.FLOAT_3, renderable.normalBufferOffset);
 569			if (_tangentBufferIndex >= 0) stage3DProxy.setSimpleVertexBuffer(_tangentBufferIndex, renderable.getVertexTangentBuffer(stage3DProxy), Context3DVertexBufferFormat.FLOAT_3, renderable.tangentBufferOffset);
 570
 571			var uvTransform : Matrix;
 572			if (_animateUVs) {
 573				uvTransform = renderable.uvTransform;
 574				if (uvTransform) {
 575					_vertexConstantData[_uvTransformIndex] = uvTransform.a;
 576					_vertexConstantData[_uvTransformIndex+1] = uvTransform.b;
 577					_vertexConstantData[_uvTransformIndex+3] = uvTransform.tx;
 578					_vertexConstantData[_uvTransformIndex+4] = uvTransform.c;
 579					_vertexConstantData[_uvTransformIndex+5] = uvTransform.d;
 580					_vertexConstantData[_uvTransformIndex+7] = uvTransform.ty;
 581				}
 582				else {
 583					trace("Warning: animateUVs is set to true with an IRenderable without a uvTransform. Identity matrix assumed.");
 584					_vertexConstantData[_uvTransformIndex] = 1;
 585					_vertexConstantData[_uvTransformIndex+1] = 0;
 586					_vertexConstantData[_uvTransformIndex+3] = 0;
 587					_vertexConstantData[_uvTransformIndex+4] = 0;
 588					_vertexConstantData[_uvTransformIndex+5] = 1;
 589					_vertexConstantData[_uvTransformIndex+7] = 0;
 590				}
 591			}
 592
 593			if (_numLights > 0 && (_combinedLightSources & LightSources.LIGHTS))
 594				updateLights(lightPicker.directionalLights, lightPicker.pointLights, stage3DProxy);
 595
 596			if (_numLightProbes > 0 && (_combinedLightSources & LightSources.PROBES))
 597				updateProbes(lightPicker.lightProbes, lightPicker.lightProbeWeights, stage3DProxy);
 598
 599			if (_sceneMatrixIndex >= 0)
 600				renderable.sceneTransform.copyRawDataTo(_vertexConstantData, _sceneMatrixIndex, true);
 601
 602			if (_sceneNormalMatrixIndex >= 0)
 603				renderable.inverseSceneTransform.copyRawDataTo(_vertexConstantData, _sceneNormalMatrixIndex, false);
 604
 605			if (_normalDependencies > 0 && _normalMethod.hasOutput)
 606				_normalMethod.setRenderState(_normalMethodVO, renderable, stage3DProxy, camera);
 607
 608			_ambientMethod.setRenderState(_ambientMethodVO, renderable, stage3DProxy, camera);
 609			_ambientMethod._lightAmbientR = _ambientLightR;
 610			_ambientMethod._lightAmbientG = _ambientLightG;
 611			_ambientMethod._lightAmbientB = _ambientLightB;
 612
 613			if (_shadowMethod) _shadowMethod.setRenderState(_shadowMethodVO, renderable, stage3DProxy, camera);
 614			_diffuseMethod.setRenderState(_diffuseMethodVO, renderable, stage3DProxy, camera);
 615			if (_usingSpecularMethod) _specularMethod.setRenderState(_specularMethodVO, renderable, stage3DProxy, camera);
 616			if (_colorTransformMethod) _colorTransformMethod.setRenderState(_colorTransformMethodVO, renderable, stage3DProxy, camera);
 617
 618			var len : uint = _methods.length;
 619			for (i = 0; i < len; ++i) {
 620				var set : MethodSet = _methods[i];
 621				set.method.setRenderState(set.data, renderable, stage3DProxy, camera);
 622			}
 623
 624			context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, _vertexConstantIndex, _vertexConstantData, _numUsedVertexConstants-_vertexConstantIndex);
 625			context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, _fragmentConstantData, _numUsedFragmentConstants);
 626
 627			super.render(renderable, stage3DProxy, camera, lightPicker);
 628		}
 629
 630
 631		/**
 632		 * Marks the shader program as invalid, so it will be recompiled before the next render.
 633		 */
 634		arcane override function invalidateShaderProgram(updateMaterial : Boolean = true) : void
 635		{
 636			super.invalidateShaderProgram(updateMaterial);
 637			_passesDirty = true;
 638
 639			_passes = new Vector.<MaterialPassBase>();
 640			if (_normalMethod.hasOutput) addPasses(_normalMethod.passes);
 641			addPasses(_ambientMethod.passes);
 642			if (_shadowMethod) addPasses(_shadowMethod.passes);
 643			addPasses(_diffuseMethod.passes);
 644			if (_specularMethod) addPasses(_specularMethod.passes);
 645			if (_colorTransformMethod) addPasses(_colorTransformMethod.passes);
 646
 647			for (var i : uint = 0; i < _methods.length; ++i) {
 648				addPasses(_methods[i].method.passes);
 649			}
 650		}
 651
 652		/**
 653		 * @inheritDoc
 654		 */
 655		override arcane function updateProgram(stage3DProxy : Stage3DProxy) : void
 656		{
 657			reset();
 658
 659			super.updateProgram(stage3DProxy);
 660		}
 661
 662		/**
 663		 * Resets the compilation state.
 664		 */
 665		private function reset() : void
 666		{
 667			_numLights = _numPointLights + _numDirectionalLights;
 668			_numProbeRegisters = Math.ceil(_numLightProbes/4);
 669
 670			if (_specularMethod)
 671				_combinedLightSources = _specularLightSources | _diffuseLightSources;
 672			else
 673				_combinedLightSources = _diffuseLightSources;
 674
 675			_usingSpecularMethod = 	_specularMethod && (
 676									(_numLights > 0 && (_specularLightSources & LightSources.LIGHTS)) ||
 677									(_numLightProbes > 0 && (_specularLightSources & LightSources.PROBES)));
 678
 679			_uvTransformIndex = -1;
 680			_cameraPositionIndex = -1;
 681			_commonsDataIndex = -1;
 682			_uvBufferIndex = -1;
 683			_secondaryUVBufferIndex = -1;
 684			_normalBufferIndex = -1;
 685			_tangentBufferIndex = -1;
 686			_lightDataIndex = -1;
 687			_sceneMatrixIndex = -1;
 688			_sceneNormalMatrixIndex = -1;
 689			_probeWeightsIndex = -1;
 690
 691			_pointLightRegisters = new Vector.<ShaderRegisterElement>(_numPointLights*3, true);
 692			_dirLightRegisters = new Vector.<ShaderRegisterElement>(_numDirectionalLights*3, true);
 693			_lightDataLength = _numLights*3;
 694
 695			_registerCache = new ShaderRegisterCache();
 696			_vertexConstantIndex = _registerCache.vertexConstantOffset = 5;
 697			_registerCache.vertexAttributesOffset = 1;
 698			_registerCache.reset();
 699
 700			_lightInputIndices = new Vector.<uint>(_numLights, true);
 701
 702			_commonsReg = null;
 703			_numUsedVertexConstants = 0;
 704			_numUsedStreams = 1;
 705
 706			_animatableAttributes = ["va0"];
 707			_animationTargetRegisters = ["vt0"];
 708			_vertexCode = "";
 709			_fragmentCode = "";
 710			_projectedTargetRegister = null;
 711
 712			_localPositionRegister = _registerCache.getFreeVertexVectorTemp();
 713			_registerCache.addVertexTempUsages(_localPositionRegister, 1);
 714
 715			compile();
 716
 717			_numUsedVertexConstants = _registerCache.numUsedVertexConstants;
 718			_numUsedFragmentConstants = _registerCache.numUsedFragmentConstants;
 719			_numUsedStreams = _registerCache.numUsedStreams;
 720			_numUsedTextures = _registerCache.numUsedTextures;
 721			_vertexConstantData.length = (_numUsedVertexConstants-_vertexConstantIndex)*4;
 722			_fragmentConstantData.length = _numUsedFragmentConstants*4;
 723
 724			initCommonsData();
 725			if (_uvTransformIndex >= 0)
 726				initUVTransformData();
 727			if (_cameraPositionIndex >= 0)
 728				_vertexConstantData[_cameraPositionIndex + 3] = 1;
 729
 730			updateMethodConstants();
 731			cleanUp();
 732		}
 733
 734		private function updateMethodConstants() : void
 735		{
 736			if (_normalMethod) _normalMethod.initConstants(_normalMethodVO);
 737			if (_diffuseMethod) _diffuseMethod.initConstants(_diffuseMethodVO);
 738			if (_ambientMethod) _ambientMethod.initConstants(_ambientMethodVO);
 739			if (_specularMethod) _specularMethod.initConstants(_specularMethodVO);
 740			if (_shadowMethod) _shadowMethod.initConstants(_shadowMethodVO);
 741			if (_colorTransformMethod) _colorTransformMethod.initConstants(_colorTransformMethodVO);
 742
 743			var len : uint = _methods.length;
 744			for (var i : uint = 0; i < len; ++i) {
 745				_methods[i].method.initConstants(_methods[i].data);
 746			}
 747		}
 748
 749		private function initUVTransformData() : void
 750		{
 751			_vertexConstantData[_uvTransformIndex] = 1;
 752			_vertexConstantData[_uvTransformIndex+1] = 0;
 753			_vertexConstantData[_uvTransformIndex+2] = 0;
 754			_vertexConstantData[_uvTransformIndex+3] = 0;
 755			_vertexConstantData[_uvTransformIndex+4] = 0;
 756			_vertexConstantData[_uvTransformIndex+5] = 1;
 757			_vertexConstantData[_uvTransformIndex+6] = 0;
 758			_vertexConstantData[_uvTransformIndex+7] = 0;
 759		}
 760
 761		private function initCommonsData() : void
 762		{
 763			_fragmentConstantData[_commonsDataIndex] = .5;
 764			_fragmentConstantData[_commonsDataIndex + 1] = 0;
 765			_fragmentConstantData[_commonsDataIndex + 2] = 1/255;
 766			_fragmentConstantData[_commonsDataIndex + 3] = 1;
 767		}
 768
 769		private function cleanUp() : void
 770		{
 771			nullifyCompilationData();
 772			cleanUpMethods();
 773		}
 774
 775		private function nullifyCompilationData() : void
 776		{
 777			_pointLightRegisters = null;
 778			_dirLightRegisters = null;
 779
 780			_projectionFragmentReg = null;
 781			_viewDirFragmentReg = null;
 782
 783			_normalVarying = null;
 784			_tangentVarying = null;
 785			_bitangentVarying = null;
 786			_uvVaryingReg = null;
 787			_secondaryUVVaryingReg = null;
 788			_viewDirVaryingReg = null;
 789
 790			_shadedTargetReg = null;
 791			_globalPositionVertexReg = null;
 792			_globalPositionVaryingReg = null;
 793			_localPositionRegister = null;
 794			_positionMatrixRegs = null;
 795			_normalInput = null;
 796			_tangentInput = null;
 797			_animatedNormalReg = null;
 798			_animatedTangentReg = null;
 799			_commonsReg = null;
 800
 801			_registerCache.dispose();
 802			_registerCache = null;
 803		}
 804
 805		private function cleanUpMethods() : void
 806		{
 807			if (_normalMethod) _normalMethod.cleanCompilationData();
 808			if (_diffuseMethod) _diffuseMethod.cleanCompilationData();
 809			if (_ambientMethod) _ambientMethod.cleanCompilationData();
 810			if (_specularMethod) _specularMethod.cleanCompilationData();
 811			if (_shadowMethod) _shadowMethod.cleanCompilationData();
 812			if (_colorTransformMethod) _colorTransformMethod.cleanCompilationData();
 813
 814			var len : uint = _methods.length;
 815			for (var i : uint = 0; i < len; ++i) {
 816				_methods[i].method.cleanCompilationData();
 817			}
 818		}
 819
 820		/**
 821		 * Compiles the actual shader code.
 822		 */
 823		private function compile() : void
 824		{
 825			createCommons();
 826			calculateDependencies();
 827
 828			if (_projectionDependencies > 0) compileProjCode();
 829			if (_uvDependencies > 0) compileUVCode();
 830			if (_secondaryUVDependencies > 0) compileSecondaryUVCode();
 831			if (_globalPosDependencies > 0) compileGlobalPositionCode();
 832
 833			updateMethodRegisters(_normalMethod);
 834			if (_normalDependencies > 0) {
 835				// needs to be created before view
 836				_animatedNormalReg = _registerCache.getFreeVertexVectorTemp();
 837				_registerCache.addVertexTempUsages(_animatedNormalReg, 1);
 838				if (_normalDependencies > 0) compileNormalCode();
 839			}
 840			if (_viewDirDependencies > 0) compileViewDirCode();
 841
 842
 843			updateMethodRegisters(_diffuseMethod);
 844			if (_shadowMethod) updateMethodRegisters(_shadowMethod);
 845			updateMethodRegisters(_ambientMethod);
 846			if (_specularMethod) updateMethodRegisters(_specularMethod);
 847			if (_colorTransformMethod) updateMethodRegisters(_colorTransformMethod);
 848
 849			for (var i : uint = 0; i < _methods.length; ++i)
 850				updateMethodRegisters(_methods[i].method);
 851
 852			_shadedTargetReg = _registerCache.getFreeFragmentVectorTemp();
 853			_registerCache.addFragmentTempUsages(_shadedTargetReg, 1);
 854
 855			compileLightingCode();
 856			compileMethods();
 857
 858			_fragmentCode += "mov " + _registerCache.fragmentOutputRegister + ", " + _shadedTargetReg + "\n";
 859
 860			_registerCache.removeFragmentTempUsage(_shadedTargetReg);
 861		}
 862
 863		private function compileProjCode() : void
 864		{
 865			_projectionFragmentReg = _registerCache.getFreeVarying();
 866			_projectedTargetRegister = _registerCache.getFreeVertexVectorTemp().toString();
 867
 868			_vertexCode += "mov " + _projectionFragmentReg + ", " + _projectedTargetRegister + "\n";
 869		}
 870
 871		private function updateMethodRegisters(method : ShadingMethodBase) : void
 872		{
 873			method.globalPosReg = _globalPositionVaryingReg;
 874			method.normalFragmentReg = _normalFragmentReg;
 875			method.projectionReg = _projectionFragmentReg;
 876			method.UVFragmentReg = _uvVaryingReg;
 877			method.tangentVaryingReg = _tangentVarying;
 878			method.secondaryUVFragmentReg = _secondaryUVVaryingReg;
 879			method.viewDirFragmentReg = _viewDirFragmentReg;
 880			method.viewDirVaryingReg = _viewDirVaryingReg;
 881		}
 882
 883		/**
 884		 * Adds passes to the list.
 885		 */
 886		private function addPasses(passes : Vector.<MaterialPassBase>) : void
 887		{
 888			if (!passes) return;
 889
 890			var len : uint = passes.length;
 891
 892			for (var i : uint = 0; i < len; ++i) {
 893				passes[i].material = material;
 894				_passes.push(passes[i]);
 895			}
 896		}
 897
 898		/**
 899		 * Calculates register dependencies for commonly used data.
 900		 */
 901		private function calculateDependencies() : void
 902		{
 903			var len : uint;
 904
 905			_normalDependencies = 0;
 906			_viewDirDependencies = 0;
 907			_uvDependencies = 0;
 908			_secondaryUVDependencies = 0;
 909			_globalPosDependencies = 0;
 910
 911			setupAndCountMethodDependencies(_diffuseMethod, _diffuseMethodVO);
 912			if (_shadowMethod) setupAndCountMethodDependencies(_shadowMethod, _shadowMethodVO);
 913			setupAndCountMethodDependencies(_ambientMethod, _ambientMethodVO);
 914			if (_usingSpecularMethod) setupAndCountMethodDependencies(_specularMethod, _specularMethodVO);
 915			if (_colorTransformMethod) setupAndCountMethodDependencies(_colorTransformMethod, _colorTransformMethodVO);
 916
 917			len = _methods.length;
 918			for (var i : uint = 0; i < len; ++i)
 919				setupAndCountMethodDependencies(_methods[i].method, _methods[i].data);
 920
 921			if (_normalDependencies > 0 && _normalMethod.hasOutput) setupAndCountMethodDependencies(_normalMethod, _normalMethodVO);
 922			if (_viewDirDependencies > 0) ++_globalPosDependencies;
 923
 924			// todo: add spotlight check
 925			if (_numPointLights > 0 && (_combinedLightSources & LightSources.LIGHTS)) {
 926				++_globalPosDependencies;
 927				_usesGlobalPosFragment = true;
 928			}
 929		}
 930
 931		private function setupAndCountMethodDependencies(method : ShadingMethodBase, methodVO : MethodVO) : void
 932		{
 933			setupMethod(method, methodVO);
 934			countDependencies(methodVO);
 935		}
 936
 937		private function countDependencies(methodVO : MethodVO) : void
 938		{
 939			if (methodVO.needsProjection) ++_projectionDependencies;
 940			if (methodVO.needsGlobalPos) {
 941				++_globalPosDependencies;
 942				_usesGlobalPosFragment = true;
 943			}
 944			if (methodVO.needsNormals) ++_normalDependencies;
 945			if (methodVO.needsTangents) ++_tangentDependencies;
 946			if (methodVO.needsView) ++_viewDirDependencies;
 947			if (methodVO.needsUV) ++_uvDependencies;
 948			if (methodVO.needsSecondaryUV) ++_secondaryUVDependencies;
 949		}
 950
 951		private function setupMethod(method : ShadingMethodBase, methodVO : MethodVO) : void
 952		{
 953			method.reset();
 954			methodVO.reset();
 955			methodVO.vertexData = _vertexConstantData;
 956			methodVO.fragmentData = _fragmentConstantData;
 957			methodVO.vertexConstantsOffset = _vertexConstantIndex;
 958			methodVO.useSmoothTextures = _smooth;
 959			methodVO.repeatTextures = _repeat;
 960			methodVO.useMipmapping = _mipmap;
 961			methodVO.numLights = _numLights + _numLightProbes;
 962			method.initVO(methodVO);
 963		}
 964
 965		private function compileGlobalPositionCode() : void
 966		{
 967			_globalPositionVertexReg = _registerCache.getFreeVertexVectorTemp();
 968			_registerCache.addVertexTempUsages(_globalPositionVertexReg, _globalPosDependencies);
 969
 970			_positionMatrixRegs = new Vector.<ShaderRegisterElement>();
 971			_positionMatrixRegs[0] = _registerCache.getFreeVertexConstant();
 972			_positionMatrixRegs[1] = _registerCache.getFreeVertexConstant();
 973			_positionMatrixRegs[2] = _registerCache.getFreeVertexConstant();
 974			_registerCache.getFreeVertexConstant();
 975			_sceneMatrixIndex = (_positionMatrixRegs[0].index - _vertexConstantIndex)*4;
 976
 977			_vertexCode += 	"m44 " + _globalPositionVertexReg + ".xyz, " + _localPositionRegister.toString() + ", " + _positionMatrixRegs[0].toString() + "\n" +
 978							"mov " + _globalPositionVertexReg + ".w, " + _localPositionRegister + ".w     \n";
 979//			_registerCache.removeVertexTempUsage(_localPositionRegister);
 980
 981			// todo: add spotlight check as well
 982			if (_usesGlobalPosFragment) {
 983				_globalPositionVaryingReg = _registerCache.getFreeVarying();
 984				_vertexCode += "mov " + _globalPositionVaryingReg + ", " + _globalPositionVertexReg + "\n";
 985//				_registerCache.removeVertexTempUsage(_globalPositionVertexReg);
 986			}
 987		}
 988
 989		private function compileUVCode() : void
 990		{
 991			var uvAttributeReg : ShaderRegisterElement = _registerCache.getFreeVertexAttribute();
 992
 993			_uvVaryingReg = _registerCache.getFreeVarying();
 994			_uvBufferIndex = uvAttributeReg.index;
 995
 996			if (_animateUVs) {
 997				// a, b, 0, tx
 998				// c, d, 0, ty
 999				var uvTransform1 : ShaderRegisterElement = _registerCache.getFreeVertexConstant();
1000				var uvTransform2 : ShaderRegisterElement = _registerCache.getFreeVertexConstant();
1001				_uvTransformIndex = (uvTransform1.index - _vertexConstantIndex)*4;
1002
1003				_vertexCode += 	"dp4 " + _uvVaryingReg + ".x, " + uvAttributeReg + ", " + uvTransform1 + "\n" +
1004								"dp4 " + _uvVaryingReg + ".y, " + uvAttributeReg + ", " + uvTransform2 + "\n" +
1005								"mov " + _uvVaryingReg + ".zw, " + uvAttributeReg + ".zw \n";
1006			}
1007			else {
1008				_vertexCode += "mov " + _uvVaryingReg + ", " + uvAttributeReg + "\n";
1009			}
1010		}
1011
1012		private function compileSecondaryUVCode() : void
1013		{
1014			var uvAttributeReg : ShaderRegisterElement = _registerCache.getFreeVertexAttribute();
1015
1016			_secondaryUVVaryingReg = _registerCache.getFreeVarying();
1017			_secondaryUVBufferIndex = uvAttributeReg.index;
1018
1019			_vertexCode += "mov " + _secondaryUVVaryingReg + ", " + uvAttributeReg + "\n";
1020		}
1021
1022		private function compileNormalCode() : void
1023		{
1024			var normalMatrix : Vector.<ShaderRegisterElement> = new Vector.<ShaderRegisterElement>(3, true);
1025
1026			_normalFragmentReg = _registerCache.getFreeFragmentVectorTemp();
1027			_registerCache.addFragmentTempUsages(_normalFragmentReg, _normalDependencies);
1028
1029			if (_normalMethod.hasOutput && !_normalMethod.tangentSpace) {
1030				_vertexCode += _normalMethod.getVertexCode(_normalMethodVO, _registerCache);
1031				_fragmentCode += _normalMethod.getFragmentCode(_normalMethodVO, _registerCache, _normalFragmentReg);
1032				return;
1033			}
1034
1035			_normalInput = _registerCache.getFreeVertexAttribute();
1036			_normalBufferIndex = _normalInput.index;
1037
1038			_normalVarying = _registerCache.getFreeVarying();
1039
1040			_animatableAttributes.push(_normalInput.toString());
1041			_animationTargetRegisters.push(_animatedNormalReg.toString());
1042
1043			normalMatrix[0] = _registerCache.getFreeVertexConstant();
1044			normalMatrix[1] = _registerCache.getFreeVertexConstant();
1045			normalMatrix[2] = _registerCache.getFreeVertexConstant();
1046			_registerCache.getFreeVertexConstant();
1047			_sceneNormalMatrixIndex = (normalMatrix[0].index-_vertexConstantIndex)*4;
1048
1049			if (_normalMethod.hasOutput) {
1050				// tangent stream required
1051				compileTangentVertexCode(normalMatrix);
1052				compileTangentNormalMapFragmentCode();
1053			}
1054			else {
1055				_vertexCode += "m33 " + _normalVarying + ".xyz, " + _animatedNormalReg + ".xyz, " + normalMatrix[0] + "\n" +
1056								"mov " + _normalVarying + ".w, " + _animatedNormalReg + ".w	\n";
1057
1058				_fragmentCode += "nrm " + _normalFragmentReg + ".xyz, " + _normalVarying + ".xyz	\n" +
1059								"mov " + _normalFragmentReg + ".w, " + _normalVarying + ".w		\n";
1060
1061
1062				if (_tangentDependencies > 0) {
1063					_tangentInput = _registerCache.getFreeVertexAttribute();
1064					_tangentBufferIndex = _tangentInput.index;
1065					_tangentVarying = _registerCache.getFreeVarying();
1066					_vertexCode += "mov " + _tangentVarying + ", " + _tangentInput + "\n";
1067				}
1068			}
1069
1070			_registerCache.removeVertexTempUsage(_animatedNormalReg);
1071		}
1072
1073		private function compileTangentVertexCode(matrix : Vector.<ShaderRegisterElement>) : void
1074		{
1075			var normalTemp : ShaderRegisterElement;
1076			var tanTemp : ShaderRegisterElement;
1077			var bitanTemp1 : ShaderRegisterElement;
1078			var bitanTemp2 : ShaderRegisterElement;
1079
1080			_tangentVarying = _registerCache.getFreeVarying();
1081			_bitangentVarying = _registerCache.getFreeVarying();
1082
1083			_tangentInput = _registerCache.getFreeVertexAttribute();
1084			_tangentBufferIndex = _tangentInput.index;
1085
1086			_animatedTangentReg = _registerCache.getFreeVertexVectorTemp();
1087			_registerCache.addVertexTempUsages(_animatedTangentReg, 1);
1088			_animatableAttributes.push(_tangentInput.toString());
1089			_animationTargetRegisters.push(_animatedTangentReg.toString());
1090
1091			normalTemp = _registerCache.getFreeVertexVectorTemp();
1092			_registerCache.addVertexTempUsages(normalTemp, 1);
1093
1094			_vertexCode += 	"m33 " + normalTemp + ".xyz, " + _animatedNormalReg + ".xyz, " + matrix[0].toString() + "\n" +
1095							"nrm " + normalTemp + ".xyz, " + normalTemp + ".xyz	\n";
1096
1097			tanTemp = _registerCache.getFreeVertexVectorTemp();
1098			_registerCache.addVertexTempUsages(tanTemp, 1);
1099
1100			_vertexCode += 	"m33 " + tanTemp + ".xyz, " + _animatedTangentReg + ".xyz, " + matrix[0].toString() + "\n" +
1101							"nrm " + tanTemp + ".xyz, " + tanTemp + ".xyz	\n";
1102
1103			bitanTemp1 = _registerCache.getFreeVertexVectorTemp();
1104			_registerCache.addVertexTempUsages(bitanTemp1, 1);
1105			bitanTemp2 = _registerCache.getFreeVertexVectorTemp();
1106
1107			_vertexCode += "mul " + bitanTemp1 + ".xyz, " + normalTemp + ".yzx, " + tanTemp + ".zxy	\n" +
1108					"mul " + bitanTemp2 + ".xyz, " + normalTemp + ".zxy, " + tanTemp + ".yzx	\n" +
1109					"sub " + bitanTemp2 + ".xyz, " + bitanTemp1 + ".xyz, " + bitanTemp2 + ".xyz	\n" +
1110
1111					"mov " + _tangentVarying + ".x, " + tanTemp + ".x	\n" +
1112					"mov " + _tangentVarying + ".y, " + bitanTemp2 + ".x	\n" +
1113					"mov " + _tangentVarying + ".z, " + normalTemp + ".x	\n" +
1114					"mov " + _tangentVarying + ".w, " + _normalInput + ".w	\n" +
1115					"mov " + _bitangentVarying + ".x, " + tanTemp + ".y	\n" +
1116					"mov " + _bitangentVarying + ".y, " + bitanTemp2 + ".y	\n" +
1117					"mov " + _bitangentVarying + ".z, " + normalTemp + ".y	\n" +
1118					"mov " + _bitangentVarying + ".w, " + _normalInput + ".w	\n" +
1119					"mov " + _normalVarying + ".x, " + tanTemp + ".z	\n" +
1120					"mov " + _normalVarying + ".y, " + bitanTemp2 + ".z	\n" +
1121					"mov " + _normalVarying + ".z, " + normalTemp + ".z	\n" +
1122					"mov " + _normalVarying + ".w, " + _normalInput + ".w	\n";
1123
1124			_registerCache.removeVertexTempUsage(normalTemp);
1125			_registerCache.removeVertexTempUsage(tanTemp);
1126			_registerCache.removeVertexTempUsage(bitanTemp1);
1127			_registerCache.removeVertexTempUsage(_animatedTangentReg);
1128		}
1129
1130		private function compileTangentNormalMapFragmentCode() : void
1131		{
1132			var t : ShaderRegisterElement;
1133			var b : ShaderRegisterElement;
1134			var n : ShaderRegisterElement;
1135
1136			t = _registerCache.getFreeFragmentVectorTemp();
1137			_registerCache.addFragmentTempUsages(t, 1);
1138			b = _registerCache.getFreeFragmentVectorTemp();
1139			_registerCache.addFragmentTempUsages(b, 1);
1140			n = _registerCache.getFreeFragmentVectorTemp();
1141			_registerCache.addFragmentTempUsages(n, 1);
1142
1143			_fragmentCode += 	"nrm " + t + ".xyz, " + _tangentVarying + ".xyz	\n" +
1144								"mov " + t + ".w, " + _tangentVarying + ".w	\n" +
1145								"nrm " + b + ".xyz, " + _bitangentVarying + ".xyz	\n" +
1146								"nrm " + n + ".xyz, " + _normalVarying + ".xyz	\n";
1147
1148			var temp : ShaderRegisterElement = _registerCache.getFreeFragmentVectorTemp();
1149			_registerCache.addFragmentTempUsages(temp, 1);
1150			_fragmentCode += _normalMethod.getFragmentCode(_normalMethodVO, _registerCache, temp) +
1151							"sub " + temp + ".xyz, " + temp + ".xyz, " + _commonsReg + ".xxx	\n" +
1152							"nrm " + temp + ".xyz, " + temp + ".xyz							\n" +
1153							"m33 " + _normalFragmentReg + ".xyz, " + temp + ".xyz, " + t + "	\n" +
1154							"mov " + _normalFragmentReg + ".w,   " + _normalVarying + ".w			\n";
1155
1156			_registerCache.removeFragmentTempUsage(temp);
1157
1158			if (_normalMethodVO.needsView) _registerCache.removeFragmentTempUsage(_viewDirFragmentReg);
1159			if (_normalMethodVO.needsGlobalPos) _registerCache.removeVertexTempUsage(_globalPositionVertexReg);
1160			_registerCache.removeFragmentTempUsage(b);
1161			_registerCache.removeFragmentTempUsage(t);
1162			_registerCache.removeFragmentTempUsage(n);
1163		}
1164
1165		private function createCommons() : void
1166		{
1167			_commonsReg = _registerCache.getFreeFragmentConstant();
1168			_commonsDataIndex = _commonsReg.index*4;
1169		}
1170
1171		private function compileViewDirCode() : void
1172		{
1173			var cameraPositionReg : ShaderRegisterElement = _registerCache.getFreeVertexConstant();
1174			_viewDirVaryingReg = _registerCache.getFreeVarying();
1175			_viewDirFragmentReg = _registerCache.getFreeFragmentVectorTemp();
1176			_registerCache.addFragmentTempUsages(_viewDirFragmentReg, _viewDirDependencies);
1177
1178			_cameraPositionIndex = (cameraPositionReg.index-_vertexConstantIndex)*4;
1179
1180			_vertexCode += "sub " + _viewDirVaryingReg + ", " + cameraPositionReg + ", " + _globalPositionVertexReg + "\n";
1181			_fragmentCode += 	"nrm " + _viewDirFragmentReg + ".xyz, " + _viewDirVaryingReg + ".xyz		\n" +
1182								"mov " + _viewDirFragmentReg + ".w,   " + _viewDirVaryingReg + ".w 		\n";
1183
1184			_registerCache.removeVertexTempUsage(_globalPositionVertexReg);
1185		}
1186
1187		private function compileLightingCode() : void
1188		{
1189			var shadowReg : ShaderRegisterElement;
1190
1191			initLightRegisters();
1192
1193			_vertexCode += _diffuseMethod.getVertexCode(_diffuseMethodVO, _registerCache);
1194			_fragmentCode += _diffuseMethod.getFragmentPreLightingCode(_diffuseMethodVO, _registerCache);
1195
1196			if (_usingSpecularMethod) {
1197				_vertexCode += _specularMethod.getVertexCode(_specularMethodVO, _registerCache);
1198				_fragmentCode += _specularMethod.getFragmentPreLightingCode(_specularMethodVO, _registerCache);
1199			}
1200
1201			_diffuseLightIndex = 0;
1202			_specularLightIndex = 0;
1203
1204			if (_numLights > 0 && (_combinedLightSources & LightSources.LIGHTS)) {
1205				compileDirectionalLightCode();
1206				compilePointLightCode();
1207			}
1208			if (_numLightProbes > 0  && (_combinedLightSources & LightSources.PROBES))
1209				compileLightProbeCode();
1210
1211			_vertexCode += _ambientMethod.getVertexCode(_ambientMethodVO, _registerCache);
1212			_fragmentCode += _ambientMethod.getFragmentCode(_ambientMethodVO, _registerCache, _shadedTargetReg);
1213			if (_ambientMethodVO.needsNormals) _registerCache.removeFragmentTempUsage(_normalFragmentReg);
1214			if (_ambientMethodVO.needsView) _registerCache.removeFragmentTempUsage(_viewDirFragmentReg);
1215
1216
1217			if (_shadowMethod) {
1218				_vertexCode += _shadowMethod.getVertexCode(_shadowMethodVO, _registerCache);
1219				// using normal to contain shadow data if available is perhaps risky :s
1220				// todo: improve compilation with lifetime analysis so this isn't necessary?
1221				if (_normalDependencies == 0) {
1222					shadowReg = _registerCache.getFreeFragmentVectorTemp();
1223					_registerCache.addFragmentTempUsages(shadowReg, 1);
1224				}
1225				else
1226					shadowReg = _normalFragmentReg;
1227
1228				_diffuseMethod.shadowRegister = shadowReg;
1229				_fragmentCode += _shadowMethod.getFragmentCode(_shadowMethodVO, _registerCache, shadowReg);
1230			}
1231			_fragmentCode += _diffuseMethod.getFragmentPostLightingCode(_diffuseMethodVO, _registerCache, _shadedTargetReg);
1232
1233			if (_alphaPremultiplied) {
1234				_fragmentCode += "add " + _shadedTargetReg + ".w, " + _shadedTargetReg + ".w, " + _commonsReg + ".z\n" +
1235								 "div " + _shadedTargetReg + ".xyz, " + _shadedTargetReg + ".xyz, " + _shadedTargetReg + ".w\n" +
1236								 "sub " + _shadedTargetReg + ".w, " + _shadedTargetReg + ".w, " + _commonsReg + ".z\n"
1237								 "sat " + _shadedTargetReg + ".xyz, " + _shadedTargetReg + ".xyz\n";
1238			}
1239
1240			// resolve other dependencies as well?
1241			if (_diffuseMethodVO.needsNormals) _registerCache.removeFragmentTempUsage(_normalFragmentReg);
1242			if (_diffuseMethodVO.needsView) _registerCache.removeFragmentTempUsage(_viewDirFragmentReg);
1243
1244			if (_usingSpecularMethod) {
1245				_specularMethod.shadowRegister = shadowReg;
1246				_fragmentCode += _specularMethod.getFragmentPostLightingCode(_specularMethodVO, _registerCache, _shadedTargetReg);
1247				if (_specularMethodVO.needsNormals) _registerCache.removeFragmentTempUsage(_normalFragmentReg);
1248				if (_specularMethodVO.needsView) _registerCache.removeFragmentTempUsage(_viewDirFragmentReg);
1249			}
1250		}
1251
1252		private function initLightRegisters() : void
1253		{
1254			// init these first so we're sure they're in sequence
1255			var i : uint, len : uint;
1256
1257			len = _dirLightRegisters.length;
1258			for (i = 0; i < len; ++i) {
1259				_dirLightRegisters[i] = _registerCache.getFreeFragmentConstant();
1260				if (_lightDataIndex == -1) _lightDataIndex = _dirLightRegisters[i].index*4;
1261			}
1262
1263			len = _pointLightRegisters.length;
1264			for (i = 0; i < len; ++i) {
1265				_pointLightRegisters[i] = _registerCache.getFreeFragmentConstant();
1266				if (_lightDataIndex == -1) _lightDataIndex = _pointLightRegisters[i].index*4;
1267			}
1268		}
1269
1270		private function compileDirectionalLightCode() : void
1271		{
1272			var diffuseColorReg : ShaderRegisterElement;
1273			var specularColorReg : ShaderRegisterElement;
1274			var lightDirReg : ShaderRegisterElement;
1275			var regIndex : int;
1276			var addSpec : Boolean = _usingSpecularMethod && ((_specularLightSources & LightSources.LIGHTS) != 0);
1277			var addDiff : Boolean = (_diffuseLightSources & LightSources.LIGHTS) != 0;
1278
1279			if (!(addSpec || addDiff)) return;
1280
1281			for (var i : uint = 0; i < _numDirectionalLights; ++i) {
1282				lightDirReg = _dirLightRegisters[regIndex++];
1283				diffuseColorReg = _dirLightRegisters[regIndex++];
1284				specularColorReg = _dirLightRegisters[regIndex++];
1285				if (addDiff) {
1286					_fragmentCode += _diffuseMethod.getFragmentCodePerLight(_diffuseMethodVO, _diffuseLightIndex, lightDirReg, diffuseColorReg, _registerCache);
1287					++_diffuseLightIndex;
1288				}
1289				if (addSpec) {
1290					_fragmentCode += _specularMethod.getFragmentCodePerLight(_specularMethodVO, _specularLightIndex, lightDirReg, specularColorReg, _registerCache);
1291					++_specularLightIndex;
1292				}
1293
1294			}
1295		}
1296
1297		private function compilePointLightCode() : void
1298		{
1299			var diffuseColorReg : ShaderRegisterElement;
1300			var specularColorReg : ShaderRegisterElement;
1301			var lightPosReg : ShaderRegisterElement;
1302			var lightDirReg : ShaderRegisterElement;
1303			var regIndex : int;
1304			var addSpec : Boolean = _usingSpecularMethod && ((_specularLightSources & LightSources.LIGHTS) != 0);
1305			var addDiff : Boolean = (_diffuseLightSources & LightSources.LIGHTS) != 0;
1306
1307			if (!(addSpec || addDiff)) return;
1308
1309			for (var i : uint = 0; i < _numPointLights; ++i) {
1310				lightPosReg = _pointLightRegisters[regIndex++];
1311				diffuseColorReg = _pointLightRegisters[regIndex++];
1312				specularColorReg = _pointLightRegisters[regIndex++];
1313				lightDirReg = _registerCache.getFreeFragmentVectorTemp();
1314				_registerCache.addFragmentTempUsages(lightDirReg, 1);
1315
1316				// calculate direction
1317				_fragmentCode += "sub " + lightDirReg + ", " + lightPosReg + ", " + _globalPositionVaryingReg + "\n" +
1318				// attenuate
1319								"dp3 " + lightDirReg + ".w, " + lightDirReg + ".xyz, " + lightDirReg + ".xyz\n" +
1320								"sqt " + lightDirReg + ".w, " + lightDirReg + ".w\n" +
1321							// w = d - radis
1322								"sub " + lightDirReg + ".w, " + lightDirReg + ".w, " + diffuseColorReg + ".w\n" +
1323							// w = (d - radius)/(max-min)
1324								"mul " + lightDirReg + ".w, " + lightDirReg + ".w, " + specularColorReg + ".w\n" +
1325							// w = clamp(w, 0, 1)
1326								"sat " + lightDirReg + ".w, " + lightDirReg + ".w\n" +
1327							// w = 1-w
1328								"sub " + lightDirReg + ".w, " + lightPosReg + ".w, " + lightDirReg + ".w\n" +
1329				// normalize
1330								"nrm " + lightDirReg + ".xyz, " + lightDirReg + ".xyz	\n";
1331
1332				if (_lightDataIndex == -1) _lightDataIndex = lightPosReg.index*4;
1333				if (addDiff) {
1334					// TODO: vo can cont

Large files files are truncated, but you can click here to view the full file