StereoPassNode.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import { StereoCamera, Vector2, PassNode, RendererUtils } from 'three/webgpu';
  2. import { nodeObject } from 'three/tsl';
  3. const _size = /*@__PURE__*/ new Vector2();
  4. let _rendererState;
  5. /**
  6. * A special render pass node that renders the scene as a stereoscopic image.
  7. *
  8. * @augments PassNode
  9. * @three_import import { stereoPass } from 'three/addons/tsl/display/StereoPassNode.js';
  10. */
  11. class StereoPassNode extends PassNode {
  12. static get type() {
  13. return 'StereoPassNode';
  14. }
  15. /**
  16. * Constructs a new stereo pass node.
  17. *
  18. * @param {Scene} scene - The scene to render.
  19. * @param {Camera} camera - The camera to render the scene with.
  20. */
  21. constructor( scene, camera ) {
  22. super( PassNode.COLOR, scene, camera );
  23. /**
  24. * This flag can be used for type testing.
  25. *
  26. * @type {boolean}
  27. * @readonly
  28. * @default true
  29. */
  30. this.isStereoPassNode = true;
  31. /**
  32. * The internal stereo camera that is used to render the scene.
  33. *
  34. * @type {StereoCamera}
  35. */
  36. this.stereo = new StereoCamera();
  37. this.stereo.aspect = 0.5;
  38. }
  39. /**
  40. * This method is used to render the stereo effect once per frame.
  41. *
  42. * @param {NodeFrame} frame - The current node frame.
  43. */
  44. updateBefore( frame ) {
  45. const { renderer } = frame;
  46. const { scene, camera, stereo, renderTarget } = this;
  47. _rendererState = RendererUtils.resetRendererState( renderer, _rendererState );
  48. //
  49. this._pixelRatio = renderer.getPixelRatio();
  50. stereo.cameraL.coordinateSystem = renderer.coordinateSystem;
  51. stereo.cameraR.coordinateSystem = renderer.coordinateSystem;
  52. stereo.update( camera );
  53. const size = renderer.getSize( _size );
  54. this.setSize( size.width, size.height );
  55. renderer.autoClear = false;
  56. this._cameraNear.value = camera.near;
  57. this._cameraFar.value = camera.far;
  58. for ( const name in this._previousTextures ) {
  59. this.toggleTexture( name );
  60. }
  61. renderer.setRenderTarget( renderTarget );
  62. renderer.setMRT( this._mrt );
  63. renderer.clear();
  64. renderTarget.scissorTest = true;
  65. renderTarget.scissor.set( 0, 0, renderTarget.width / 2, renderTarget.height );
  66. renderTarget.viewport.set( 0, 0, renderTarget.width / 2, renderTarget.height );
  67. renderer.render( scene, stereo.cameraL );
  68. renderTarget.scissor.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height );
  69. renderTarget.viewport.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height );
  70. renderer.render( scene, stereo.cameraR );
  71. renderTarget.scissorTest = false;
  72. // restore
  73. RendererUtils.restoreRendererState( renderer, _rendererState );
  74. }
  75. }
  76. export default StereoPassNode;
  77. /**
  78. * TSL function for creating a stereo pass node for stereoscopic rendering.
  79. *
  80. * @tsl
  81. * @function
  82. * @param {Scene} scene - The scene to render.
  83. * @param {Camera} camera - The camera to render the scene with.
  84. * @returns {StereoPassNode}
  85. */
  86. export const stereoPass = ( scene, camera ) => nodeObject( new StereoPassNode( scene, camera ) );