RTTNode.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import {
  2. Mesh,
  3. OrthographicCamera,
  4. PlaneGeometry,
  5. Scene,
  6. WebGLRenderTarget
  7. } from '../../../../build/three.module.js';
  8. import { NodeBuilder } from '../core/NodeBuilder.js';
  9. import { NodeMaterial } from '../materials/NodeMaterial.js';
  10. import { TextureNode } from './TextureNode.js';
  11. class RTTNode extends TextureNode {
  12. constructor( width, height, input, options = {} ) {
  13. const renderTarget = new WebGLRenderTarget( width, height, options );
  14. super( renderTarget.texture );
  15. this.input = input;
  16. this.clear = options.clear !== undefined ? options.clear : true;
  17. this.renderTarget = renderTarget;
  18. this.material = new NodeMaterial();
  19. this.camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
  20. this.scene = new Scene();
  21. this.quad = new Mesh( new PlaneGeometry( 2, 2 ), this.material );
  22. this.quad.frustumCulled = false; // Avoid getting clipped
  23. this.scene.add( this.quad );
  24. this.render = true;
  25. }
  26. build( builder, output, uuid ) {
  27. const rttBuilder = new NodeBuilder();
  28. rttBuilder.nodes = builder.nodes;
  29. rttBuilder.updaters = builder.updaters;
  30. this.material.fragment.value = this.input;
  31. this.material.build( { builder: rttBuilder } );
  32. return super.build( builder, output, uuid );
  33. }
  34. updateFramesaveTo( frame ) {
  35. this.saveTo.render = false;
  36. if ( this.saveTo !== this.saveToCurrent ) {
  37. if ( this.saveToMaterial ) this.saveToMaterial.dispose();
  38. const material = new NodeMaterial();
  39. material.fragment.value = this;
  40. material.build();
  41. const scene = new Scene();
  42. const quad = new Mesh( new PlaneGeometry( 2, 2 ), material );
  43. quad.frustumCulled = false; // Avoid getting clipped
  44. scene.add( quad );
  45. this.saveToScene = scene;
  46. this.saveToMaterial = material;
  47. }
  48. this.saveToCurrent = this.saveTo;
  49. frame.renderer.setRenderTarget( this.saveTo.renderTarget );
  50. if ( this.saveTo.clear ) frame.renderer.clear();
  51. frame.renderer.render( this.saveToScene, this.camera );
  52. }
  53. updateFrame( frame ) {
  54. if ( frame.renderer ) {
  55. // from the second frame
  56. if ( this.saveTo && this.saveTo.render === false ) {
  57. this.updateFramesaveTo( frame );
  58. }
  59. if ( this.render ) {
  60. if ( this.material.uniforms.renderTexture ) {
  61. this.material.uniforms.renderTexture.value = frame.renderTexture;
  62. }
  63. frame.renderer.setRenderTarget( this.renderTarget );
  64. if ( this.clear ) frame.renderer.clear();
  65. frame.renderer.render( this.scene, this.camera );
  66. }
  67. // first frame
  68. if ( this.saveTo && this.saveTo.render === true ) {
  69. this.updateFramesaveTo( frame );
  70. }
  71. } else {
  72. console.warn( 'RTTNode need a renderer in NodeFrame' );
  73. }
  74. }
  75. copy( source ) {
  76. super.copy( source );
  77. this.saveTo = source.saveTo;
  78. return this;
  79. }
  80. toJSON( meta ) {
  81. let data = this.getJSONNode( meta );
  82. if ( ! data ) {
  83. data = super.toJSON( meta );
  84. if ( this.saveTo ) data.saveTo = this.saveTo.toJSON( meta ).uuid;
  85. }
  86. return data;
  87. }
  88. }
  89. RTTNode.prototype.nodeType = 'RTT';
  90. export { RTTNode };