Jelajahi Sumber

TSL: Introduce `OnBeforeRenderPipeline` and `OnAfterRenderPipeline` and update context directly on material (#34025)

sunag 1 Minggu lalu
induk
melakukan
dd3c651d76

+ 3 - 2
examples/jsm/tsl/display/AnaglyphPassNode.js

@@ -1,5 +1,5 @@
 import { Matrix3, NodeMaterial, Vector3 } from 'three/webgpu';
 import { Matrix3, NodeMaterial, Vector3 } from 'three/webgpu';
-import { clamp, Fn, vec4, uv, uniform, max } from 'three/tsl';
+import { clamp, Fn, vec4, uv, uniform, max, context } from 'three/tsl';
 import StereoCompositePassNode from './StereoCompositePassNode.js';
 import StereoCompositePassNode from './StereoCompositePassNode.js';
 import { frameCorners } from '../../utils/CameraUtils.js';
 import { frameCorners } from '../../utils/CameraUtils.js';
 
 
@@ -523,7 +523,8 @@ class AnaglyphPassNode extends StereoCompositePassNode {
 		} );
 		} );
 
 
 		const material = this._material || ( this._material = new NodeMaterial() );
 		const material = this._material || ( this._material = new NodeMaterial() );
-		material.fragmentNode = anaglyph().context( builder.getSharedContext() );
+		material.contextNode = context( builder.getSharedContext() );
+		material.fragmentNode = anaglyph();
 		material.name = 'Anaglyph';
 		material.name = 'Anaglyph';
 		material.needsUpdate = true;
 		material.needsUpdate = true;
 
 

+ 3 - 2
examples/jsm/tsl/display/BilateralBlurNode.js

@@ -1,5 +1,5 @@
 import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
 import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
-import { Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, luminance, abs, exp, max } from 'three/tsl';
+import { Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, luminance, abs, exp, max, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 
 
@@ -302,7 +302,8 @@ class BilateralBlurNode extends TempNode {
 		//
 		//
 
 
 		const material = this._material || ( this._material = new NodeMaterial() );
 		const material = this._material || ( this._material = new NodeMaterial() );
-		material.fragmentNode = blur().context( builder.getSharedContext() );
+		material.contextNode = context( builder.getSharedContext() );
+		material.fragmentNode = blur();
 		material.name = 'Bilateral_blur';
 		material.name = 'Bilateral_blur';
 		material.needsUpdate = true;
 		material.needsUpdate = true;
 
 

+ 12 - 7
examples/jsm/tsl/display/BloomNode.js

@@ -1,5 +1,5 @@
 import { HalfFloatType, RenderTarget, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils, NodeUpdateType } from 'three/webgpu';
 import { HalfFloatType, RenderTarget, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils, NodeUpdateType } from 'three/webgpu';
-import { nodeObject, Fn, float, uv, passTexture, uniform, Loop, texture, luminance, smoothstep, mix, vec4, uniformArray, add, int, array } from 'three/tsl';
+import { nodeObject, Fn, float, uv, passTexture, uniform, Loop, texture, luminance, smoothstep, mix, vec4, uniformArray, add, int, array, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -408,10 +408,13 @@ class BloomNode extends TempNode {
 	 */
 	 */
 	setup( builder ) {
 	setup( builder ) {
 
 
+		const sharedContext = context( builder.getSharedContext() );
+
 		// luminosity high pass material
 		// luminosity high pass material
 
 
 		this._highPassFilterMaterial = this._highPassFilterMaterial || new NodeMaterial();
 		this._highPassFilterMaterial = this._highPassFilterMaterial || new NodeMaterial();
-		this._highPassFilterMaterial.fragmentNode = this.highPassFn( { input: this.inputNode, threshold: this.threshold, smoothWidth: this.smoothWidth } ).context( builder.getSharedContext() );
+		this._highPassFilterMaterial.contextNode = sharedContext;
+		this._highPassFilterMaterial.fragmentNode = this.highPassFn( { input: this.inputNode, threshold: this.threshold, smoothWidth: this.smoothWidth } );
 		this._highPassFilterMaterial.name = 'Bloom_highPass';
 		this._highPassFilterMaterial.name = 'Bloom_highPass';
 		this._highPassFilterMaterial.needsUpdate = true;
 		this._highPassFilterMaterial.needsUpdate = true;
 
 
@@ -423,7 +426,7 @@ class BloomNode extends TempNode {
 
 
 		for ( let i = 0; i < this._nMips; i ++ ) {
 		for ( let i = 0; i < this._nMips; i ++ ) {
 
 
-			this._separableBlurMaterials.push( this._getSeparableBlurMaterial( builder, kernelSizeArray[ i ] ) );
+			this._separableBlurMaterials.push( this._getSeparableBlurMaterial( sharedContext, kernelSizeArray[ i ] ) );
 
 
 		}
 		}
 
 
@@ -447,7 +450,8 @@ class BloomNode extends TempNode {
 		} );
 		} );
 
 
 		this._compositeMaterial = this._compositeMaterial || new NodeMaterial();
 		this._compositeMaterial = this._compositeMaterial || new NodeMaterial();
-		this._compositeMaterial.fragmentNode = compositePass().context( builder.getSharedContext() );
+		this._compositeMaterial.contextNode = sharedContext;
+		this._compositeMaterial.fragmentNode = compositePass();
 		this._compositeMaterial.name = 'Bloom_comp';
 		this._compositeMaterial.name = 'Bloom_comp';
 		this._compositeMaterial.needsUpdate = true;
 		this._compositeMaterial.needsUpdate = true;
 
 
@@ -492,11 +496,11 @@ class BloomNode extends TempNode {
 	 * Create a separable blur material for the given kernel radius.
 	 * Create a separable blur material for the given kernel radius.
 	 *
 	 *
 	 * @private
 	 * @private
-	 * @param {NodeBuilder} builder - The current node builder.
+	 * @param {NodeContext} sharedContext
 	 * @param {number} kernelRadius - The kernel radius.
 	 * @param {number} kernelRadius - The kernel radius.
 	 * @return {NodeMaterial}
 	 * @return {NodeMaterial}
 	 */
 	 */
-	_getSeparableBlurMaterial( builder, kernelRadius ) {
+	_getSeparableBlurMaterial( sharedContext, kernelRadius ) {
 
 
 		const coefficients = [];
 		const coefficients = [];
 		const sigma = kernelRadius / 3;
 		const sigma = kernelRadius / 3;
@@ -554,7 +558,8 @@ class BloomNode extends TempNode {
 		} );
 		} );
 
 
 		const separableBlurMaterial = new NodeMaterial();
 		const separableBlurMaterial = new NodeMaterial();
-		separableBlurMaterial.fragmentNode = separableBlurPass().context( builder.getSharedContext() );
+		separableBlurMaterial.contextNode = sharedContext;
+		separableBlurMaterial.fragmentNode = separableBlurPass();
 		separableBlurMaterial.name = 'Bloom_separable';
 		separableBlurMaterial.name = 'Bloom_separable';
 		separableBlurMaterial.needsUpdate = true;
 		separableBlurMaterial.needsUpdate = true;
 
 

+ 11 - 5
examples/jsm/tsl/display/DepthOfFieldNode.js

@@ -1,5 +1,5 @@
 import { TempNode, NodeMaterial, NodeUpdateType, RenderTarget, Vector2, HalfFloatType, RedFormat, QuadMesh, RendererUtils } from 'three/webgpu';
 import { TempNode, NodeMaterial, NodeUpdateType, RenderTarget, Vector2, HalfFloatType, RedFormat, QuadMesh, RendererUtils } from 'three/webgpu';
-import { convertToTexture, nodeObject, Fn, uniform, smoothstep, step, texture, max, uniformArray, outputStruct, property, vec4, vec3, uv, Loop, min, mix, float } from 'three/tsl';
+import { convertToTexture, nodeObject, Fn, uniform, smoothstep, step, texture, max, uniformArray, outputStruct, property, vec4, vec3, uv, Loop, min, mix, float, context } from 'three/tsl';
 import { gaussianBlur } from './GaussianBlurNode.js';
 import { gaussianBlur } from './GaussianBlurNode.js';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
@@ -351,6 +351,8 @@ class DepthOfFieldNode extends TempNode {
 	 */
 	 */
 	setup( builder ) {
 	setup( builder ) {
 
 
+		const sharedContext = context( builder.getSharedContext() );
+
 		const kernels = this._generateKernels();
 		const kernels = this._generateKernels();
 
 
 		// CoC, near and far fields
 		// CoC, near and far fields
@@ -372,7 +374,8 @@ class DepthOfFieldNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._CoCMaterial.colorNode = CoC().context( builder.getSharedContext() );
+		this._CoCMaterial.contextNode = sharedContext;
+		this._CoCMaterial.colorNode = CoC();
 		this._CoCMaterial.outputNode = outputNode;
 		this._CoCMaterial.outputNode = outputNode;
 		this._CoCMaterial.needsUpdate = true;
 		this._CoCMaterial.needsUpdate = true;
 
 
@@ -408,7 +411,8 @@ class DepthOfFieldNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._blur64Material.fragmentNode = blur64().context( builder.getSharedContext() );
+		this._blur64Material.contextNode = sharedContext;
+		this._blur64Material.fragmentNode = blur64();
 		this._blur64Material.needsUpdate = true;
 		this._blur64Material.needsUpdate = true;
 
 
 		// bokeh 16 blur pass
 		// bokeh 16 blur pass
@@ -437,7 +441,8 @@ class DepthOfFieldNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._blur16Material.fragmentNode = blur16().context( builder.getSharedContext() );
+		this._blur16Material.contextNode = sharedContext;
+		this._blur16Material.fragmentNode = blur16();
 		this._blur16Material.needsUpdate = true;
 		this._blur16Material.needsUpdate = true;
 
 
 		// composite
 		// composite
@@ -466,7 +471,8 @@ class DepthOfFieldNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._compositeMaterial.fragmentNode = composite().context( builder.getSharedContext() );
+		this._compositeMaterial.contextNode = sharedContext;
+		this._compositeMaterial.fragmentNode = composite();
 		this._compositeMaterial.needsUpdate = true;
 		this._compositeMaterial.needsUpdate = true;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 6 - 4
examples/jsm/tsl/display/FSR1Node.js

@@ -1,5 +1,5 @@
 import { HalfFloatType, RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
 import { HalfFloatType, RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
-import { Fn, float, vec2, vec3, vec4, ivec2, int, uv, floor, fract, abs, max, min, clamp, saturate, sqrt, select, exp2, nodeObject, passTexture, textureSize, textureLoad, convertToTexture } from 'three/tsl';
+import { Fn, float, vec2, vec3, vec4, ivec2, int, uv, floor, fract, abs, max, min, clamp, saturate, sqrt, select, exp2, nodeObject, passTexture, textureSize, textureLoad, convertToTexture, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -423,15 +423,17 @@ class FSR1Node extends TempNode {
 
 
 		//
 		//
 
 
-		const context = builder.getSharedContext();
+		const sharedContext = context( builder.getSharedContext() );
 
 
 		const easuMaterial = this._easuMaterial || ( this._easuMaterial = new NodeMaterial() );
 		const easuMaterial = this._easuMaterial || ( this._easuMaterial = new NodeMaterial() );
-		easuMaterial.fragmentNode = easu().context( context );
+		easuMaterial.contextNode = sharedContext;
+		easuMaterial.fragmentNode = easu();
 		easuMaterial.name = 'FSR1_EASU';
 		easuMaterial.name = 'FSR1_EASU';
 		easuMaterial.needsUpdate = true;
 		easuMaterial.needsUpdate = true;
 
 
 		const rcasMaterial = this._rcasMaterial || ( this._rcasMaterial = new NodeMaterial() );
 		const rcasMaterial = this._rcasMaterial || ( this._rcasMaterial = new NodeMaterial() );
-		rcasMaterial.fragmentNode = rcas().context( context );
+		rcasMaterial.contextNode = sharedContext;
+		rcasMaterial.fragmentNode = rcas();
 		rcasMaterial.name = 'FSR1_RCAS';
 		rcasMaterial.name = 'FSR1_RCAS';
 		rcasMaterial.needsUpdate = true;
 		rcasMaterial.needsUpdate = true;
 
 

+ 5 - 3
examples/jsm/tsl/display/GTAONode.js

@@ -1,5 +1,5 @@
 import { DataTexture, RenderTarget, RepeatWrapping, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils, RedFormat } from 'three/webgpu';
 import { DataTexture, RenderTarget, RepeatWrapping, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils, RedFormat } from 'three/webgpu';
-import { reference, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getNormalFromDepth, getViewPosition, getScreenPositionFromClip, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec2, vec3, vec4, int, dot, max, min, pow, abs, If, textureSize, sin, cos, PI, texture, passTexture, mat3, normalize, cross, mix, acos, clamp, interleavedGradientNoise, screenCoordinate, rand } from 'three/tsl';
+import { reference, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getNormalFromDepth, getViewPosition, getScreenPositionFromClip, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec2, vec3, vec4, int, dot, max, min, pow, abs, If, textureSize, sin, cos, PI, texture, passTexture, mat3, normalize, cross, mix, acos, clamp, interleavedGradientNoise, screenCoordinate, rand, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -350,7 +350,8 @@ class GTAONode extends TempNode {
 
 
 			this._currentSamples = this.samples.value;
 			this._currentSamples = this.samples.value;
 
 
-			this._material.fragmentNode = this._ao().context( this._sharedContext );
+			this._material.contextNode = context( this._sharedContext );
+			this._material.fragmentNode = this._ao();
 			this._material.needsUpdate = true;
 			this._material.needsUpdate = true;
 
 
 		}
 		}
@@ -571,7 +572,8 @@ class GTAONode extends TempNode {
 		this._sharedContext = builder.getSharedContext();
 		this._sharedContext = builder.getSharedContext();
 		this._currentSamples = this.samples.value;
 		this._currentSamples = this.samples.value;
 
 
-		this._material.fragmentNode = this._ao().context( this._sharedContext );
+		this._material.contextNode = context( builder.getSharedContext() );
+		this._material.fragmentNode = this._ao();
 		this._material.needsUpdate = true;
 		this._material.needsUpdate = true;
 
 
 		//
 		//

+ 3 - 2
examples/jsm/tsl/display/GaussianBlurNode.js

@@ -1,5 +1,5 @@
 import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
 import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
-import { Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, premultiplyAlpha, unpremultiplyAlpha } from 'three/tsl';
+import { Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, premultiplyAlpha, unpremultiplyAlpha, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 
 
@@ -287,7 +287,8 @@ class GaussianBlurNode extends TempNode {
 		//
 		//
 
 
 		const material = this._material || ( this._material = new NodeMaterial() );
 		const material = this._material || ( this._material = new NodeMaterial() );
-		material.fragmentNode = blur().context( builder.getSharedContext() );
+		material.contextNode = context( builder.getSharedContext() );
+		material.fragmentNode = blur();
 		material.name = 'Gaussian_blur';
 		material.name = 'Gaussian_blur';
 		material.needsUpdate = true;
 		material.needsUpdate = true;
 
 

+ 3 - 2
examples/jsm/tsl/display/GodraysNode.js

@@ -1,5 +1,5 @@
 import { Frustum, Matrix4, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, Vector3, Plane } from 'three/webgpu';
 import { Frustum, Matrix4, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, Vector3, Plane } from 'three/webgpu';
-import { cubeTexture, clamp, viewZToPerspectiveDepth, logarithmicDepthToViewZ, float, Loop, max, Fn, passTexture, uv, dot, uniformArray, If, getViewPosition, uniform, vec4, add, interleavedGradientNoise, screenCoordinate, round, mul, uint, mix, exp, vec3, distance, pow, reference, lightPosition, vec2, bool, texture, perspectiveDepthToViewZ, lightShadowMatrix } from 'three/tsl';
+import { cubeTexture, clamp, viewZToPerspectiveDepth, logarithmicDepthToViewZ, float, Loop, max, Fn, passTexture, uv, dot, uniformArray, If, getViewPosition, uniform, vec4, add, interleavedGradientNoise, screenCoordinate, round, mul, uint, mix, exp, vec3, distance, pow, reference, lightPosition, vec2, bool, texture, perspectiveDepthToViewZ, lightShadowMatrix, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -579,7 +579,8 @@ class GodraysNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._material.fragmentNode = godrays().context( builder.getSharedContext() );
+		this._material.contextNode = context( builder.getSharedContext() );
+		this._material.fragmentNode = godrays();
 		this._material.needsUpdate = true;
 		this._material.needsUpdate = true;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 3 - 2
examples/jsm/tsl/display/LensflareNode.js

@@ -1,5 +1,5 @@
 import { RenderTarget, Vector2, TempNode, NodeUpdateType, QuadMesh, RendererUtils, NodeMaterial } from 'three/webgpu';
 import { RenderTarget, Vector2, TempNode, NodeUpdateType, QuadMesh, RendererUtils, NodeMaterial } from 'three/webgpu';
-import { convertToTexture, nodeObject, Fn, passTexture, uv, vec2, vec3, vec4, max, float, sub, int, Loop, fract, pow, distance } from 'three/tsl';
+import { convertToTexture, nodeObject, Fn, passTexture, uv, vec2, vec3, vec4, max, float, sub, int, Loop, fract, pow, distance, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -239,7 +239,8 @@ class LensflareNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._material.fragmentNode = lensflare().context( builder.getSharedContext() );
+		this._material.contextNode = context( builder.getSharedContext() );
+		this._material.fragmentNode = lensflare();
 		this._material.needsUpdate = true;
 		this._material.needsUpdate = true;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 3 - 2
examples/jsm/tsl/display/ParallaxBarrierPassNode.js

@@ -1,5 +1,5 @@
 import { NodeMaterial } from 'three/webgpu';
 import { NodeMaterial } from 'three/webgpu';
-import { Fn, vec4, uv, If, mod, screenCoordinate } from 'three/tsl';
+import { Fn, vec4, uv, If, mod, screenCoordinate, context } from 'three/tsl';
 import StereoCompositePassNode from './StereoCompositePassNode.js';
 import StereoCompositePassNode from './StereoCompositePassNode.js';
 
 
 /**
 /**
@@ -66,7 +66,8 @@ class ParallaxBarrierPassNode extends StereoCompositePassNode {
 		} );
 		} );
 
 
 		const material = this._material || ( this._material = new NodeMaterial() );
 		const material = this._material || ( this._material = new NodeMaterial() );
-		material.fragmentNode = parallaxBarrier().context( builder.getSharedContext() );
+		material.contextNode = context( builder.getSharedContext() );
+		material.fragmentNode = parallaxBarrier();
 		material.needsUpdate = true;
 		material.needsUpdate = true;
 
 
 		return super.setup( builder );
 		return super.setup( builder );

+ 3 - 2
examples/jsm/tsl/display/RecurrentDenoiseNode.js

@@ -1,4 +1,4 @@
-import { abs, atan, bool, convertToTexture, cos, cross, Discard, dot, EPSILON, exp, float, Fn, getScreenPosition, getViewPosition, If, int, log, Loop, luminance, mat2, max, mix, nodeObject, NodeUpdateType, normalize, passTexture, PI, property, reflect, sin, smoothstep, sqrt, tan, texture, uniform, unpackRGBToNormal, uv, vec2, vec3, vec4 } from 'three/tsl';
+import { abs, atan, bool, convertToTexture, cos, cross, Discard, dot, EPSILON, exp, float, Fn, getScreenPosition, getViewPosition, If, int, log, Loop, luminance, mat2, max, mix, nodeObject, NodeUpdateType, normalize, passTexture, PI, property, reflect, sin, smoothstep, sqrt, tan, texture, uniform, unpackRGBToNormal, uv, vec2, vec3, vec4, context } from 'three/tsl';
 import { HalfFloatType, MathUtils, Matrix4, NodeMaterial, QuadMesh, RendererUtils, RenderTarget, TempNode, Vector2 } from 'three/webgpu';
 import { HalfFloatType, MathUtils, Matrix4, NodeMaterial, QuadMesh, RendererUtils, RenderTarget, TempNode, Vector2 } from 'three/webgpu';
 import { bindAnalyticNoise } from '../utils/RNoise.js';
 import { bindAnalyticNoise } from '../utils/RNoise.js';
 import { ENV_RAY_LENGTH_THRESHOLD } from '../utils/SpecularHelpers.js';
 import { ENV_RAY_LENGTH_THRESHOLD } from '../utils/SpecularHelpers.js';
@@ -880,7 +880,8 @@ class RecurrentDenoiseNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._material.fragmentNode = denoiseFn( uv() ).context( builder.getSharedContext() );
+		this._material.contextNode = context( builder.getSharedContext() );
+		this._material.fragmentNode = denoiseFn( uv() );
 		this._material.needsUpdate = true;
 		this._material.needsUpdate = true;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 9 - 4
examples/jsm/tsl/display/SMAANode.js

@@ -1,5 +1,5 @@
 import { HalfFloatType, LinearFilter, NearestFilter, RenderTarget, Texture, Vector2, QuadMesh, NodeMaterial, TempNode, RendererUtils } from 'three/webgpu';
 import { HalfFloatType, LinearFilter, NearestFilter, RenderTarget, Texture, Vector2, QuadMesh, NodeMaterial, TempNode, RendererUtils } from 'three/webgpu';
-import { abs, Fn, NodeUpdateType, uv, uniform, convertToTexture, vec2, vec4, passTexture, max, step, dot, float, texture, If, Loop, int, Break, sqrt, sign, mix } from 'three/tsl';
+import { abs, Fn, NodeUpdateType, uv, uniform, convertToTexture, vec2, vec4, passTexture, max, step, dot, float, texture, If, Loop, int, Break, sqrt, sign, mix, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -651,13 +651,18 @@ class SMAANode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._materialEdges.fragmentNode = SMAAEdgeDetection().context( builder.getSharedContext() );
+		const sharedContext = context( builder.getSharedContext() );
+
+		this._materialEdges.contextNode = sharedContext;
+		this._materialEdges.fragmentNode = SMAAEdgeDetection();
 		this._materialEdges.needsUpdate = true;
 		this._materialEdges.needsUpdate = true;
 
 
-		this._materialWeights.fragmentNode = SMAAWeights().context( builder.getSharedContext() );
+		this._materialWeights.contextNode = sharedContext;
+		this._materialWeights.fragmentNode = SMAAWeights();
 		this._materialWeights.needsUpdate = true;
 		this._materialWeights.needsUpdate = true;
 
 
-		this._materialBlend.fragmentNode = SMAABlend().context( builder.getSharedContext() );
+		this._materialBlend.contextNode = sharedContext;
+		this._materialBlend.fragmentNode = SMAABlend();
 		this._materialBlend.needsUpdate = true;
 		this._materialBlend.needsUpdate = true;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 9 - 3
examples/jsm/tsl/display/SSAONode.js

@@ -1,5 +1,5 @@
 import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, RedFormat } from 'three/webgpu';
 import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, RedFormat } from 'three/webgpu';
-import { reference, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, getScreenPositionFromClip, vogelDiskSample, interleavedGradientNoise, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec4, int, dot, max, clamp, length, screenCoordinate, PI2, texture, passTexture } from 'three/tsl';
+import { reference, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, getScreenPositionFromClip, vogelDiskSample, interleavedGradientNoise, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec4, int, dot, max, clamp, length, screenCoordinate, PI2, texture, passTexture, context } from 'three/tsl';
 import { depthAwareBlur } from './depthAwareBlur.js';
 import { depthAwareBlur } from './depthAwareBlur.js';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
@@ -385,12 +385,18 @@ class SSAONode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._aoMaterial.fragmentNode = ao().context( builder.getSharedContext() );
+		const sharedContext = context( builder.getSharedContext() );
+
+		// compute ambient occlusion
+
+		this._aoMaterial.contextNode = sharedContext;
+		this._aoMaterial.fragmentNode = ao();
 		this._aoMaterial.needsUpdate = true;
 		this._aoMaterial.needsUpdate = true;
 
 
 		// separable, depth-aware blur ( run horizontally then vertically via `_blurDirection` )
 		// separable, depth-aware blur ( run horizontally then vertically via `_blurDirection` )
 
 
-		this._blurMaterial.fragmentNode = depthAwareBlur( this._blurInput, this.depthNode, this._blurDirection, this._camera, this.blurSharpness, this.radius ).context( builder.getSharedContext() );
+		this._blurMaterial.contextNode = sharedContext;
+		this._blurMaterial.fragmentNode = depthAwareBlur( this._blurInput, this.depthNode, this._blurDirection, this._camera, this.blurSharpness, this.radius );
 		this._blurMaterial.needsUpdate = true;
 		this._blurMaterial.needsUpdate = true;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 3 - 2
examples/jsm/tsl/display/SSGINode.js

@@ -1,5 +1,5 @@
 import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, MathUtils, RGBFormat, RedFormat, UnsignedInt101111Type, UnsignedByteType } from 'three/webgpu';
 import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, MathUtils, RGBFormat, RedFormat, UnsignedInt101111Type, UnsignedByteType } from 'three/webgpu';
-import { clamp, normalize, reference, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth, countOneBits, interleavedGradientNoise, property, outputStruct } from 'three/tsl';
+import { clamp, normalize, reference, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth, countOneBits, interleavedGradientNoise, property, outputStruct, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -648,7 +648,8 @@ class SSGINode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._material.colorNode = gi().context( builder.getSharedContext() );
+		this._material.contextNode = context( builder.getSharedContext() );
+		this._material.colorNode = gi();
 		this._material.outputNode = outputNode;
 		this._material.outputNode = outputNode;
 		this._material.needsUpdate = true;
 		this._material.needsUpdate = true;
 
 

+ 3 - 2
examples/jsm/tsl/display/SSRNode.js

@@ -1,4 +1,4 @@
-import { Break, Continue, Fn, If, Loop, abs, bool, cross, distance, div, dot, float, getScreenPosition, getViewPosition, int, logarithmicDepthToViewZ, luminance, max, min, mix, mul, nodeObject, normalize, orthographicDepthToViewZ, passTexture, perspectiveDepthToViewZ, reference, reflect, sub, texture, trunc, uniform, uv, vec2, vec3, vec4, viewZToPerspectiveDepth } from 'three/tsl';
+import { Break, Continue, Fn, If, Loop, abs, bool, cross, distance, div, dot, float, getScreenPosition, getViewPosition, int, logarithmicDepthToViewZ, luminance, max, min, mix, mul, nodeObject, normalize, orthographicDepthToViewZ, passTexture, perspectiveDepthToViewZ, reference, reflect, sub, texture, trunc, uniform, uv, vec2, vec3, vec4, viewZToPerspectiveDepth, context } from 'three/tsl';
 import { HalfFloatType, LinearFilter, LinearMipmapLinearFilter, Matrix4, NodeMaterial, NodeUpdateType, QuadMesh, RenderTarget, RendererUtils, TempNode, Vector2, Vector3 } from 'three/webgpu';
 import { HalfFloatType, LinearFilter, LinearMipmapLinearFilter, Matrix4, NodeMaterial, NodeUpdateType, QuadMesh, RenderTarget, RendererUtils, TempNode, Vector2, Vector3 } from 'three/webgpu';
 import { bindAnalyticNoise } from '../utils/RNoise.js';
 import { bindAnalyticNoise } from '../utils/RNoise.js';
 import { ENV_RAY_LENGTH, getSpecularDominantFactor, ggxReflectionSample } from '../utils/SpecularHelpers.js';
 import { ENV_RAY_LENGTH, getSpecularDominantFactor, ggxReflectionSample } from '../utils/SpecularHelpers.js';
@@ -625,7 +625,8 @@ class SSRNode extends TempNode {
 
 
 		if ( this._ssrFn === null ) return;
 		if ( this._ssrFn === null ) return;
 
 
-		this._ssrMaterial.fragmentNode = this._ssrFn().context( this._sharedContext );
+		this._ssrMaterial.contextNode = context( this._sharedContext );
+		this._ssrMaterial.fragmentNode = this._ssrFn();
 		this._ssrMaterial.needsUpdate = true;
 		this._ssrMaterial.needsUpdate = true;
 
 
 	}
 	}

+ 3 - 2
examples/jsm/tsl/display/SSSNode.js

@@ -1,5 +1,5 @@
 import { RedFormat, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, UnsignedByteType } from 'three/webgpu';
 import { RedFormat, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, UnsignedByteType } from 'three/webgpu';
-import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, float, Break, Loop, int, max, abs, If, interleavedGradientNoise, screenCoordinate, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, lightPosition, lightTargetPosition, fract, rand, mix } from 'three/tsl';
+import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, float, Break, Loop, int, max, abs, If, interleavedGradientNoise, screenCoordinate, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, lightPosition, lightTargetPosition, fract, rand, mix, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -454,7 +454,8 @@ class SSSNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._material.fragmentNode = sss().context( builder.getSharedContext() );
+		this._material.contextNode = context( builder.getSharedContext() );
+		this._material.fragmentNode = sss();
 		this._material.needsUpdate = true;
 		this._material.needsUpdate = true;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 3 - 4
examples/jsm/tsl/display/SharpenNode.js

@@ -1,5 +1,5 @@
 import { HalfFloatType, RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
 import { HalfFloatType, RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
-import { Fn, float, vec3, vec4, ivec2, int, uv, floor, abs, max, min, exp2, nodeObject, passTexture, textureSize, textureLoad, convertToTexture } from 'three/tsl';
+import { Fn, float, vec3, vec4, ivec2, int, uv, floor, abs, max, min, exp2, nodeObject, passTexture, textureSize, textureLoad, convertToTexture, context } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -236,10 +236,9 @@ class SharpenNode extends TempNode {
 
 
 		//
 		//
 
 
-		const context = builder.getSharedContext();
-
 		const material = this._material || ( this._material = new NodeMaterial() );
 		const material = this._material || ( this._material = new NodeMaterial() );
-		material.fragmentNode = rcas().context( context );
+		material.contextNode = context( builder.getSharedContext() );
+		material.fragmentNode = rcas();
 		material.name = 'Sharpen_RCAS';
 		material.name = 'Sharpen_RCAS';
 		material.needsUpdate = true;
 		material.needsUpdate = true;
 
 

+ 11 - 7
examples/jsm/tsl/display/TAAUNode.js

@@ -1,5 +1,5 @@
 import { HalfFloatType, Vector2, RenderTarget, RendererUtils, QuadMesh, NodeMaterial, TempNode, NodeUpdateType, Matrix4, DepthTexture } from 'three/webgpu';
 import { HalfFloatType, Vector2, RenderTarget, RendererUtils, QuadMesh, NodeMaterial, TempNode, NodeUpdateType, Matrix4, DepthTexture } from 'three/webgpu';
-import { add, exp, float, If, Fn, max, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity, getViewPosition, viewZToPerspectiveDepth, struct, ivec2, mix, property, outputStruct } from 'three/tsl';
+import { add, exp, float, If, Fn, max, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity, getViewPosition, viewZToPerspectiveDepth, struct, ivec2, mix, property, outputStruct, context, OnBeforeRenderPipeline, OnAfterRenderPipeline } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -501,13 +501,13 @@ class TAAUNode extends TempNode {
 	 */
 	 */
 	setup( builder ) {
 	setup( builder ) {
 
 
-		const renderPipeline = builder.context.renderPipeline;
+		if ( builder.renderPipeline && ! builder.context.renderPipelineState.viewOffsetOwner ) {
 
 
-		if ( renderPipeline ) {
+			builder.context.renderPipelineState.viewOffsetOwner = this;
 
 
 			this._needsPostProcessingSync = true;
 			this._needsPostProcessingSync = true;
 
 
-			renderPipeline.context.onBeforeRenderPipeline = () => {
+			OnBeforeRenderPipeline( () => {
 
 
 				const beautyRenderTarget = ( this.beautyNode.isRTTNode ) ? this.beautyNode.renderTarget : this.beautyNode.passNode.renderTarget;
 				const beautyRenderTarget = ( this.beautyNode.isRTTNode ) ? this.beautyNode.renderTarget : this.beautyNode.passNode.renderTarget;
 
 
@@ -516,13 +516,13 @@ class TAAUNode extends TempNode {
 
 
 				this.setViewOffset( inputWidth, inputHeight );
 				this.setViewOffset( inputWidth, inputHeight );
 
 
-			};
+			} );
 
 
-			renderPipeline.context.onAfterRenderPipeline = () => {
+			OnAfterRenderPipeline( () => {
 
 
 				this.clearViewOffset();
 				this.clearViewOffset();
 
 
-			};
+			} );
 
 
 		}
 		}
 
 
@@ -763,6 +763,9 @@ class TAAUNode extends TempNode {
 
 
 		// materials
 		// materials
 
 
+		const sharedContext = context( builder.getSharedContext() );
+
+		this._resolveMaterial.contextNode = sharedContext;
 		this._resolveMaterial.colorNode = resolve();
 		this._resolveMaterial.colorNode = resolve();
 		this._resolveMaterial.outputNode = outputNode;
 		this._resolveMaterial.outputNode = outputNode;
 
 
@@ -775,6 +778,7 @@ class TAAUNode extends TempNode {
 
 
 		} )();
 		} )();
 
 
+		this._seedMaterial.contextNode = sharedContext;
 		this._seedMaterial.outputNode = outputNode;
 		this._seedMaterial.outputNode = outputNode;
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 8 - 7
examples/jsm/tsl/display/TRAANode.js

@@ -1,5 +1,5 @@
 import { HalfFloatType, Vector2, RenderTarget, RendererUtils, QuadMesh, NodeMaterial, TempNode, NodeUpdateType, Matrix4, DepthTexture, FloatType } from 'three/webgpu';
 import { HalfFloatType, Vector2, RenderTarget, RendererUtils, QuadMesh, NodeMaterial, TempNode, NodeUpdateType, Matrix4, DepthTexture, FloatType } from 'three/webgpu';
-import { add, float, If, Fn, max, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity, getViewPosition, viewZToPerspectiveDepth, struct, ivec2, mix, logarithmicDepthToViewZ, viewZToOrthographicDepth } from 'three/tsl';
+import { add, float, If, Fn, max, texture, uniform, uv, vec2, vec4, luminance, convertToTexture, passTexture, velocity, getViewPosition, viewZToPerspectiveDepth, struct, ivec2, mix, logarithmicDepthToViewZ, viewZToOrthographicDepth, context, OnBeforeRenderPipeline, OnAfterRenderPipeline } from 'three/tsl';
 
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
 const _size = /*@__PURE__*/ new Vector2();
@@ -442,24 +442,24 @@ class TRAANode extends TempNode {
 	 */
 	 */
 	setup( builder ) {
 	setup( builder ) {
 
 
-		const renderPipeline = builder.context.renderPipeline;
+		if ( builder.renderPipeline && ! builder.context.renderPipelineState.viewOffsetOwner ) {
 
 
-		if ( renderPipeline ) {
+			builder.context.renderPipelineState.viewOffsetOwner = this;
 
 
 			this._needsPostProcessingSync = true;
 			this._needsPostProcessingSync = true;
 
 
-			renderPipeline.context.onBeforeRenderPipeline = () => {
+			OnBeforeRenderPipeline( () => {
 
 
 				const size = builder.renderer.getDrawingBufferSize( _size );
 				const size = builder.renderer.getDrawingBufferSize( _size );
 				this.setViewOffset( size.width, size.height );
 				this.setViewOffset( size.width, size.height );
 
 
-			};
+			} );
 
 
-			renderPipeline.context.onAfterRenderPipeline = () => {
+			OnAfterRenderPipeline( () => {
 
 
 				this.clearViewOffset();
 				this.clearViewOffset();
 
 
-			};
+			} );
 
 
 		}
 		}
 
 
@@ -709,6 +709,7 @@ class TRAANode extends TempNode {
 
 
 		// materials
 		// materials
 
 
+		this._resolveMaterial.contextNode = context( builder.getSharedContext() );
 		this._resolveMaterial.colorNode = resolve();
 		this._resolveMaterial.colorNode = resolve();
 
 
 		return this._textureNode;
 		return this._textureNode;

+ 17 - 13
examples/jsm/tsl/display/TemporalReprojectNode.js

@@ -1,4 +1,4 @@
-import { EPSILON, Fn, If, abs, convertToTexture, dFdx, dFdy, dot, exp, float, floor, fwidth, getViewPosition, ivec2, luminance, max, min, mix, nodeObject, normalize, passTexture, screenCoordinate, select, smoothstep, sqrt, struct, texture, textureLoad, uniform, unpackRGBToNormal, uv, vec2, vec3, vec4, velocity } from 'three/tsl';
+import { EPSILON, Fn, If, abs, convertToTexture, dFdx, dFdy, dot, exp, float, floor, fwidth, getViewPosition, ivec2, luminance, max, min, mix, nodeObject, normalize, passTexture, screenCoordinate, select, smoothstep, sqrt, struct, texture, textureLoad, uniform, unpackRGBToNormal, uv, vec2, vec3, vec4, velocity, context, OnBeforeRenderPipeline, OnAfterRenderPipeline } from 'three/tsl';
 import { DepthTexture, HalfFloatType, Matrix4, NodeMaterial, NodeUpdateType, QuadMesh, RenderTarget, RendererUtils, TempNode, Vector2, Vector3 } from 'three/webgpu';
 import { DepthTexture, HalfFloatType, Matrix4, NodeMaterial, NodeUpdateType, QuadMesh, RenderTarget, RendererUtils, TempNode, Vector2, Vector3 } from 'three/webgpu';
 import { ENV_RAY_LENGTH, ENV_RAY_LENGTH_THRESHOLD } from '../utils/SpecularHelpers.js';
 import { ENV_RAY_LENGTH, ENV_RAY_LENGTH_THRESHOLD } from '../utils/SpecularHelpers.js';
 
 
@@ -727,36 +727,39 @@ class TemporalReprojectNode extends TempNode {
 
 
 	setup( builder ) {
 	setup( builder ) {
 
 
-		const renderPipeline = builder.context.renderPipeline;
+		const sharedContext = context( builder.getSharedContext() );
 
 
-		if ( renderPipeline ) {
+		if ( builder.renderPipeline && ! builder.context.renderPipelineState.viewOffsetOwner ) {
+
+			builder.context.renderPipelineState.viewOffsetOwner = this;
 
 
 			this._needsPostProcessingSync = true;
 			this._needsPostProcessingSync = true;
 
 
-			renderPipeline.context.onBeforeRenderPipeline = () => {
+			OnBeforeRenderPipeline( () => {
 
 
 				this.setViewOffset();
 				this.setViewOffset();
 
 
-			};
+			} );
 
 
-			renderPipeline.context.onAfterRenderPipeline = () => {
+			OnAfterRenderPipeline( () => {
 
 
 				this.clearViewOffset();
 				this.clearViewOffset();
 
 
-			};
+			} );
 
 
 		}
 		}
 
 
-		this._resolveMaterial.fragmentNode = this._buildResolve( builder );
+		this._resolveMaterial.contextNode = sharedContext;
+		this._resolveMaterial.fragmentNode = this._buildResolve();
 		this._resolveMaterial.needsUpdate = true;
 		this._resolveMaterial.needsUpdate = true;
 
 
-		this._buildSeed( builder );
+		this._buildSeed( sharedContext );
 
 
 		return this._textureNode;
 		return this._textureNode;
 
 
 	}
 	}
 
 
-	_buildSeed( builder ) {
+	_buildSeed( sharedContext ) {
 
 
 		const seed = Fn( () => {
 		const seed = Fn( () => {
 
 
@@ -768,12 +771,13 @@ class TemporalReprojectNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		this._seedMaterial.fragmentNode = seed().context( builder.getSharedContext() );
+		this._seedMaterial.contextNode = sharedContext;
+		this._seedMaterial.fragmentNode = seed();
 		this._seedMaterial.needsUpdate = true;
 		this._seedMaterial.needsUpdate = true;
 
 
 	}
 	}
 
 
-	_buildResolve( builder ) {
+	_buildResolve() {
 
 
 		const isSpecular = this.mode === 'specular';
 		const isSpecular = this.mode === 'specular';
 		const cameraUniforms = this._cameraUniforms;
 		const cameraUniforms = this._cameraUniforms;
@@ -944,7 +948,7 @@ class TemporalReprojectNode extends TempNode {
 
 
 		} );
 		} );
 
 
-		return resolve().context( builder.getSharedContext() );
+		return resolve();
 
 
 	}
 	}
 
 

+ 2 - 2
examples/webgpu_postprocessing_ssr_denoise.html

@@ -455,7 +455,7 @@
 				denoiseNode.flickerSuppression.value = params.denoise.flickerSuppression;
 				denoiseNode.flickerSuppression.value = params.denoise.flickerSuppression;
 				denoiseNode.adaptiveTrust.value = params.denoise.adaptiveTrust;
 				denoiseNode.adaptiveTrust.value = params.denoise.adaptiveTrust;
 
 
-	}
+			}
 
 
 		}
 		}
 
 
@@ -519,7 +519,7 @@
 
 
 				}
 				}
 
 
-	}
+			}
 
 
 			if ( ! isCompareMode( params.output ) ) controls.enabled = true;
 			if ( ! isCompareMode( params.output ) ) controls.enabled = true;
 
 

+ 2 - 0
src/Three.TSL.js

@@ -407,6 +407,8 @@ export const objectViewPosition = TSL.objectViewPosition;
 export const objectWorldMatrix = TSL.objectWorldMatrix;
 export const objectWorldMatrix = TSL.objectWorldMatrix;
 export const OnBeforeObjectUpdate = TSL.OnBeforeObjectUpdate;
 export const OnBeforeObjectUpdate = TSL.OnBeforeObjectUpdate;
 export const OnBeforeMaterialUpdate = TSL.OnBeforeMaterialUpdate;
 export const OnBeforeMaterialUpdate = TSL.OnBeforeMaterialUpdate;
+export const OnBeforeRenderPipeline = TSL.OnBeforeRenderPipeline;
+export const OnAfterRenderPipeline = TSL.OnAfterRenderPipeline;
 export const OnObjectUpdate = TSL.OnObjectUpdate;
 export const OnObjectUpdate = TSL.OnObjectUpdate;
 export const OnMaterialUpdate = TSL.OnMaterialUpdate;
 export const OnMaterialUpdate = TSL.OnMaterialUpdate;
 export const oneMinus = TSL.oneMinus;
 export const oneMinus = TSL.oneMinus;

+ 11 - 0
src/nodes/core/NodeBuilder.js

@@ -891,6 +891,17 @@ class NodeBuilder {
 
 
 	}
 	}
 
 
+	/**
+	 * A reference to the render pipeline.
+	 *
+	 * @type {RenderPipeline}
+	 */
+	get renderPipeline() {
+
+		return this.context.renderPipeline;
+
+	}
+
 	/**
 	/**
 	 * Whether the given texture is filtered or not.
 	 * Whether the given texture is filtered or not.
 	 *
 	 *

+ 7 - 2
src/nodes/lighting/ShadowNode.js

@@ -22,6 +22,7 @@ import { getShadowMaterial, disposeShadowMaterial, BasicShadowFilter, PCFShadowF
 import { positionLocal } from '../accessors/Position.js';
 import { positionLocal } from '../accessors/Position.js';
 import { uniform } from '../core/UniformNode.js';
 import { uniform } from '../core/UniformNode.js';
 import { equirectDirection } from '../utils/EquirectUV.js';
 import { equirectDirection } from '../utils/EquirectUV.js';
+import { context } from '../core/ContextNode.js';
 
 
 //
 //
 
 
@@ -492,12 +493,16 @@ class ShadowNode extends ShadowBaseNode {
 			const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
 			const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
 			const size = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
 			const size = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
 
 
+			const sharedContext = context( builder.getSharedContext() );
+
 			let material = this.vsmMaterialVertical || ( this.vsmMaterialVertical = new NodeMaterial() );
 			let material = this.vsmMaterialVertical || ( this.vsmMaterialVertical = new NodeMaterial() );
-			material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical, depthLayer: this.depthLayer } ).context( builder.getSharedContext() );
+			material.contextNode = sharedContext;
+			material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical, depthLayer: this.depthLayer } );
 			material.name = 'VSMVertical';
 			material.name = 'VSMVertical';
 
 
 			material = this.vsmMaterialHorizontal || ( this.vsmMaterialHorizontal = new NodeMaterial() );
 			material = this.vsmMaterialHorizontal || ( this.vsmMaterialHorizontal = new NodeMaterial() );
-			material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal, depthLayer: this.depthLayer } ).context( builder.getSharedContext() );
+			material.contextNode = sharedContext;
+			material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal, depthLayer: this.depthLayer } );
 			material.name = 'VSMHorizontal';
 			material.name = 'VSMHorizontal';
 
 
 		}
 		}

+ 54 - 0
src/nodes/utils/EventNode.js

@@ -55,6 +55,36 @@ class EventNode extends Node {
 
 
 	}
 	}
 
 
+	setup( builder ) {
+
+		const { eventType, callback } = this;
+
+		if ( eventType === EventNode.BEFORE_RENDER_PIPELINE ) {
+
+			const callbacks = builder.context.onBeforePipelineCallbacks;
+
+			if ( callbacks ) {
+
+				callbacks.push( callback );
+
+			}
+
+		} else if ( eventType === EventNode.AFTER_RENDER_PIPELINE ) {
+
+			const callbacks = builder.context.onAfterPipelineCallbacks;
+
+			if ( callbacks ) {
+
+				callbacks.push( callback );
+
+			}
+
+		}
+
+		return super.setup( builder );
+
+	}
+
 	update( frame ) {
 	update( frame ) {
 
 
 		this.callback( frame );
 		this.callback( frame );
@@ -75,6 +105,8 @@ EventNode.FRAME = 'frame';
 EventNode.BEFORE_OBJECT = 'beforeObject';
 EventNode.BEFORE_OBJECT = 'beforeObject';
 EventNode.BEFORE_MATERIAL = 'beforeMaterial';
 EventNode.BEFORE_MATERIAL = 'beforeMaterial';
 EventNode.BEFORE_FRAME = 'beforeFrame';
 EventNode.BEFORE_FRAME = 'beforeFrame';
+EventNode.BEFORE_RENDER_PIPELINE = 'beforeRenderPipeline';
+EventNode.AFTER_RENDER_PIPELINE = 'afterRenderPipeline';
 
 
 export default EventNode;
 export default EventNode;
 
 
@@ -146,3 +178,25 @@ export const OnBeforeMaterialUpdate = ( callback ) => createEvent( EventNode.BEF
  * @returns {EventNode}
  * @returns {EventNode}
  */
  */
 export const OnBeforeFrameUpdate = ( callback ) => createEvent( EventNode.BEFORE_FRAME, callback );
 export const OnBeforeFrameUpdate = ( callback ) => createEvent( EventNode.BEFORE_FRAME, callback );
+
+/**
+ * Creates an event that triggers a function before the render pipeline is rendered.
+ *
+ * The node must be part of a node chain that is used as the output of a `RenderPipeline`,
+ * otherwise the event is ignored.
+ *
+ * @param {Function} callback - The callback function.
+ * @returns {EventNode}
+ */
+export const OnBeforeRenderPipeline = ( callback ) => createEvent( EventNode.BEFORE_RENDER_PIPELINE, callback );
+
+/**
+ * Creates an event that triggers a function after the render pipeline is rendered.
+ *
+ * The node must be part of a node chain that is used as the output of a `RenderPipeline`,
+ * otherwise the event is ignored.
+ *
+ * @param {Function} callback - The callback function.
+ * @returns {EventNode}
+ */
+export const OnAfterRenderPipeline = ( callback ) => createEvent( EventNode.AFTER_RENDER_PIPELINE, callback );

+ 3 - 12
src/nodes/utils/RTTNode.js

@@ -2,6 +2,7 @@ import { nodeObject } from '../tsl/TSLCore.js';
 import TextureNode from '../accessors/TextureNode.js';
 import TextureNode from '../accessors/TextureNode.js';
 import { NodeUpdateType } from '../core/constants.js';
 import { NodeUpdateType } from '../core/constants.js';
 import { uv } from '../accessors/UV.js';
 import { uv } from '../accessors/UV.js';
+import { context } from '../core/ContextNode.js';
 import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
 import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
 import QuadMesh from '../../renderers/common/QuadMesh.js';
 import QuadMesh from '../../renderers/common/QuadMesh.js';
 
 
@@ -106,15 +107,6 @@ class RTTNode extends TextureNode {
 		 */
 		 */
 		this._resolutionScale = 1;
 		this._resolutionScale = 1;
 
 
-		/**
-		 * The node which is used with the quad mesh for RTT.
-		 *
-		 * @private
-		 * @type {Node}
-		 * @default null
-		 */
-		this._rttNode = null;
-
 		/**
 		/**
 		 * The internal quad mesh for RTT.
 		 * The internal quad mesh for RTT.
 		 *
 		 *
@@ -149,7 +141,8 @@ class RTTNode extends TextureNode {
 
 
 	setup( builder ) {
 	setup( builder ) {
 
 
-		this._rttNode = this.node.context( builder.getSharedContext() );
+		this._quadMesh.material.contextNode = context( builder.getSharedContext() );
+		this._quadMesh.material.fragmentNode = this.node;
 		this._quadMesh.material.name = 'RTT';
 		this._quadMesh.material.name = 'RTT';
 		this._quadMesh.material.needsUpdate = true;
 		this._quadMesh.material.needsUpdate = true;
 
 
@@ -243,8 +236,6 @@ class RTTNode extends TextureNode {
 
 
 		}
 		}
 
 
-
-		this._quadMesh.material.fragmentNode = this._rttNode;
 		this._quadMesh.name = name;
 		this._quadMesh.name = name;
 
 
 		//
 		//

+ 24 - 27
src/renderers/common/RenderPipeline.js

@@ -1,6 +1,6 @@
 import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
 import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
 import { ColorManagement } from '../../math/ColorManagement.js';
 import { ColorManagement } from '../../math/ColorManagement.js';
-import { vec4, renderOutput } from '../../nodes/TSL.js';
+import { vec4, renderOutput, context } from '../../nodes/TSL.js';
 import { NoToneMapping } from '../../constants.js';
 import { NoToneMapping } from '../../constants.js';
 import QuadMesh from '../../renderers/common/QuadMesh.js';
 import QuadMesh from '../../renderers/common/QuadMesh.js';
 import { warnOnce } from '../../utils.js';
 import { warnOnce } from '../../utils.js';
@@ -29,6 +29,15 @@ class RenderPipeline {
 	 */
 	 */
 	constructor( renderer, outputNode = vec4( 0, 0, 1, 1 ) ) {
 	constructor( renderer, outputNode = vec4( 0, 0, 1, 1 ) ) {
 
 
+		/**
+		 * This flag can be used for type testing.
+		 *
+		 * @type {boolean}
+		 * @readonly
+		 * @default true
+		 */
+		this.isRenderPipeline = true;
+
 		/**
 		/**
 		 * A reference to the renderer.
 		 * A reference to the renderer.
 		 *
 		 *
@@ -86,13 +95,13 @@ class RenderPipeline {
 		this._quadMesh.name = 'Render Pipeline';
 		this._quadMesh.name = 'Render Pipeline';
 
 
 		/**
 		/**
-		 * The context of the render pipeline stack.
+		 * The context data for the render pipeline.
 		 *
 		 *
 		 * @private
 		 * @private
 		 * @type {?Object}
 		 * @type {?Object}
 		 * @default null
 		 * @default null
 		 */
 		 */
-		this._context = null;
+		this._contextData = null;
 
 
 		/**
 		/**
 		 * The current tone mapping.
 		 * The current tone mapping.
@@ -124,7 +133,7 @@ class RenderPipeline {
 
 
 		this._update();
 		this._update();
 
 
-		if ( this._context.onBeforeRenderPipeline !== null ) this._context.onBeforeRenderPipeline();
+		for ( const callback of this._contextData.onBeforePipelineCallbacks ) callback();
 
 
 		const toneMapping = renderer.toneMapping;
 		const toneMapping = renderer.toneMapping;
 		const outputColorSpace = renderer.outputColorSpace;
 		const outputColorSpace = renderer.outputColorSpace;
@@ -146,19 +155,7 @@ class RenderPipeline {
 		renderer.toneMapping = toneMapping;
 		renderer.toneMapping = toneMapping;
 		renderer.outputColorSpace = outputColorSpace;
 		renderer.outputColorSpace = outputColorSpace;
 
 
-		if ( this._context.onAfterRenderPipeline !== null ) this._context.onAfterRenderPipeline();
-
-	}
-
-	/**
-	 * Returns the current context of the render pipeline stack.
-	 *
-	 * @readonly
-	 * @type {?Object}
-	 */
-	get context() {
-
-		return this._context;
+		for ( const callback of this._contextData.onAfterPipelineCallbacks ) callback();
 
 
 	}
 	}
 
 
@@ -197,31 +194,31 @@ class RenderPipeline {
 			const toneMapping = this._toneMapping;
 			const toneMapping = this._toneMapping;
 			const outputColorSpace = this._outputColorSpace;
 			const outputColorSpace = this._outputColorSpace;
 
 
-			const context = {
+			const contextData = {
 				renderPipeline: this,
 				renderPipeline: this,
-				onBeforeRenderPipeline: null,
-				onAfterRenderPipeline: null
+				renderPipelineState: {
+					viewOffsetOwner: null
+				},
+				onBeforePipelineCallbacks: [],
+				onAfterPipelineCallbacks: []
 			};
 			};
 
 
 			let outputNode = this.outputNode;
 			let outputNode = this.outputNode;
 
 
 			if ( this.outputColorTransform === true ) {
 			if ( this.outputColorTransform === true ) {
 
 
-				outputNode = outputNode.context( context );
-
 				outputNode = renderOutput( outputNode, toneMapping, outputColorSpace );
 				outputNode = renderOutput( outputNode, toneMapping, outputColorSpace );
 
 
 			} else {
 			} else {
 
 
-				context.toneMapping = toneMapping;
-				context.outputColorSpace = outputColorSpace;
-
-				outputNode = outputNode.context( context );
+				contextData.toneMapping = toneMapping;
+				contextData.outputColorSpace = outputColorSpace;
 
 
 			}
 			}
 
 
-			this._context = context;
+			this._contextData = contextData;
 
 
+			this._quadMesh.material.contextNode = context( contextData );
 			this._quadMesh.material.fragmentNode = outputNode;
 			this._quadMesh.material.fragmentNode = outputNode;
 			this._quadMesh.material.needsUpdate = true;
 			this._quadMesh.material.needsUpdate = true;
 
 

粤ICP备19079148号