PageRenderTime 43ms CodeModel.GetById 14ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 1ms

/src/away3d/core/render/DefaultRenderer.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 249 lines | 188 code | 38 blank | 23 comment | 24 complexity | fa263cf76976451878c8232c10845c60 MD5 | raw file
  1package away3d.core.render
  2{
  3	import away3d.arcane;
  4	import away3d.cameras.Camera3D;
  5	import away3d.core.base.IRenderable;
  6	import away3d.core.data.RenderableListItem;
  7	import away3d.core.managers.Stage3DProxy;
  8	import away3d.core.math.Matrix3DUtils;
  9	import away3d.core.math.Matrix3DUtils;
 10	import away3d.core.traverse.EntityCollector;
 11	import away3d.lights.DirectionalLight;
 12	import away3d.lights.LightBase;
 13	import away3d.lights.PointLight;
 14	import away3d.lights.shadowmaps.ShadowMapperBase;
 15	import away3d.materials.MaterialBase;
 16
 17	import flash.display3D.Context3DBlendFactor;
 18	import flash.display3D.Context3DCompareMode;
 19	import flash.display3D.textures.TextureBase;
 20	import flash.geom.Matrix3D;
 21	import flash.geom.Rectangle;
 22	import flash.geom.Vector3D;
 23
 24	use namespace arcane;
 25
 26	/**
 27	 * The DefaultRenderer class provides the default rendering method. It renders the scene graph objects using the
 28	 * materials assigned to them.
 29	 */
 30	public class DefaultRenderer extends RendererBase
 31	{
 32		private static var RTT_PASSES:int = 1;
 33		private static var SCREEN_PASSES:int = 2;
 34		private static var ALL_PASSES:int = 3;
 35		private var _activeMaterial:MaterialBase;
 36		private var _distanceRenderer:DepthRenderer;
 37		private var _depthRenderer:DepthRenderer;
 38		private var _skyboxProjection:Matrix3D = new Matrix3D();
 39		private var _tempSkyboxMatrix:Matrix3D = new Matrix3D();
 40		private var _skyboxTempVector:Vector3D = new Vector3D();
 41
 42		/**
 43		 * Creates a new DefaultRenderer object.
 44		 * @param antiAlias The amount of anti-aliasing to use.
 45		 * @param renderMode The render mode to use.
 46		 */
 47		public function DefaultRenderer()
 48		{
 49			super();
 50			_depthRenderer = new DepthRenderer();
 51			_distanceRenderer = new DepthRenderer(false, true);
 52		}
 53
 54		arcane override function set stage3DProxy(value:Stage3DProxy):void
 55		{
 56			super.stage3DProxy = value;
 57			_distanceRenderer.stage3DProxy = _depthRenderer.stage3DProxy = value;
 58		}
 59
 60		protected override function executeRender(entityCollector:EntityCollector, target:TextureBase = null, scissorRect:Rectangle = null, surfaceSelector:int = 0):void
 61		{
 62			updateLights(entityCollector);
 63
 64			// otherwise RTT will interfere with other RTTs
 65			if (target) {
 66				drawRenderables(entityCollector.opaqueRenderableHead, entityCollector, RTT_PASSES);
 67				drawRenderables(entityCollector.blendedRenderableHead, entityCollector, RTT_PASSES);
 68			}
 69
 70			super.executeRender(entityCollector, target, scissorRect, surfaceSelector);
 71		}
 72
 73		private function updateLights(entityCollector:EntityCollector):void
 74		{
 75			var dirLights:Vector.<DirectionalLight> = entityCollector.directionalLights;
 76			var pointLights:Vector.<PointLight> = entityCollector.pointLights;
 77			var len:uint, i:uint;
 78			var light:LightBase;
 79			var shadowMapper:ShadowMapperBase;
 80
 81			len = dirLights.length;
 82			for (i = 0; i < len; ++i) {
 83				light = dirLights[i];
 84				shadowMapper = light.shadowMapper;
 85				if (light.castsShadows && (shadowMapper.autoUpdateShadows || shadowMapper._shadowsInvalid))
 86					shadowMapper.renderDepthMap(_stage3DProxy, entityCollector, _depthRenderer);
 87			}
 88
 89			len = pointLights.length;
 90			for (i = 0; i < len; ++i) {
 91				light = pointLights[i];
 92				shadowMapper = light.shadowMapper;
 93				if (light.castsShadows && (shadowMapper.autoUpdateShadows || shadowMapper._shadowsInvalid))
 94					shadowMapper.renderDepthMap(_stage3DProxy, entityCollector, _distanceRenderer);
 95			}
 96		}
 97
 98		/**
 99		 * @inheritDoc
100		 */
101		override protected function draw(entityCollector:EntityCollector, target:TextureBase):void
102		{
103			_context.setBlendFactors(Context3DBlendFactor.ONE, Context3DBlendFactor.ZERO);
104
105			if (entityCollector.skyBox) {
106				if (_activeMaterial)
107					_activeMaterial.deactivate(_stage3DProxy);
108				_activeMaterial = null;
109
110				_context.setDepthTest(false, Context3DCompareMode.ALWAYS);
111				drawSkyBox(entityCollector);
112			}
113
114			_context.setDepthTest(true, Context3DCompareMode.LESS_EQUAL);
115
116			var which:int = target? SCREEN_PASSES : ALL_PASSES;
117			drawRenderables(entityCollector.opaqueRenderableHead, entityCollector, which);
118			drawRenderables(entityCollector.blendedRenderableHead, entityCollector, which);
119
120			_context.setDepthTest(false, Context3DCompareMode.LESS_EQUAL);
121
122			if (_activeMaterial)
123				_activeMaterial.deactivate(_stage3DProxy);
124
125			_activeMaterial = null;
126		}
127
128		/**
129		 * Draw the skybox if present.
130		 * @param entityCollector The EntityCollector containing all potentially visible information.
131		 */
132		private function drawSkyBox(entityCollector:EntityCollector):void
133		{
134			var skyBox:IRenderable = entityCollector.skyBox;
135			var material:MaterialBase = skyBox.material;
136			var camera:Camera3D = entityCollector.camera;
137
138			updateSkyBoxProjection(camera);
139
140			material.activatePass(0, _stage3DProxy, camera);
141			material.renderPass(0, skyBox, _stage3DProxy, entityCollector, _skyboxProjection);
142			material.deactivatePass(0, _stage3DProxy);
143		}
144
145		private function updateSkyBoxProjection(camera:Camera3D):void
146		{
147			_skyboxProjection.copyFrom(_rttViewProjectionMatrix);
148			_skyboxProjection.copyRowTo(2, _skyboxTempVector);
149			var camPos:Vector3D = camera.scenePosition;
150			var cx:Number = _skyboxTempVector.x;
151			var cy:Number = _skyboxTempVector.y;
152			var cz:Number = _skyboxTempVector.z;
153			var length:Number = Math.sqrt(cx*cx + cy*cy + cz*cz);
154
155			_skyboxTempVector.x = 0;
156			_skyboxTempVector.y = 0;
157			_skyboxTempVector.z = 0;
158			_skyboxTempVector.w = 1;
159			_tempSkyboxMatrix.copyFrom(camera.sceneTransform);
160			_tempSkyboxMatrix.copyColumnFrom(3,_skyboxTempVector);
161
162			_skyboxTempVector.x = 0;
163			_skyboxTempVector.y = 0;
164			_skyboxTempVector.z = 1;
165			_skyboxTempVector.w = 0;
166
167			Matrix3DUtils.transformVector(_tempSkyboxMatrix,_skyboxTempVector, _skyboxTempVector);
168			_skyboxTempVector.normalize();
169
170			var angle:Number = Math.acos(_skyboxTempVector.x*(cx/length) + _skyboxTempVector.y*(cy/length) + _skyboxTempVector.z*(cz/length));
171			if(Math.abs(angle)>0.000001) {
172				return;
173			}
174
175			var cw:Number = -(cx*camPos.x + cy*camPos.y + cz*camPos.z + length);
176			var signX:Number = cx >= 0? 1 : -1;
177			var signY:Number = cy >= 0? 1 : -1;
178
179			var p:Vector3D = _skyboxTempVector;
180			p.x = signX;
181			p.y = signY;
182			p.z = 1;
183			p.w = 1;
184			_tempSkyboxMatrix.copyFrom(_skyboxProjection);
185			_tempSkyboxMatrix.invert();
186			var q:Vector3D = Matrix3DUtils.transformVector(_tempSkyboxMatrix,p,Matrix3DUtils.CALCULATION_VECTOR3D);
187			_skyboxProjection.copyRowTo(3, p);
188			var a:Number = (q.x*p.x + q.y*p.y + q.z*p.z + q.w*p.w)/(cx*q.x + cy*q.y + cz*q.z + cw*q.w);
189			_skyboxTempVector.x = cx*a;
190			_skyboxTempVector.y = cy*a;
191			_skyboxTempVector.z = cz*a;
192			_skyboxTempVector.w = cw*a;
193			//copy changed near far
194			_skyboxProjection.copyRowFrom(2, _skyboxTempVector);
195		}
196
197		/**
198		 * Draw a list of renderables.
199		 * @param renderables The renderables to draw.
200		 * @param entityCollector The EntityCollector containing all potentially visible information.
201		 */
202		private function drawRenderables(item:RenderableListItem, entityCollector:EntityCollector, which:int):void
203		{
204			var numPasses:uint;
205			var j:uint;
206			var camera:Camera3D = entityCollector.camera;
207			var item2:RenderableListItem;
208
209			while (item) {
210				_activeMaterial = item.renderable.material;
211				_activeMaterial.updateMaterial(_context);
212
213				numPasses = _activeMaterial.numPasses;
214				j = 0;
215
216				do {
217					item2 = item;
218
219					var rttMask:int = _activeMaterial.passRendersToTexture(j)? 1 : 2;
220
221					if ((rttMask & which) != 0) {
222						_activeMaterial.activatePass(j, _stage3DProxy, camera);
223						do {
224							_activeMaterial.renderPass(j, item2.renderable, _stage3DProxy, entityCollector, _rttViewProjectionMatrix);
225							item2 = item2.next;
226						} while (item2 && item2.renderable.material == _activeMaterial);
227						_activeMaterial.deactivatePass(j, _stage3DProxy);
228					} else {
229						do
230							item2 = item2.next;
231						while (item2 && item2.renderable.material == _activeMaterial);
232					}
233
234				} while (++j < numPasses);
235
236				item = item2;
237			}
238		}
239
240		arcane override function dispose():void
241		{
242			super.dispose();
243			_depthRenderer.dispose();
244			_distanceRenderer.dispose();
245			_depthRenderer = null;
246			_distanceRenderer = null;
247		}
248	}
249}