1
0

MaskPass.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import { Pass } from './Pass.js';
  2. /**
  3. * This pass can be used to define a mask during post processing.
  4. * Meaning only areas of subsequent post processing are affected
  5. * which lie in the masking area of this pass. Internally, the masking
  6. * is implemented with the stencil buffer.
  7. *
  8. * ```js
  9. * const maskPass = new MaskPass( scene, camera );
  10. * composer.addPass( maskPass );
  11. * ```
  12. *
  13. * @augments Pass
  14. */
  15. class MaskPass extends Pass {
  16. /**
  17. * Constructs a new mask pass.
  18. *
  19. * @param {Scene} scene - The 3D objects in this scene will define the mask.
  20. * @param {Camera} camera - The camera.
  21. */
  22. constructor( scene, camera ) {
  23. super();
  24. /**
  25. * The scene that defines the mask.
  26. *
  27. * @type {Scene}
  28. */
  29. this.scene = scene;
  30. /**
  31. * The camera.
  32. *
  33. * @type {Camera}
  34. */
  35. this.camera = camera;
  36. /**
  37. * Overwritten to perform a clear operation by default.
  38. *
  39. * @type {boolean}
  40. * @default true
  41. */
  42. this.clear = true;
  43. /**
  44. * Overwritten to disable the swap.
  45. *
  46. * @type {boolean}
  47. * @default false
  48. */
  49. this.needsSwap = false;
  50. /**
  51. * Whether to inverse the mask or not.
  52. *
  53. * @type {boolean}
  54. * @default false
  55. */
  56. this.inverse = false;
  57. }
  58. /**
  59. * Performs a mask pass with the configured scene and camera.
  60. *
  61. * @param {WebGLRenderer} renderer - The renderer.
  62. * @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
  63. * destination for the pass.
  64. * @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
  65. * previous pass from this buffer.
  66. * @param {number} deltaTime - The delta time in seconds.
  67. * @param {boolean} maskActive - Whether masking is active or not.
  68. */
  69. render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {
  70. const context = renderer.getContext();
  71. const state = renderer.state;
  72. // don't update color or depth
  73. state.buffers.color.setMask( false );
  74. state.buffers.depth.setMask( false );
  75. // lock buffers
  76. state.buffers.color.setLocked( true );
  77. state.buffers.depth.setLocked( true );
  78. // set up stencil
  79. let writeValue, clearValue;
  80. if ( this.inverse ) {
  81. writeValue = 0;
  82. clearValue = 1;
  83. } else {
  84. writeValue = 1;
  85. clearValue = 0;
  86. }
  87. state.buffers.stencil.setTest( true );
  88. state.buffers.stencil.setOp( context.REPLACE, context.REPLACE, context.REPLACE );
  89. state.buffers.stencil.setFunc( context.ALWAYS, writeValue, 0xffffffff );
  90. state.buffers.stencil.setClear( clearValue );
  91. state.buffers.stencil.setLocked( true );
  92. // draw into the stencil buffer
  93. renderer.setRenderTarget( readBuffer );
  94. if ( this.clear ) renderer.clear();
  95. renderer.render( this.scene, this.camera );
  96. renderer.setRenderTarget( writeBuffer );
  97. if ( this.clear ) renderer.clear();
  98. renderer.render( this.scene, this.camera );
  99. // unlock color and depth buffer and make them writable for subsequent rendering/clearing
  100. state.buffers.color.setLocked( false );
  101. state.buffers.depth.setLocked( false );
  102. state.buffers.color.setMask( true );
  103. state.buffers.depth.setMask( true );
  104. // only render where stencil is set to 1
  105. state.buffers.stencil.setLocked( false );
  106. state.buffers.stencil.setFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1
  107. state.buffers.stencil.setOp( context.KEEP, context.KEEP, context.KEEP );
  108. state.buffers.stencil.setLocked( true );
  109. }
  110. }
  111. /**
  112. * This pass can be used to clear a mask previously defined with {@link MaskPass}.
  113. *
  114. * ```js
  115. * const clearPass = new ClearMaskPass();
  116. * composer.addPass( clearPass );
  117. * ```
  118. *
  119. * @augments Pass
  120. */
  121. class ClearMaskPass extends Pass {
  122. /**
  123. * Constructs a new clear mask pass.
  124. */
  125. constructor() {
  126. super();
  127. /**
  128. * Overwritten to disable the swap.
  129. *
  130. * @type {boolean}
  131. * @default false
  132. */
  133. this.needsSwap = false;
  134. }
  135. /**
  136. * Performs the clear of the currently defined mask.
  137. *
  138. * @param {WebGLRenderer} renderer - The renderer.
  139. * @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
  140. * destination for the pass.
  141. * @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
  142. * previous pass from this buffer.
  143. * @param {number} deltaTime - The delta time in seconds.
  144. * @param {boolean} maskActive - Whether masking is active or not.
  145. */
  146. render( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) {
  147. renderer.state.buffers.stencil.setLocked( false );
  148. renderer.state.buffers.stencil.setTest( false );
  149. }
  150. }
  151. export { MaskPass, ClearMaskPass };
粤ICP备19079148号