PageRenderTime 224ms CodeModel.GetById 81ms app.highlight 13ms RepoModel.GetById 127ms app.codeStats 1ms

/src/away3d/materials/passes/SingleObjectDepthPass.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 193 lines | 122 code | 24 blank | 47 comment | 10 complexity | fea7b951cea313d70bcc6847a1c6f60e MD5 | raw 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.lights.LightBase;
  8	
  9	import flash.display3D.Context3D;
 10	import flash.display3D.Context3DProgramType;
 11	import flash.display3D.Context3DTextureFormat;
 12	import flash.display3D.textures.Texture;
 13	import flash.geom.Matrix3D;
 14	import flash.utils.Dictionary;
 15	
 16	use namespace arcane;
 17	
 18	/**
 19	 * The SingleObjectDepthPass provides a material pass that renders a single object to a depth map from the point
 20	 * of view from a light.
 21	 */
 22	public class SingleObjectDepthPass extends MaterialPassBase
 23	{
 24		private var _textures:Vector.<Dictionary>;
 25		private var _projections:Dictionary;
 26		private var _textureSize:uint;
 27		private var _polyOffset:Vector.<Number>;
 28		private var _enc:Vector.<Number>;
 29		private var _projectionTexturesInvalid:Boolean = true;
 30		
 31		/**
 32		 * Creates a new SingleObjectDepthPass object.
 33		 * @param textureSize The size of the depth map texture to render to.
 34		 * @param polyOffset The amount by which the rendered object will be inflated, to prevent depth map rounding errors.
 35		 *
 36		 * todo: provide custom vertex code to assembler
 37		 */
 38		public function SingleObjectDepthPass(textureSize:uint = 512, polyOffset:Number = 15)
 39		{
 40			super(true);
 41			_textureSize = textureSize;
 42			_numUsedStreams = 2;
 43			_numUsedVertexConstants = 7;
 44			_polyOffset = new <Number>[polyOffset, 0, 0, 0];
 45			_enc = Vector.<Number>([    1.0, 255.0, 65025.0, 16581375.0,
 46				1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0
 47				]);
 48			
 49			_animatableAttributes = Vector.<String>(["va0", "va1"]);
 50			_animationTargetRegisters = Vector.<String>(["vt0", "vt1"]);
 51		}
 52		
 53		/**
 54		 * @inheritDoc
 55		 */
 56		override public function dispose():void
 57		{
 58			if (_textures) {
 59				for (var i:uint = 0; i < _textures.length; ++i) {
 60					for each (var vec:Vector.<Texture> in _textures[i]) {
 61						for (var j:uint = 0; j < vec.length; ++j)
 62							vec[j].dispose();
 63					}
 64				}
 65				_textures = null;
 66			}
 67		}
 68
 69		/**
 70		 * Updates the projection textures used to contain the depth renders.
 71		 */
 72		private function updateProjectionTextures():void
 73		{
 74			if (_textures) {
 75				for (var i:uint = 0; i < _textures.length; ++i) {
 76					for each (var vec:Vector.<Texture> in _textures[i]) {
 77						for (var j:uint = 0; j < vec.length; ++j)
 78							vec[j].dispose();
 79					}
 80				}
 81			}
 82			
 83			_textures = new Vector.<Dictionary>(8);
 84			_projections = new Dictionary();
 85			_projectionTexturesInvalid = false;
 86		}
 87		
 88		/**
 89		 * @inheritDoc
 90		 */
 91		arcane override function getVertexCode():String
 92		{
 93			var code:String;
 94			// offset
 95			code = "mul vt7, vt1, vc4.x	\n" +
 96				"add vt7, vt7, vt0		\n" +
 97				"mov vt7.w, vt0.w		\n";
 98			// project
 99			code += "m44 vt2, vt7, vc0		\n" +
100				"mov op, vt2			\n";
101			
102			// perspective divide
103			code += "div v0, vt2, vt2.w \n";
104			
105			return code;
106		}
107		
108		/**
109		 * @inheritDoc
110		 */
111		arcane override function getFragmentCode(animationCode:String):String
112		{
113			var code:String = "";
114			
115			// encode float -> rgba
116			code += "mul ft0, fc0, v0.z     \n" +
117				"frc ft0, ft0           \n" +
118				"mul ft1, ft0.yzww, fc1 \n" +
119				"sub ft0, ft0, ft1      \n" +
120				"mov oc, ft0            \n";
121			
122			return code;
123		}
124
125		/**
126		 * Gets the depth maps rendered for this object from all lights.
127		 * @param renderable The renderable for which to retrieve the depth maps.
128		 * @param stage3DProxy The Stage3DProxy object currently used for rendering.
129		 * @return A list of depth map textures for all supported lights.
130		 */
131		arcane function getDepthMap(renderable:IRenderable, stage3DProxy:Stage3DProxy):Texture
132		{
133			return _textures[stage3DProxy._stage3DIndex][renderable];
134		}
135		
136		/**
137		 * Retrieves the depth map projection maps for all lights.
138		 * @param renderable The renderable for which to retrieve the projection maps.
139		 * @return A list of projection maps for all supported lights.
140		 */
141		arcane function getProjection(renderable:IRenderable):Matrix3D
142		{
143			return _projections[renderable];
144		}
145		
146		/**
147		 * @inheritDoc
148		 */
149		arcane override function render(renderable:IRenderable, stage3DProxy:Stage3DProxy, camera:Camera3D, viewProjection:Matrix3D):void
150		{
151			var matrix:Matrix3D;
152			var contextIndex:int = stage3DProxy._stage3DIndex;
153			var context:Context3D = stage3DProxy._context3D;
154			var len:uint;
155			var light:LightBase;
156			var lights:Vector.<LightBase> = _lightPicker.allPickedLights;
157			
158			_textures[contextIndex] ||= new Dictionary();
159			
160			if (!_projections[renderable])
161				_projections[renderable] = new Matrix3D();
162			
163			len = lights.length;
164			// local position = enough
165			light = lights[0];
166			
167			matrix = light.getObjectProjectionMatrix(renderable, camera, _projections[renderable]);
168			
169			// todo: use texture proxy?
170			var target:Texture = _textures[contextIndex][renderable] ||= context.createTexture(_textureSize, _textureSize, Context3DTextureFormat.BGRA, true);
171			
172			stage3DProxy.setRenderTarget(target, true);
173			context.clear(1.0, 1.0, 1.0);
174			context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
175			context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, _enc, 2);
176			renderable.activateVertexBuffer(0, stage3DProxy);
177			renderable.activateVertexNormalBuffer(1, stage3DProxy);
178			context.drawTriangles(renderable.getIndexBuffer(stage3DProxy), 0, renderable.numTriangles);
179		}
180		
181		/**
182		 * @inheritDoc
183		 */
184		override arcane function activate(stage3DProxy:Stage3DProxy, camera:Camera3D):void
185		{
186			if (_projectionTexturesInvalid)
187				updateProjectionTextures();
188			// never scale
189			super.activate(stage3DProxy, camera);
190			stage3DProxy._context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, _polyOffset, 1);
191		}
192	}
193}