File size: 4,260 Bytes
a28eca3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { TempNode } from 'three/webgpu';
import { nodeObject, Fn, float, uv, convertToTexture, vec4, If, int, clamp, sub, mix } from 'three/tsl';

/** @module TransitionNode **/

/**
 * Post processing node for creating a transition effect between scenes.
 *
 * @augments TempNode
 */
class TransitionNode extends TempNode {

	static get type() {

		return 'TransitionNode';

	}

	/**
	 * Constructs a new transition node.
	 *
	 * @param {TextureNode} textureNodeA - A texture node that represents the beauty pass of the first scene.
	 * @param {TextureNode} textureNodeB - A texture node that represents the beauty pass of the second scene.
	 * @param {TextureNode} mixTextureNode - A texture node that defines how the transition effect should look like.
	 * @param {Node<float>} mixRatioNode - The interpolation factor that controls the mix.
	 * @param {Node<float>} thresholdNode - Can be used to tweak the linear interpolation.
	 * @param {Node<float>} useTextureNode - Whether `mixTextureNode` should influence the transition or not.
	 */
	constructor( textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode ) {

		super( 'vec4' );

		/**
		 * A texture node that represents the beauty pass of the first scene.
		 *
		 * @type {TextureNode}
		 */
		this.textureNodeA = textureNodeA;

		/**
		 * A texture node that represents the beauty pass of the second scene.
		 *
		 * @type {TextureNode}
		 */
		this.textureNodeB = textureNodeB;

		/**
		 * A texture that defines how the transition effect should look like.
		 *
		 * @type {TextureNode}
		 */
		this.mixTextureNode = mixTextureNode;

		/**
		 * The interpolation factor that controls the mix.
		 *
		 * @type {Node<float>}
		 */
		this.mixRatioNode = mixRatioNode;

		/**
		 * Can be used to tweak the linear interpolation.
		 *
		 * @type {Node<float>}
		 */
		this.thresholdNode = thresholdNode;

		/**
		 * Whether `mixTextureNode` should influence the transition or not.
		 *
		 * @type {Node<float>}
		 */
		this.useTextureNode = useTextureNode;

	}

	/**
	 * This method is used to setup the effect's TSL code.
	 *
	 * @param {NodeBuilder} builder - The current node builder.
	 * @return {ShaderCallNodeInternal}
	 */
	setup() {

		const { textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode } = this;

		const sampleTexture = ( textureNode ) => {

			const uvNodeTexture = textureNode.uvNode || uv();
			return textureNode.sample( uvNodeTexture );

		};

		const transition = Fn( () => {

			const texelOne = sampleTexture( textureNodeA );
			const texelTwo = sampleTexture( textureNodeB );

			const color = vec4().toVar();

			If( useTextureNode.equal( int( 1 ) ), () => {

				const transitionTexel = sampleTexture( mixTextureNode );
				const r = mixRatioNode.mul( thresholdNode.mul( 2.0 ).add( 1.0 ) ).sub( thresholdNode );
				const mixf = clamp( sub( transitionTexel.r, r ).mul( float( 1.0 ).div( thresholdNode ) ), 0.0, 1.0 );

				color.assign( mix( texelOne, texelTwo, mixf ) );

			} ).Else( () => {

				color.assign( mix( texelTwo, texelOne, mixRatioNode ) );

			} );

			return color;

		} );

		const outputNode = transition();

		return outputNode;

	}

}

export default TransitionNode;

/**
 * TSL function for creating a transition node for post processing.
 *
 * @function
 * @param {Node<vec4>} nodeA - A texture node that represents the beauty pass of the first scene.
 * @param {Node<vec4>} nodeB - A texture node that represents the beauty pass of the second scene.
 * @param {Node<vec4>} mixTextureNode - A texture that defines how the transition effect should look like.
 * @param {Node<float> | Number} mixRatio - The interpolation factor that controls the mix.
 * @param {Node<float> | Number} threshold - Can be used to tweak the linear interpolation.
 * @param {Node<float> | Number} useTexture - Whether `mixTextureNode` should influence the transition or not.
 * @returns {TransitionNode}
 */
export const transition = ( nodeA, nodeB, mixTextureNode, mixRatio, threshold, useTexture ) => nodeObject( new TransitionNode( convertToTexture( nodeA ), convertToTexture( nodeB ), convertToTexture( mixTextureNode ), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) ) );