AfterimagePass.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import {
  2. HalfFloatType,
  3. NearestFilter,
  4. NoBlending,
  5. ShaderMaterial,
  6. UniformsUtils,
  7. WebGLRenderTarget
  8. } from 'three';
  9. import { Pass, FullScreenQuad } from './Pass.js';
  10. import { CopyShader } from '../shaders/CopyShader.js';
  11. import { AfterimageShader } from '../shaders/AfterimageShader.js';
  12. /**
  13. * Pass for a basic after image effect.
  14. *
  15. * ```js
  16. * const afterimagePass = new AfterimagePass( 0.9 );
  17. * composer.addPass( afterimagePass );
  18. * ```
  19. *
  20. * @augments Pass
  21. */
  22. class AfterimagePass extends Pass {
  23. /**
  24. * Constructs a new after image pass.
  25. *
  26. * @param {number} [damp=0.96] - The damping intensity. A higher value means a stronger after image effect.
  27. */
  28. constructor( damp = 0.96 ) {
  29. super();
  30. /**
  31. * The pass uniforms. Use this object if you want to update the
  32. * `damp` value at runtime.
  33. * ```js
  34. * pass.uniforms.damp.value = 0.9;
  35. * ```
  36. *
  37. * @type {Object}
  38. */
  39. this.uniforms = UniformsUtils.clone( AfterimageShader.uniforms );
  40. this.uniforms[ 'damp' ].value = damp;
  41. /**
  42. * The composition material.
  43. *
  44. * @type {ShaderMaterial}
  45. */
  46. this.compFsMaterial = new ShaderMaterial( {
  47. uniforms: this.uniforms,
  48. vertexShader: AfterimageShader.vertexShader,
  49. fragmentShader: AfterimageShader.fragmentShader
  50. } );
  51. /**
  52. * The copy material.
  53. *
  54. * @type {ShaderMaterial}
  55. */
  56. this.copyFsMaterial = new ShaderMaterial( {
  57. uniforms: UniformsUtils.clone( CopyShader.uniforms ),
  58. vertexShader: CopyShader.vertexShader,
  59. fragmentShader: CopyShader.fragmentShader,
  60. blending: NoBlending,
  61. depthTest: false,
  62. depthWrite: false
  63. } );
  64. // internals
  65. this._textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
  66. magFilter: NearestFilter,
  67. type: HalfFloatType
  68. } );
  69. this._textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
  70. magFilter: NearestFilter,
  71. type: HalfFloatType
  72. } );
  73. this._compFsQuad = new FullScreenQuad( this.compFsMaterial );
  74. this._copyFsQuad = new FullScreenQuad( this.copyFsMaterial );
  75. }
  76. /**
  77. * Performs the after image pass.
  78. *
  79. * @param {WebGLRenderer} renderer - The renderer.
  80. * @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
  81. * destination for the pass.
  82. * @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
  83. * previous pass from this buffer.
  84. * @param {number} deltaTime - The delta time in seconds.
  85. * @param {boolean} maskActive - Whether masking is active or not.
  86. */
  87. render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {
  88. this.uniforms[ 'tOld' ].value = this._textureOld.texture;
  89. this.uniforms[ 'tNew' ].value = readBuffer.texture;
  90. renderer.setRenderTarget( this._textureComp );
  91. this._compFsQuad.render( renderer );
  92. this._copyFsQuad.material.uniforms.tDiffuse.value = this._textureComp.texture;
  93. if ( this.renderToScreen ) {
  94. renderer.setRenderTarget( null );
  95. this._copyFsQuad.render( renderer );
  96. } else {
  97. renderer.setRenderTarget( writeBuffer );
  98. if ( this.clear ) renderer.clear();
  99. this._copyFsQuad.render( renderer );
  100. }
  101. // Swap buffers.
  102. const temp = this._textureOld;
  103. this._textureOld = this._textureComp;
  104. this._textureComp = temp;
  105. // Now textureOld contains the latest image, ready for the next frame.
  106. }
  107. /**
  108. * Sets the size of the pass.
  109. *
  110. * @param {number} width - The width to set.
  111. * @param {number} height - The width to set.
  112. */
  113. setSize( width, height ) {
  114. this._textureComp.setSize( width, height );
  115. this._textureOld.setSize( width, height );
  116. }
  117. /**
  118. * Frees the GPU-related resources allocated by this instance. Call this
  119. * method whenever the pass is no longer used in your app.
  120. */
  121. dispose() {
  122. this._textureComp.dispose();
  123. this._textureOld.dispose();
  124. this.compFsMaterial.dispose();
  125. this.copyFsMaterial.dispose();
  126. this._compFsQuad.dispose();
  127. this._copyFsQuad.dispose();
  128. }
  129. }
  130. export { AfterimagePass };
粤ICP备19079148号