/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

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