Home Reference Source

src/effects/TiltShiftEffect.js

  1. import { SRGBColorSpace, Uniform, Vector2, WebGLRenderTarget } from "three";
  2. import { Resolution } from "../core/Resolution.js";
  3. import { KernelSize } from "../enums/KernelSize.js";
  4. import { TiltShiftBlurPass } from "../passes/TiltShiftBlurPass.js";
  5. import { Effect } from "./Effect.js";
  6.  
  7. import fragmentShader from "./glsl/tilt-shift.frag";
  8. import vertexShader from "./glsl/tilt-shift.vert";
  9.  
  10. /**
  11. * A tilt shift effect.
  12. */
  13.  
  14. export class TiltShiftEffect extends Effect {
  15.  
  16. /**
  17. * Constructs a new tilt shift Effect
  18. *
  19. * @param {Object} [options] - The options.
  20. * @param {BlendFunction} [options.blendFunction] - The blend function of this effect.
  21. * @param {Number} [options.offset=0.0] - The relative offset of the focus area.
  22. * @param {Number} [options.rotation=0.0] - The rotation of the focus area in radians.
  23. * @param {Number} [options.focusArea=0.4] - The relative size of the focus area.
  24. * @param {Number} [options.feather=0.3] - The softness of the focus area edges.
  25. * @param {Number} [options.bias=0.06] - Deprecated.
  26. * @param {KernelSize} [options.kernelSize=KernelSize.MEDIUM] - The blur kernel size.
  27. * @param {Number} [options.resolutionScale=0.5] - The resolution scale.
  28. * @param {Number} [options.resolutionX=Resolution.AUTO_SIZE] - The horizontal resolution.
  29. * @param {Number} [options.resolutionY=Resolution.AUTO_SIZE] - The vertical resolution.
  30. */
  31.  
  32. constructor({
  33. blendFunction,
  34. offset = 0.0,
  35. rotation = 0.0,
  36. focusArea = 0.4,
  37. feather = 0.3,
  38. kernelSize = KernelSize.MEDIUM,
  39. resolutionScale = 0.5,
  40. resolutionX = Resolution.AUTO_SIZE,
  41. resolutionY = Resolution.AUTO_SIZE
  42. } = {}) {
  43.  
  44. super("TiltShiftEffect", fragmentShader, {
  45. vertexShader,
  46. blendFunction,
  47. uniforms: new Map([
  48. ["rotation", new Uniform(new Vector2())],
  49. ["maskParams", new Uniform(new Vector2())],
  50. ["map", new Uniform(null)]
  51. ])
  52. });
  53.  
  54. /**
  55. * @see {@link offset}
  56. * @type {Number}
  57. * @private
  58. */
  59.  
  60. this._offset = offset;
  61.  
  62. /**
  63. * @see {@link focusArea}
  64. * @type {Number}
  65. * @private
  66. */
  67.  
  68. this._focusArea = focusArea;
  69.  
  70. /**
  71. * @see {@link feather}
  72. * @type {Number}
  73. * @private
  74. */
  75.  
  76. this._feather = feather;
  77.  
  78. /**
  79. * A render target.
  80. *
  81. * @type {WebGLRenderTarget}
  82. * @private
  83. */
  84.  
  85. this.renderTarget = new WebGLRenderTarget(1, 1, { depthBuffer: false });
  86. this.renderTarget.texture.name = "TiltShift.Target";
  87. this.uniforms.get("map").value = this.renderTarget.texture;
  88.  
  89. /**
  90. * A blur pass.
  91. *
  92. * @type {TiltShiftBlurPass}
  93. * @readonly
  94. */
  95.  
  96. this.blurPass = new TiltShiftBlurPass({
  97. kernelSize,
  98. resolutionScale,
  99. resolutionX,
  100. resolutionY,
  101. offset,
  102. rotation,
  103. focusArea,
  104. feather
  105. });
  106.  
  107. /**
  108. * The render resolution.
  109. *
  110. * @type {Resolution}
  111. * @readonly
  112. */
  113.  
  114. const resolution = this.resolution = new Resolution(this, resolutionX, resolutionY, resolutionScale);
  115. resolution.addEventListener("change", (e) => this.setSize(resolution.baseWidth, resolution.baseHeight));
  116.  
  117. this.rotation = rotation;
  118. this.updateParams();
  119.  
  120. }
  121.  
  122. /**
  123. * Updates the mask params.
  124. *
  125. * @private
  126. */
  127.  
  128. updateParams() {
  129.  
  130. const params = this.uniforms.get("maskParams").value;
  131. const x = Math.max(this.focusArea - this.feather, 0.0);
  132. params.set(this.offset - x, this.offset + x);
  133.  
  134. }
  135.  
  136. /**
  137. * The rotation of the focus area in radians.
  138. *
  139. * @type {Number}
  140. */
  141.  
  142. get rotation() {
  143.  
  144. return Math.acos(this.uniforms.get("rotation").value.x);
  145.  
  146. }
  147.  
  148. set rotation(value) {
  149.  
  150. this.uniforms.get("rotation").value.set(Math.cos(value), Math.sin(value));
  151. this.blurPass.blurMaterial.rotation = value;
  152.  
  153. }
  154.  
  155. /**
  156. * The relative offset of the focus area.
  157. *
  158. * @type {Number}
  159. */
  160.  
  161. get offset() {
  162.  
  163. return this._offset;
  164.  
  165. }
  166.  
  167. set offset(value) {
  168.  
  169. this._offset = value;
  170. this.blurPass.blurMaterial.offset = value;
  171. this.updateParams();
  172.  
  173. }
  174.  
  175. /**
  176. * The relative size of the focus area.
  177. *
  178. * @type {Number}
  179. */
  180.  
  181. get focusArea() {
  182.  
  183. return this._focusArea;
  184.  
  185. }
  186.  
  187. set focusArea(value) {
  188.  
  189. this._focusArea = value;
  190. this.blurPass.blurMaterial.focusArea = value;
  191. this.updateParams();
  192.  
  193. }
  194.  
  195. /**
  196. * The softness of the focus area edges.
  197. *
  198. * @type {Number}
  199. */
  200.  
  201. get feather() {
  202.  
  203. return this._feather;
  204.  
  205. }
  206.  
  207. set feather(value) {
  208.  
  209. this._feather = value;
  210. this.blurPass.blurMaterial.feather = value;
  211. this.updateParams();
  212.  
  213. }
  214.  
  215. /**
  216. * A blend bias.
  217. *
  218. * @type {Number}
  219. * @deprecated
  220. */
  221.  
  222. get bias() { return 0; }
  223. set bias(value) {}
  224.  
  225. /**
  226. * Updates this effect.
  227. *
  228. * @param {WebGLRenderer} renderer - The renderer.
  229. * @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
  230. * @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
  231. */
  232.  
  233. update(renderer, inputBuffer, deltaTime) {
  234.  
  235. this.blurPass.render(renderer, inputBuffer, this.renderTarget);
  236.  
  237. }
  238.  
  239. /**
  240. * Updates the size of internal render targets.
  241. *
  242. * @param {Number} width - The width.
  243. * @param {Number} height - The height.
  244. */
  245.  
  246. setSize(width, height) {
  247.  
  248. const resolution = this.resolution;
  249. resolution.setBaseSize(width, height);
  250.  
  251. this.renderTarget.setSize(resolution.width, resolution.height);
  252. this.blurPass.resolution.copy(resolution);
  253.  
  254. }
  255.  
  256. /**
  257. * Performs initialization tasks.
  258. *
  259. * @param {WebGLRenderer} renderer - The renderer.
  260. * @param {Boolean} alpha - Whether the renderer uses the alpha channel or not.
  261. * @param {Number} frameBufferType - The type of the main frame buffers.
  262. */
  263.  
  264. initialize(renderer, alpha, frameBufferType) {
  265.  
  266. this.blurPass.initialize(renderer, alpha, frameBufferType);
  267.  
  268. if(frameBufferType !== undefined) {
  269.  
  270. this.renderTarget.texture.type = frameBufferType;
  271.  
  272. if(renderer !== null && renderer.outputColorSpace === SRGBColorSpace) {
  273.  
  274. this.renderTarget.texture.colorSpace = SRGBColorSpace;
  275.  
  276. }
  277.  
  278. }
  279.  
  280. }
  281.  
  282. }