TransitionNode.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import { TempNode } from 'three/webgpu';
  2. import { nodeObject, Fn, float, uv, convertToTexture, vec4, If, int, clamp, sub, mix } from 'three/tsl';
  3. /**
  4. * Post processing node for creating a transition effect between scenes.
  5. *
  6. * @augments TempNode
  7. * @three_import import { transition } from 'three/addons/tsl/display/TransitionNode.js';
  8. */
  9. class TransitionNode extends TempNode {
  10. static get type() {
  11. return 'TransitionNode';
  12. }
  13. /**
  14. * Constructs a new transition node.
  15. *
  16. * @param {TextureNode} textureNodeA - A texture node that represents the beauty pass of the first scene.
  17. * @param {TextureNode} textureNodeB - A texture node that represents the beauty pass of the second scene.
  18. * @param {TextureNode} mixTextureNode - A texture node that defines how the transition effect should look like.
  19. * @param {Node<float>} mixRatioNode - The interpolation factor that controls the mix.
  20. * @param {Node<float>} thresholdNode - Can be used to tweak the linear interpolation.
  21. * @param {Node<float>} useTextureNode - Whether `mixTextureNode` should influence the transition or not.
  22. */
  23. constructor( textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode ) {
  24. super( 'vec4' );
  25. /**
  26. * A texture node that represents the beauty pass of the first scene.
  27. *
  28. * @type {TextureNode}
  29. */
  30. this.textureNodeA = textureNodeA;
  31. /**
  32. * A texture node that represents the beauty pass of the second scene.
  33. *
  34. * @type {TextureNode}
  35. */
  36. this.textureNodeB = textureNodeB;
  37. /**
  38. * A texture that defines how the transition effect should look like.
  39. *
  40. * @type {TextureNode}
  41. */
  42. this.mixTextureNode = mixTextureNode;
  43. /**
  44. * The interpolation factor that controls the mix.
  45. *
  46. * @type {Node<float>}
  47. */
  48. this.mixRatioNode = mixRatioNode;
  49. /**
  50. * Can be used to tweak the linear interpolation.
  51. *
  52. * @type {Node<float>}
  53. */
  54. this.thresholdNode = thresholdNode;
  55. /**
  56. * Whether `mixTextureNode` should influence the transition or not.
  57. *
  58. * @type {Node<float>}
  59. */
  60. this.useTextureNode = useTextureNode;
  61. }
  62. /**
  63. * This method is used to setup the effect's TSL code.
  64. *
  65. * @param {NodeBuilder} builder - The current node builder.
  66. * @return {ShaderCallNodeInternal}
  67. */
  68. setup() {
  69. const { textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode } = this;
  70. const sampleTexture = ( textureNode ) => {
  71. const uvNodeTexture = textureNode.uvNode || uv();
  72. return textureNode.sample( uvNodeTexture );
  73. };
  74. const transition = Fn( () => {
  75. const texelOne = sampleTexture( textureNodeA );
  76. const texelTwo = sampleTexture( textureNodeB );
  77. const color = vec4().toVar();
  78. If( useTextureNode.equal( int( 1 ) ), () => {
  79. const transitionTexel = sampleTexture( mixTextureNode );
  80. const r = mixRatioNode.mul( thresholdNode.mul( 2.0 ).add( 1.0 ) ).sub( thresholdNode );
  81. const mixf = clamp( sub( transitionTexel.r, r ).mul( float( 1.0 ).div( thresholdNode ) ), 0.0, 1.0 );
  82. color.assign( mix( texelOne, texelTwo, mixf ) );
  83. } ).Else( () => {
  84. color.assign( mix( texelTwo, texelOne, mixRatioNode ) );
  85. } );
  86. return color;
  87. } );
  88. const outputNode = transition();
  89. return outputNode;
  90. }
  91. }
  92. export default TransitionNode;
  93. /**
  94. * TSL function for creating a transition node for post processing.
  95. *
  96. * @tsl
  97. * @function
  98. * @param {Node<vec4>} nodeA - A texture node that represents the beauty pass of the first scene.
  99. * @param {Node<vec4>} nodeB - A texture node that represents the beauty pass of the second scene.
  100. * @param {Node<vec4>} mixTextureNode - A texture that defines how the transition effect should look like.
  101. * @param {Node<float> | number} mixRatio - The interpolation factor that controls the mix.
  102. * @param {Node<float> | number} threshold - Can be used to tweak the linear interpolation.
  103. * @param {Node<float> | number} useTexture - Whether `mixTextureNode` should influence the transition or not.
  104. * @returns {TransitionNode}
  105. */
  106. export const transition = ( nodeA, nodeB, mixTextureNode, mixRatio, threshold, useTexture ) => nodeObject( new TransitionNode( convertToTexture( nodeA ), convertToTexture( nodeB ), convertToTexture( mixTextureNode ), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) ) );