BokehPass.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import {
  2. Color,
  3. HalfFloatType,
  4. MeshDepthMaterial,
  5. NearestFilter,
  6. NoBlending,
  7. RGBADepthPacking,
  8. ShaderMaterial,
  9. UniformsUtils,
  10. WebGLRenderTarget
  11. } from 'three';
  12. import { Pass, FullScreenQuad } from './Pass.js';
  13. import { BokehShader } from '../shaders/BokehShader.js';
  14. /**
  15. * Pass for creating depth of field (DOF) effect.
  16. *
  17. * ```js
  18. * const bokehPass = new BokehPass( scene, camera, {
  19. * focus: 500
  20. * aperture: 5,
  21. * maxblur: 0.01
  22. * } );
  23. * composer.addPass( bokehPass );
  24. * ```
  25. *
  26. * @augments Pass
  27. */
  28. class BokehPass extends Pass {
  29. /**
  30. * Constructs a new Bokeh pass.
  31. *
  32. * @param {Scene} scene - The scene to render the DOF for.
  33. * @param {Camera} camera - The camera.
  34. * @param {BokehPass~Options} params - The pass options.
  35. */
  36. constructor( scene, camera, params ) {
  37. super();
  38. /**
  39. * The scene to render the DOF for.
  40. *
  41. * @type {Scene}
  42. */
  43. this.scene = scene;
  44. /**
  45. * The camera.
  46. *
  47. * @type {Camera}
  48. */
  49. this.camera = camera;
  50. const focus = ( params.focus !== undefined ) ? params.focus : 1.0;
  51. const aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025;
  52. const maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0;
  53. // render targets
  54. this._renderTargetDepth = new WebGLRenderTarget( 1, 1, { // will be resized later
  55. minFilter: NearestFilter,
  56. magFilter: NearestFilter,
  57. type: HalfFloatType
  58. } );
  59. this._renderTargetDepth.texture.name = 'BokehPass.depth';
  60. // depth material
  61. this._materialDepth = new MeshDepthMaterial();
  62. this._materialDepth.depthPacking = RGBADepthPacking;
  63. this._materialDepth.blending = NoBlending;
  64. // bokeh material
  65. const bokehUniforms = UniformsUtils.clone( BokehShader.uniforms );
  66. bokehUniforms[ 'tDepth' ].value = this._renderTargetDepth.texture;
  67. bokehUniforms[ 'focus' ].value = focus;
  68. bokehUniforms[ 'aspect' ].value = camera.aspect;
  69. bokehUniforms[ 'aperture' ].value = aperture;
  70. bokehUniforms[ 'maxblur' ].value = maxblur;
  71. bokehUniforms[ 'nearClip' ].value = camera.near;
  72. bokehUniforms[ 'farClip' ].value = camera.far;
  73. /**
  74. * The pass bokeh material.
  75. *
  76. * @type {ShaderMaterial}
  77. */
  78. this.materialBokeh = new ShaderMaterial( {
  79. defines: Object.assign( {}, BokehShader.defines ),
  80. uniforms: bokehUniforms,
  81. vertexShader: BokehShader.vertexShader,
  82. fragmentShader: BokehShader.fragmentShader
  83. } );
  84. /**
  85. * The pass uniforms. Use this object if you want to update the
  86. * `focus`, `aperture` or `maxblur` values at runtime.
  87. *
  88. * ```js
  89. * pass.uniforms.focus.value = focus;
  90. * pass.uniforms.aperture.value = aperture;
  91. * pass.uniforms.maxblur.value = maxblur;
  92. * ```
  93. *
  94. * @type {Object}
  95. */
  96. this.uniforms = bokehUniforms;
  97. // internals
  98. this._fsQuad = new FullScreenQuad( this.materialBokeh );
  99. this._oldClearColor = new Color();
  100. }
  101. /**
  102. * Performs the Bokeh pass.
  103. *
  104. * @param {WebGLRenderer} renderer - The renderer.
  105. * @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
  106. * destination for the pass.
  107. * @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
  108. * previous pass from this buffer.
  109. * @param {number} deltaTime - The delta time in seconds.
  110. * @param {boolean} maskActive - Whether masking is active or not.
  111. */
  112. render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {
  113. // Render depth into texture
  114. this.scene.overrideMaterial = this._materialDepth;
  115. renderer.getClearColor( this._oldClearColor );
  116. const oldClearAlpha = renderer.getClearAlpha();
  117. const oldAutoClear = renderer.autoClear;
  118. renderer.autoClear = false;
  119. renderer.setClearColor( 0xffffff );
  120. renderer.setClearAlpha( 1.0 );
  121. renderer.setRenderTarget( this._renderTargetDepth );
  122. renderer.clear();
  123. renderer.render( this.scene, this.camera );
  124. // Render bokeh composite
  125. this.uniforms[ 'tColor' ].value = readBuffer.texture;
  126. this.uniforms[ 'nearClip' ].value = this.camera.near;
  127. this.uniforms[ 'farClip' ].value = this.camera.far;
  128. if ( this.renderToScreen ) {
  129. renderer.setRenderTarget( null );
  130. this._fsQuad.render( renderer );
  131. } else {
  132. renderer.setRenderTarget( writeBuffer );
  133. renderer.clear();
  134. this._fsQuad.render( renderer );
  135. }
  136. this.scene.overrideMaterial = null;
  137. renderer.setClearColor( this._oldClearColor );
  138. renderer.setClearAlpha( oldClearAlpha );
  139. renderer.autoClear = oldAutoClear;
  140. }
  141. /**
  142. * Sets the size of the pass.
  143. *
  144. * @param {number} width - The width to set.
  145. * @param {number} height - The width to set.
  146. */
  147. setSize( width, height ) {
  148. this.materialBokeh.uniforms[ 'aspect' ].value = width / height;
  149. this._renderTargetDepth.setSize( width, height );
  150. }
  151. /**
  152. * Frees the GPU-related resources allocated by this instance. Call this
  153. * method whenever the pass is no longer used in your app.
  154. */
  155. dispose() {
  156. this._renderTargetDepth.dispose();
  157. this._materialDepth.dispose();
  158. this.materialBokeh.dispose();
  159. this._fsQuad.dispose();
  160. }
  161. }
  162. /**
  163. * Constructor options of `BokehPass`.
  164. *
  165. * @typedef {Object} BokehPass~Options
  166. * @property {number} [focus=1] - Defines the effect's focus which is the distance along the camera's look direction in world units.
  167. * @property {number} [aperture=0.025] - Defines the effect's aperture.
  168. * @property {number} [maxblur=1] - Defines the effect's maximum blur.
  169. **/
  170. export { BokehPass };
粤ICP备19079148号