PageRenderTime 64ms CodeModel.GetById 35ms app.highlight 11ms RepoModel.GetById 16ms app.codeStats 0ms

/src/away3d/materials/methods/ProjectiveTextureMethod.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 167 lines | 106 code | 19 blank | 42 comment | 10 complexity | 76d2332a25d3bc0b8c299142444ee271 MD5 | raw file
  1package away3d.materials.methods
  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.entities.TextureProjector;
  8	import away3d.materials.compilation.ShaderRegisterCache;
  9	import away3d.materials.compilation.ShaderRegisterElement;
 10	
 11	import flash.geom.Matrix3D;
 12	
 13	use namespace arcane;
 14	
 15	/**
 16	 * ProjectiveTextureMethod is a material method used to project a texture unto the surface of an object.
 17	 * This can be used for various effects apart from acting like a normal projector, such as projecting fake shadows
 18	 * unto a surface, the impact of light coming through a stained glass window, ...
 19	 */
 20	public class ProjectiveTextureMethod extends EffectMethodBase
 21	{
 22		public static const MULTIPLY:String = "multiply";
 23		public static const ADD:String = "add";
 24		public static const MIX:String = "mix";
 25		
 26		private var _projector:TextureProjector;
 27		private var _uvVarying:ShaderRegisterElement;
 28		private var _projMatrix:Matrix3D = new Matrix3D();
 29		private var _mode:String;
 30		
 31		/**
 32		 * Creates a new ProjectiveTextureMethod object.
 33		 *
 34		 * @param projector The TextureProjector object that defines the projection properties as well as the texture.
 35		 * @param mode The blend mode with which the texture is blended unto the surface.
 36		 *
 37		 * @see away3d.entities.TextureProjector
 38		 */
 39		public function ProjectiveTextureMethod(projector:TextureProjector, mode:String = "multiply")
 40		{
 41			super();
 42			_projector = projector;
 43			_mode = mode;
 44		}
 45
 46		/**
 47		 * @inheritDoc
 48		 */
 49		override arcane function initConstants(vo:MethodVO):void
 50		{
 51			var index:int = vo.fragmentConstantsIndex;
 52			var data:Vector.<Number> = vo.fragmentData;
 53			data[index] = .5;
 54			data[index + 1] = -.5;
 55			data[index + 2] = 1.0;
 56			data[index + 3] = 1.0;
 57		}
 58
 59		/**
 60		 * @inheritDoc
 61		 */
 62		arcane override function cleanCompilationData():void
 63		{
 64			super.cleanCompilationData();
 65			_uvVarying = null;
 66		}
 67		
 68		/**
 69		 * The blend mode with which the texture is blended unto the object.
 70		 * ProjectiveTextureMethod.MULTIPLY can be used to project shadows. To prevent clamping, the texture's alpha should be white!
 71		 * ProjectiveTextureMethod.ADD can be used to project light, such as a slide projector or light coming through stained glass. To prevent clamping, the texture's alpha should be black!
 72		 * ProjectiveTextureMethod.MIX provides normal alpha blending. To prevent clamping, the texture's alpha should be transparent!
 73		 */
 74		public function get mode():String
 75		{
 76			return _mode;
 77		}
 78		
 79		public function set mode(value:String):void
 80		{
 81			if (_mode == value)
 82				return;
 83			_mode = value;
 84			invalidateShaderProgram();
 85		}
 86		
 87		/**
 88		 * The TextureProjector object that defines the projection properties as well as the texture.
 89		 *
 90		 * @see away3d.entities.TextureProjector
 91		 */
 92		public function get projector():TextureProjector
 93		{
 94			return _projector;
 95		}
 96		
 97		public function set projector(value:TextureProjector):void
 98		{
 99			_projector = value;
100		}
101		
102		/**
103		 * @inheritDoc
104		 */
105		arcane override function getVertexCode(vo:MethodVO, regCache:ShaderRegisterCache):String
106		{
107			var projReg:ShaderRegisterElement = regCache.getFreeVertexConstant();
108			regCache.getFreeVertexConstant();
109			regCache.getFreeVertexConstant();
110			regCache.getFreeVertexConstant();
111			regCache.getFreeVertexVectorTemp();
112			vo.vertexConstantsIndex = projReg.index*4;
113			_uvVarying = regCache.getFreeVarying();
114			
115			return "m44 " + _uvVarying + ", vt0, " + projReg + "\n";
116		}
117		
118		/**
119		 * @inheritDoc
120		 */
121		override arcane function getFragmentCode(vo:MethodVO, regCache:ShaderRegisterCache, targetReg:ShaderRegisterElement):String
122		{
123			var code:String = "";
124			var mapRegister:ShaderRegisterElement = regCache.getFreeTextureReg();
125			var col:ShaderRegisterElement = regCache.getFreeFragmentVectorTemp();
126			var toTexReg:ShaderRegisterElement = regCache.getFreeFragmentConstant();
127			vo.fragmentConstantsIndex = toTexReg.index*4;
128			vo.texturesIndex = mapRegister.index;
129			
130			code += "div " + col + ", " + _uvVarying + ", " + _uvVarying + ".w						\n" +
131				"mul " + col + ".xy, " + col + ".xy, " + toTexReg + ".xy	\n" +
132				"add " + col + ".xy, " + col + ".xy, " + toTexReg + ".xx	\n";
133			code += getTex2DSampleCode(vo, col, mapRegister, _projector.texture, col, "clamp");
134			
135			if (_mode == MULTIPLY)
136				code += "mul " + targetReg + ".xyz, " + targetReg + ".xyz, " + col + ".xyz			\n";
137			else if (_mode == ADD)
138				code += "add " + targetReg + ".xyz, " + targetReg + ".xyz, " + col + ".xyz			\n";
139			else if (_mode == MIX) {
140				code += "sub " + col + ".xyz, " + col + ".xyz, " + targetReg + ".xyz				\n" +
141					"mul " + col + ".xyz, " + col + ".xyz, " + col + ".w						\n" +
142					"add " + targetReg + ".xyz, " + targetReg + ".xyz, " + col + ".xyz			\n";
143			} else
144				throw new Error("Unknown mode \"" + _mode + "\"");
145			
146			return code;
147		}
148
149		/**
150		 * @inheritDoc
151		 */
152		arcane override function setRenderState(vo:MethodVO, renderable:IRenderable, stage3DProxy:Stage3DProxy, camera:Camera3D):void
153		{
154			_projMatrix.copyFrom(_projector.viewProjection);
155			_projMatrix.prepend(renderable.getRenderSceneTransform(camera));
156			_projMatrix.copyRawDataTo(vo.vertexData, vo.vertexConstantsIndex, true);
157		}
158		
159		/**
160		 * @inheritDoc
161		 */
162		override arcane function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):void
163		{
164			stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _projector.texture.getTextureForStage3D(stage3DProxy));
165		}
166	}
167}