物管理前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.3 KiB

  1. (function () {
  2. class EffectComposer {
  3. constructor(renderer, renderTarget) {
  4. this.renderer = renderer;
  5. if (renderTarget === undefined) {
  6. const size = renderer.getSize(new THREE.Vector2());
  7. this._pixelRatio = renderer.getPixelRatio();
  8. this._width = size.width;
  9. this._height = size.height;
  10. renderTarget = new THREE.WebGLRenderTarget(
  11. this._width * this._pixelRatio,
  12. this._height * this._pixelRatio
  13. );
  14. renderTarget.texture.name = "EffectComposer.rt1";
  15. } else {
  16. this._pixelRatio = 1;
  17. this._width = renderTarget.width;
  18. this._height = renderTarget.height;
  19. }
  20. this.renderTarget1 = renderTarget;
  21. this.renderTarget2 = renderTarget.clone();
  22. this.renderTarget2.texture.name = "EffectComposer.rt2";
  23. this.writeBuffer = this.renderTarget1;
  24. this.readBuffer = this.renderTarget2;
  25. this.renderToScreen = true;
  26. this.passes = []; // dependencies
  27. if (THREE.CopyShader === undefined) {
  28. console.error("THREE.EffectComposer relies on THREE.CopyShader");
  29. }
  30. if (THREE.ShaderPass === undefined) {
  31. console.error("THREE.EffectComposer relies on THREE.ShaderPass");
  32. }
  33. this.copyPass = new THREE.ShaderPass(THREE.CopyShader);
  34. this.clock = new THREE.Clock();
  35. }
  36. swapBuffers() {
  37. const tmp = this.readBuffer;
  38. this.readBuffer = this.writeBuffer;
  39. this.writeBuffer = tmp;
  40. }
  41. addPass(pass) {
  42. this.passes.push(pass);
  43. pass.setSize(this._width * this._pixelRatio, this._height * this._pixelRatio);
  44. }
  45. insertPass(pass, index) {
  46. this.passes.splice(index, 0, pass);
  47. pass.setSize(this._width * this._pixelRatio, this._height * this._pixelRatio);
  48. }
  49. removePass(pass) {
  50. const index = this.passes.indexOf(pass);
  51. if (index !== -1) {
  52. this.passes.splice(index, 1);
  53. }
  54. }
  55. isLastEnabledPass(passIndex) {
  56. for (let i = passIndex + 1; i < this.passes.length; i++) {
  57. if (this.passes[i].enabled) {
  58. return false;
  59. }
  60. }
  61. return true;
  62. }
  63. render(deltaTime) {
  64. // deltaTime value is in seconds
  65. if (deltaTime === undefined) {
  66. deltaTime = this.clock.getDelta();
  67. }
  68. const currentRenderTarget = this.renderer.getRenderTarget();
  69. let maskActive = false;
  70. for (let i = 0, il = this.passes.length; i < il; i++) {
  71. const pass = this.passes[i];
  72. if (pass.enabled === false) continue;
  73. pass.renderToScreen = this.renderToScreen && this.isLastEnabledPass(i);
  74. pass.render(this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive);
  75. if (pass.needsSwap) {
  76. if (maskActive) {
  77. const context = this.renderer.getContext();
  78. const stencil = this.renderer.state.buffers.stencil; //context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
  79. stencil.setFunc(context.NOTEQUAL, 1, 0xffffffff);
  80. this.copyPass.render(this.renderer, this.writeBuffer, this.readBuffer, deltaTime); //context.stencilFunc( context.EQUAL, 1, 0xffffffff );
  81. stencil.setFunc(context.EQUAL, 1, 0xffffffff);
  82. }
  83. this.swapBuffers();
  84. }
  85. if (THREE.MaskPass !== undefined) {
  86. if (pass instanceof THREE.MaskPass) {
  87. maskActive = true;
  88. } else if (pass instanceof THREE.ClearMaskPass) {
  89. maskActive = false;
  90. }
  91. }
  92. }
  93. this.renderer.setRenderTarget(currentRenderTarget);
  94. }
  95. reset(renderTarget) {
  96. if (renderTarget === undefined) {
  97. const size = this.renderer.getSize(new THREE.Vector2());
  98. this._pixelRatio = this.renderer.getPixelRatio();
  99. this._width = size.width;
  100. this._height = size.height;
  101. renderTarget = this.renderTarget1.clone();
  102. renderTarget.setSize(this._width * this._pixelRatio, this._height * this._pixelRatio);
  103. }
  104. this.renderTarget1.dispose();
  105. this.renderTarget2.dispose();
  106. this.renderTarget1 = renderTarget;
  107. this.renderTarget2 = renderTarget.clone();
  108. this.writeBuffer = this.renderTarget1;
  109. this.readBuffer = this.renderTarget2;
  110. }
  111. setSize(width, height) {
  112. this._width = width;
  113. this._height = height;
  114. const effectiveWidth = this._width * this._pixelRatio;
  115. const effectiveHeight = this._height * this._pixelRatio;
  116. this.renderTarget1.setSize(effectiveWidth, effectiveHeight);
  117. this.renderTarget2.setSize(effectiveWidth, effectiveHeight);
  118. for (let i = 0; i < this.passes.length; i++) {
  119. this.passes[i].setSize(effectiveWidth, effectiveHeight);
  120. }
  121. }
  122. setPixelRatio(pixelRatio) {
  123. this._pixelRatio = pixelRatio;
  124. this.setSize(this._width, this._height);
  125. }
  126. }
  127. class Pass {
  128. constructor() {
  129. // if set to true, the pass is processed by the composer
  130. this.enabled = true; // if set to true, the pass indicates to swap read and write buffer after rendering
  131. this.needsSwap = true; // if set to true, the pass clears its buffer before rendering
  132. this.clear = false; // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer.
  133. this.renderToScreen = false;
  134. }
  135. setSize() {}
  136. render() {
  137. console.error("THREE.Pass: .render() must be implemented in derived pass.");
  138. }
  139. } // Helper for passes that need to fill the viewport with a single quad.
  140. const _camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); // https://github.com/mrdoob/three.js/pull/21358
  141. const _geometry = new THREE.BufferGeometry();
  142. _geometry.setAttribute(
  143. "position",
  144. new THREE.Float32BufferAttribute([-1, 3, 0, -1, -1, 0, 3, -1, 0], 3)
  145. );
  146. _geometry.setAttribute("uv", new THREE.Float32BufferAttribute([0, 2, 0, 0, 2, 0], 2));
  147. class FullScreenQuad {
  148. constructor(material) {
  149. this._mesh = new THREE.Mesh(_geometry, material);
  150. }
  151. dispose() {
  152. this._mesh.geometry.dispose();
  153. }
  154. render(renderer) {
  155. renderer.render(this._mesh, _camera);
  156. }
  157. get material() {
  158. return this._mesh.material;
  159. }
  160. set material(value) {
  161. this._mesh.material = value;
  162. }
  163. }
  164. THREE.EffectComposer = EffectComposer;
  165. THREE.FullScreenQuad = FullScreenQuad;
  166. THREE.Pass = Pass;
  167. })();