PageRenderTime 24ms CodeModel.GetById 12ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 1ms

/src/away3d/filters/tasks/Filter3DDepthOfFFieldTask.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 175 lines | 135 code | 38 blank | 2 comment | 19 complexity | 85f3f9de89608b5b847abed84f784fe3 MD5 | raw file
  1package away3d.filters.tasks
  2{
  3	import away3d.arcane;
  4	import away3d.cameras.Camera3D;
  5	import away3d.core.managers.Stage3DProxy;
  6
  7	import flash.display3D.Context3D;
  8	import flash.display3D.Context3DProgramType;
  9	import flash.display3D.textures.Texture;
 10
 11	use namespace arcane;
 12
 13	public class Filter3DDepthOfFFieldTask extends Filter3DTaskBase
 14	{
 15		private static const MAX_BLUR : int = 6;
 16		private var _maxBlurX : uint;
 17		private var _maxBlurY : uint;
 18		private var _data : Vector.<Number>;
 19		private var _stepX : Number = 1;
 20		private var _stepY : Number = 1;
 21		private var _numSamples : uint;
 22		private var _focusDistance : Number;
 23		private var _range : Number = 1000;
 24
 25		public function Filter3DDepthOfFFieldTask(maxBlurX : uint = 3, maxBlurY : uint = 3)
 26		{
 27			super(true);
 28			_maxBlurX = maxBlurX;
 29			_maxBlurY = maxBlurY;
 30			_data = Vector.<Number>([0, 0, 0, _focusDistance, 0, 0, 0, 0, _range, 0, 0, 0, 1.0, 1 / 255.0, 1 / 65025.0, 1 / 16581375.0]);
 31		}
 32
 33		public function get range() : Number
 34		{
 35			return _range;
 36		}
 37
 38		public function set range(value : Number) : void
 39		{
 40			_range = value;
 41			_data[8] = value
 42		}
 43
 44
 45		public function get focusDistance() : Number
 46		{
 47			return _focusDistance;
 48		}
 49
 50		public function set focusDistance(value : Number) : void
 51		{
 52			_data[3] = _focusDistance = value;
 53		}
 54
 55		public function get maxBlurX() : uint
 56		{
 57			return _maxBlurX;
 58		}
 59
 60		public function set maxBlurX(value : uint) : void
 61		{
 62			if (_maxBlurX == value) return;
 63			_maxBlurX = value;
 64
 65			if (_maxBlurX > MAX_BLUR) _stepX = _maxBlurX / MAX_BLUR;
 66			else _stepX = 1;
 67
 68			invalidateProgram3D();
 69			updateBlurData();
 70		}
 71
 72		public function get maxBlurY() : uint
 73		{
 74			return _maxBlurY;
 75		}
 76
 77		public function set maxBlurY(value : uint) : void
 78		{
 79			if (_maxBlurY == value) return;
 80			_maxBlurY = value;
 81
 82			invalidateProgram3D();
 83			updateBlurData();
 84		}
 85
 86		override protected function getFragmentCode() : String
 87		{
 88			var code : String;
 89
 90			_numSamples = 0;
 91
 92			// sample depth, unpack & get blur amount (offset point + step size)
 93			code = "tex ft0, v0, fs1 <2d, nearest>	\n" +
 94					"dp4 ft1.z, ft0, fc3				\n" +
 95					"sub ft1.z, ft1.z, fc1.z			\n" + // d = d - f
 96					"div ft1.z, fc1.w, ft1.z			\n" + // screenZ = -n*f/(d-f)
 97					"sub ft1.z, ft1.z, fc0.w			\n" + // screenZ - dist
 98					"div ft1.z, ft1.z, fc2.x			\n" + // (screenZ - dist)/range
 99
100					"abs ft1.z, ft1.z					\n" + // abs(screenZ - dist)/range
101					"sat ft1.z, ft1.z					\n" + // sat(abs(screenZ - dist)/range)
102					"mul ft6.xy, ft1.z, fc0.xy			\n" +
103					"mul ft7.xy, ft1.z, fc1.xy			\n";
104
105
106			code += "mov ft0, v0	\n" +
107					"sub ft0.y, v0.y, ft6.y\n";
108
109			for (var y : Number = 0; y <= _maxBlurY; y += _stepY) {
110				if (y > 0) code += "sub ft0.x, v0.x, ft6.x\n";
111				for (var x : Number = 0; x <= _maxBlurX; x += _stepX) {
112					++_numSamples;
113					if (x == 0 && y == 0)
114						code += "tex ft1, ft0, fs0 <2d,linear,clamp>\n";
115					else
116						code += "tex ft2, ft0, fs0 <2d,linear,clamp>\n" +
117								"add ft1, ft1, ft2 \n";
118
119					if (x < _maxBlurX) code += "add ft0.x, ft0.x, ft7.x	\n";
120				}
121				if (y < _maxBlurY) code += "add ft0.y, ft0.y, ft7.y		\n";
122			}
123
124			code += "mul oc, ft1, fc0.z";
125
126			_data[2] = 1 / _numSamples;
127
128			return code;
129		}
130
131		override public function activate(stage3DProxy : Stage3DProxy, camera : Camera3D, depthTexture : Texture) : void
132		{
133			var context : Context3D = stage3DProxy._context3D;
134			var n : Number = camera.lens.near;
135			var f : Number = camera.lens.far;
136
137			_data[6] = f / (f - n);
138			_data[7] = -n * _data[6];
139
140			stage3DProxy.setTextureAt(1, depthTexture);
141			context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, _data, 4);
142		}
143
144		override public function deactivate(stage3DProxy : Stage3DProxy) : void
145		{
146			stage3DProxy.setTextureAt(1, null);
147		}
148
149		override protected function updateTextures(stage : Stage3DProxy) : void
150		{
151			super.updateTextures(stage);
152
153			updateBlurData();
154		}
155
156		private function updateBlurData() : void
157		{
158			// todo: replace with view width once texture rendering is scissored?
159			var invW : Number = 1 / _textureWidth;
160			var invH : Number = 1 / _textureHeight;
161
162			if (_maxBlurX > MAX_BLUR) _stepX = _maxBlurX / MAX_BLUR;
163			else _stepX = 1;
164
165			if (_maxBlurY > MAX_BLUR) _stepY = _maxBlurY / MAX_BLUR;
166			else _stepY = 1;
167
168
169			_data[0] = _maxBlurX * .5 * invW;
170			_data[1] = _maxBlurY * .5 * invH;
171			_data[4] = _stepX * invW;
172			_data[5] = _stepY * invH;
173		}
174	}
175}