diff --git a/examples/files.json b/examples/files.json index 5e996c8b88a87e..a27ec057066894 100644 --- a/examples/files.json +++ b/examples/files.json @@ -349,6 +349,7 @@ "webgpu_morphtargets_face", "webgpu_occlusion", "webgpu_particles", + "webgpu_portal", "webgpu_rtt", "webgpu_sandbox", "webgpu_shadertoy", diff --git a/examples/jsm/nodes/Nodes.js b/examples/jsm/nodes/Nodes.js index 68f2bc24333cbf..586633301f54af 100644 --- a/examples/jsm/nodes/Nodes.js +++ b/examples/jsm/nodes/Nodes.js @@ -110,6 +110,8 @@ export { default as ViewportTextureNode, viewportTexture, viewportMipTexture } f export { default as ViewportSharedTextureNode, viewportSharedTexture } from './display/ViewportSharedTextureNode.js'; export { default as ViewportDepthTextureNode, viewportDepthTexture } from './display/ViewportDepthTextureNode.js'; export { default as ViewportDepthNode, viewZToOrthographicDepth, orthographicDepthToViewZ, viewZToPerspectiveDepth, perspectiveDepthToViewZ, depth, depthTexture, depthPixel } from './display/ViewportDepthNode.js'; +export { default as GaussianBlurNode, gaussianBlur } from './display/GaussianBlurNode.js'; +export { default as PassNode, pass, depthPass } from './display/PassNode.js'; // code export { default as ExpressionNode, expression } from './code/ExpressionNode.js'; diff --git a/examples/jsm/nodes/accessors/CubeTextureNode.js b/examples/jsm/nodes/accessors/CubeTextureNode.js index c04a82e1e45a34..542080a5a28f95 100644 --- a/examples/jsm/nodes/accessors/CubeTextureNode.js +++ b/examples/jsm/nodes/accessors/CubeTextureNode.js @@ -27,9 +27,14 @@ class CubeTextureNode extends TextureNode { setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for CubeTextureNode - generateUV( builder, uvNode ) { + setupUV( builder, uvNode ) { + + return vec3( uvNode.x.negate(), uvNode.yz ); + + } + + generateUV( builder, cubeUV ) { - const cubeUV = vec3( uvNode.x.negate(), uvNode.yz ); return cubeUV.build( builder, 'vec3' ); } diff --git a/examples/jsm/nodes/accessors/TextureNode.js b/examples/jsm/nodes/accessors/TextureNode.js index c8d2c2e2b71dbf..c5369a25cd875d 100644 --- a/examples/jsm/nodes/accessors/TextureNode.js +++ b/examples/jsm/nodes/accessors/TextureNode.js @@ -78,6 +78,20 @@ class TextureNode extends UniformNode { } + setupUV( builder, uvNode ) { + + const texture = this.value; + + if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true || texture.isDepthTexture === true ) ) { + + uvNode = uvNode.setY( uvNode.y.oneMinus() ); + + } + + return uvNode; + + } + setup( builder ) { const properties = builder.getNodeProperties( this ); @@ -100,6 +114,8 @@ class TextureNode extends UniformNode { } + uvNode = this.setupUV( builder, uvNode ); + // let levelNode = this.levelNode; @@ -125,6 +141,12 @@ class TextureNode extends UniformNode { } + generateUV( builder, uvNode ) { + + return uvNode.build( builder, this.sampler === true ? 'vec2' : 'ivec2' ); + + } + generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, depthSnippet, compareSnippet ) { const texture = this.value; @@ -153,21 +175,6 @@ class TextureNode extends UniformNode { } - generateUV( builder, uvNode ) { - - const texture = this.value; - - if ( ( builder.isFlipY() && ( texture.isFramebufferTexture === true || texture.isDepthTexture === true ) ) || - ( builder.isFlipY() === false && texture.isRenderTargetTexture === true ) ) { - - uvNode = uvNode.setY( uvNode.y.fract().oneMinus() ); - - } - - return uvNode.build( builder, this.sampler === true ? 'vec2' : 'ivec2' ); - - } - generate( builder, output ) { const properties = builder.getNodeProperties( this ); diff --git a/examples/jsm/nodes/core/AttributeNode.js b/examples/jsm/nodes/core/AttributeNode.js index 939145889f2a23..37ece19c1f2f98 100644 --- a/examples/jsm/nodes/core/AttributeNode.js +++ b/examples/jsm/nodes/core/AttributeNode.js @@ -12,6 +12,12 @@ class AttributeNode extends Node { } + isGlobal() { + + return true; + + } + getHash( builder ) { return this.getAttributeName( builder ); diff --git a/examples/jsm/nodes/core/CacheNode.js b/examples/jsm/nodes/core/CacheNode.js index 22230d4a283dae..71b6c22eff7a9e 100644 --- a/examples/jsm/nodes/core/CacheNode.js +++ b/examples/jsm/nodes/core/CacheNode.js @@ -24,8 +24,9 @@ class CacheNode extends Node { build( builder, ...params ) { const previousCache = builder.getCache(); + const cache = this.cache || builder.globalCache; - builder.setCache( this.cache ); + builder.setCache( cache ); const data = this.node.build( builder, ...params ); @@ -40,7 +41,9 @@ class CacheNode extends Node { export default CacheNode; export const cache = nodeProxy( CacheNode ); +export const globalCache = ( node ) => cache( node, null ); addNodeElement( 'cache', cache ); +addNodeElement( 'globalCache', globalCache ); addNodeClass( 'CacheNode', CacheNode ); diff --git a/examples/jsm/nodes/core/NodeBuilder.js b/examples/jsm/nodes/core/NodeBuilder.js index 4b06f8db4518de..e1148e30e1f17a 100644 --- a/examples/jsm/nodes/core/NodeBuilder.js +++ b/examples/jsm/nodes/core/NodeBuilder.js @@ -626,9 +626,9 @@ class NodeBuilder { } - getDataFromNode( node, shaderStage = this.shaderStage ) { + getDataFromNode( node, shaderStage = this.shaderStage, cache = null ) { - const cache = node.isGlobal( this ) ? this.globalCache : this.cache; + cache = cache === null ? ( node.isGlobal( this ) ? this.globalCache : this.cache ) : cache; let nodeData = cache.getNodeData( node ); @@ -697,7 +697,7 @@ class NodeBuilder { getUniformFromNode( node, type, shaderStage = this.shaderStage, name = null ) { - const nodeData = this.getDataFromNode( node, shaderStage ); + const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); let nodeUniform = nodeData.uniform; diff --git a/examples/jsm/nodes/display/ColorAdjustmentNode.js b/examples/jsm/nodes/display/ColorAdjustmentNode.js index b321573eeddd8b..ed330d8dc38ad8 100644 --- a/examples/jsm/nodes/display/ColorAdjustmentNode.js +++ b/examples/jsm/nodes/display/ColorAdjustmentNode.js @@ -6,7 +6,7 @@ import { addNodeElement, tslFn, nodeProxy, float, vec3 } from '../shadernode/Sha const saturationNode = tslFn( ( { color, adjustment } ) => { - return adjustment.mix( luminance( color ), color ); + return adjustment.mix( luminance( color.rgb ), color.rgb ); } ); @@ -17,7 +17,7 @@ const vibranceNode = tslFn( ( { color, adjustment } ) => { const mx = color.r.max( color.g.max( color.b ) ); const amt = mx.sub( average ).mul( adjustment ).mul( - 3.0 ); - return mix( color, mx, amt ); + return mix( color.rgb, mx, amt ); } ); diff --git a/examples/jsm/nodes/display/GaussianBlurNode.js b/examples/jsm/nodes/display/GaussianBlurNode.js new file mode 100644 index 00000000000000..627f46196c6bd2 --- /dev/null +++ b/examples/jsm/nodes/display/GaussianBlurNode.js @@ -0,0 +1,165 @@ +import TempNode from '../core/TempNode.js'; +import { nodeObject, addNodeElement, tslFn, float, vec2, vec3, vec4 } from '../shadernode/ShaderNode.js'; +import { NodeUpdateType } from '../core/constants.js'; +import { mul } from '../math/OperatorNode.js'; +import { uv } from '../accessors/UVNode.js'; +import { texture } from '../accessors/TextureNode.js'; +import { uniform } from '../core/UniformNode.js'; +import { Vector2, RenderTarget } from 'three'; +import QuadMesh from '../../objects/QuadMesh.js'; + +const quadMesh = new QuadMesh(); + +class GaussianBlurNode extends TempNode { + + constructor( textureNode, sigma = 2 ) { + + super( textureNode ); + + this.textureNode = textureNode; + this.sigma = sigma; + + this.directionNode = vec2( 1 ); + + this._invSize = uniform( new Vector2() ); + this._passDirection = uniform( new Vector2() ); + + this._horizontalRT = new RenderTarget(); + this._verticalRT = new RenderTarget(); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + setSize( width, height ) { + + this._invSize.value.set( 1 / width, 1 / height ); + this._horizontalRT.setSize( width, height ); + this._verticalRT.setSize( width, height ); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + + const textureNode = this.textureNode; + const map = textureNode.value; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentTexture = textureNode.value; + + quadMesh.material = this._material; + + this.setSize( map.image.width, map.image.height ); + + // horizontal + + renderer.setRenderTarget( this._horizontalRT ); + + this._passDirection.value.set( 1, 0 ); + + quadMesh.render( renderer ); + + // vertical + + textureNode.value = this._horizontalRT.texture; + renderer.setRenderTarget( this._verticalRT ); + + this._passDirection.value.set( 0, 1 ); + + quadMesh.render( renderer ); + + // restore + + renderer.setRenderTarget( currentRenderTarget ); + textureNode.value = currentTexture; + + } + + setup( builder ) { + + const textureNode = this.textureNode; + + if ( textureNode.isTextureNode !== true ) { + + console.error( 'GaussianBlurNode requires a TextureNode.' ); + + return vec4(); + + } + + // + + const uvNode = textureNode.uvNode || uv(); + + const sampleTexture = ( uv ) => textureNode.cache().context( { getUV: () => uv, forceUVContext: true } ); + + const blur = tslFn( () => { + + const kernelSize = 3 + ( 2 * this.sigma ); + const gaussianCoefficients = this._getCoefficients( kernelSize ); + + const invSize = this._invSize; + const direction = vec2( this.directionNode ).mul( this._passDirection ); + + const weightSum = float( gaussianCoefficients[ 0 ] ).toVar(); + const diffuseSum = vec3( sampleTexture( uvNode ).mul( weightSum ) ).toVar(); + + for ( let i = 1; i < kernelSize; i ++ ) { + + const x = float( i ); + const w = float( gaussianCoefficients[ i ] ); + + const uvOffset = vec2( direction.mul( invSize.mul( x ) ) ).toVar(); + + const sample1 = vec3( sampleTexture( uvNode.add( uvOffset ) ) ); + const sample2 = vec3( sampleTexture( uvNode.sub( uvOffset ) ) ); + + diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) ); + weightSum.addAssign( mul( 2.0, w ) ); + + } + + return vec4( diffuseSum.div( weightSum ), 1.0 ); + + } ); + + // + + const material = this._material || ( this._material = builder.createNodeMaterial( 'MeshBasicNodeMaterial' ) ); + material.fragmentNode = blur(); + + // + + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; + + // + + return texture( this._verticalRT.texture ); + + } + + _getCoefficients( kernelRadius ) { + + const coefficients = []; + + for ( let i = 0; i < kernelRadius; i ++ ) { + + coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); + + } + + return coefficients; + + } + +} + +export const gaussianBlur = ( node, sigma ) => nodeObject( new GaussianBlurNode( nodeObject( node ), sigma ) ); + +addNodeElement( 'gaussianBlur', gaussianBlur ); + +export default GaussianBlurNode; + diff --git a/examples/jsm/nodes/display/PassNode.js b/examples/jsm/nodes/display/PassNode.js new file mode 100644 index 00000000000000..426461099ec940 --- /dev/null +++ b/examples/jsm/nodes/display/PassNode.js @@ -0,0 +1,182 @@ +import { addNodeClass } from '../core/Node.js'; +import TempNode from '../core/TempNode.js'; +import TextureNode from '../accessors/TextureNode.js'; +import { NodeUpdateType } from '../core/constants.js'; +import { nodeObject } from '../shadernode/ShaderNode.js'; +import { uniform } from '../core/UniformNode.js'; +import { viewZToOrthographicDepth, perspectiveDepthToViewZ } from './ViewportDepthNode.js'; +import { RenderTarget, Vector2, HalfFloatType, DepthTexture, FloatType, NoToneMapping } from 'three'; + +class PassTextureNode extends TextureNode { + + constructor( passNode, texture ) { + + super( texture ); + + this.passNode = passNode; + + this.setUpdateMatrix( false ); + + } + + setup( builder ) { + + this.passNode.build( builder ); + + return super.setup( builder ); + + } + + clone() { + + return new this.constructor( this.passNode, this.value ); + + } + +} + +class PassNode extends TempNode { + + constructor( scope, scene, camera ) { + + super( 'vec4' ); + + this.scope = scope; + this.scene = scene; + this.camera = camera; + + this._pixelRatio = 1; + this._width = 1; + this._height = 1; + + const depthTexture = new DepthTexture(); + depthTexture.isRenderTargetTexture = true; + depthTexture.type = FloatType; + depthTexture.name = 'PostProcessingDepth'; + + const renderTarget = new RenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType } ); + renderTarget.texture.name = 'PostProcessing'; + renderTarget.depthTexture = depthTexture; + + this.renderTarget = renderTarget; + + this.updateBeforeType = NodeUpdateType.FRAME; + + this._textureNode = nodeObject( new PassTextureNode( this, renderTarget.texture ) ); + this._depthTextureNode = nodeObject( new PassTextureNode( this, depthTexture ) ); + + this._depthNode = null; + this._cameraNear = uniform( 0 ); + this._cameraFar = uniform( 0 ); + + this.isPassNode = true; + + } + + isGlobal() { + + return true; + + } + + getTextureNode() { + + return this._textureNode; + + } + + getTextureDepthNode() { + + return this._depthTextureNode; + + } + + getDepthNode() { + + if ( this._depthNode === null ) { + + const cameraNear = this._cameraNear; + const cameraFar = this._cameraFar; + + this._depthNode = viewZToOrthographicDepth( perspectiveDepthToViewZ( this._depthTextureNode, cameraNear, cameraFar ), cameraNear, cameraFar ); + + } + + return this._depthNode; + + } + + setup() { + + return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getDepthNode(); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + const { scene, camera } = this; + + this._pixelRatio = renderer.getPixelRatio(); + + const size = renderer.getSize( new Vector2() ); + + this.setSize( size.width, size.height ); + + const currentToneMapping = renderer.toneMapping; + const currentToneMappingNode = renderer.toneMappingNode; + const currentRenderTarget = renderer.getRenderTarget(); + + this._cameraNear.value = camera.near; + this._cameraFar.value = camera.far; + + renderer.toneMapping = NoToneMapping; + renderer.toneMappingNode = null; + renderer.setRenderTarget( this.renderTarget ); + + renderer.render( scene, camera ); + + renderer.toneMapping = currentToneMapping; + renderer.toneMappingNode = currentToneMappingNode; + renderer.setRenderTarget( currentRenderTarget ); + + } + + setSize( width, height ) { + + this._width = width; + this._height = height; + + const effectiveWidth = this._width * this._pixelRatio; + const effectiveHeight = this._height * this._pixelRatio; + + this.renderTarget.setSize( effectiveWidth, effectiveHeight ); + + } + + setPixelRatio( pixelRatio ) { + + this._pixelRatio = pixelRatio; + + this.setSize( this._width, this._height ); + + } + + dispose() { + + this.renderTarget.dispose(); + + } + + +} + +PassNode.COLOR = 'color'; +PassNode.DEPTH = 'depth'; + +export default PassNode; + +export const pass = ( scene, camera ) => nodeObject( new PassNode( PassNode.COLOR, scene, camera ) ); +export const depthPass = ( scene, camera ) => nodeObject( new PassNode( PassNode.DEPTH, scene, camera ) ); + +addNodeClass( 'PassNode', PassNode ); diff --git a/examples/jsm/nodes/utils/RemapNode.js b/examples/jsm/nodes/utils/RemapNode.js index e730967267ee50..73858bfb4e7de0 100644 --- a/examples/jsm/nodes/utils/RemapNode.js +++ b/examples/jsm/nodes/utils/RemapNode.js @@ -1,9 +1,9 @@ import Node, { addNodeClass } from '../core/Node.js'; -import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; +import { float, addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; class RemapNode extends Node { - constructor( node, inLowNode, inHighNode, outLowNode, outHighNode ) { + constructor( node, inLowNode, inHighNode, outLowNode = float( 0 ), outHighNode = float( 1 ) ) { super(); diff --git a/examples/jsm/objects/QuadMesh.js b/examples/jsm/objects/QuadMesh.js new file mode 100644 index 00000000000000..f637777cf97d80 --- /dev/null +++ b/examples/jsm/objects/QuadMesh.js @@ -0,0 +1,60 @@ +import { BufferGeometry, Float32BufferAttribute, Mesh, OrthographicCamera } from 'three'; + +// Helper for passes that need to fill the viewport with a single quad. + +const _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); + +// https://github.com/mrdoob/three.js/pull/21358 + +class QuadGeometry extends BufferGeometry { + + constructor( flipY = false ) { + + super(); + + const uv = flipY === false ? [ 0, - 1, 0, 1, 2, 1 ] : [ 0, 2, 0, 0, 2, 0 ]; + + this.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uv, 2 ) ); + + } + +} + +const _geometry = new QuadGeometry(); + +class QuadMesh { + + constructor( material = null ) { + + this._mesh = new Mesh( _geometry, material ); + + } + + dispose() { + + this._mesh.geometry.dispose(); + + } + + render( renderer ) { + + renderer.render( this._mesh, _camera ); + + } + + get material() { + + return this._mesh.material; + + } + + set material( value ) { + + this._mesh.material = value; + + } + +} + +export default QuadMesh; diff --git a/examples/jsm/renderers/common/Background.js b/examples/jsm/renderers/common/Background.js index 5a5e6fa67db0e7..a1c717dcfe0aee 100644 --- a/examples/jsm/renderers/common/Background.js +++ b/examples/jsm/renderers/common/Background.js @@ -1,7 +1,7 @@ import DataMap from './DataMap.js'; import Color4 from './Color4.js'; import { Mesh, SphereGeometry, BackSide } from 'three'; -import { context, normalWorld, backgroundBlurriness, backgroundIntensity, NodeMaterial, modelViewProjection } from '../../nodes/Nodes.js'; +import { vec4, context, normalWorld, backgroundBlurriness, backgroundIntensity, NodeMaterial, modelViewProjection } from '../../nodes/Nodes.js'; const _clearColor = new Color4(); @@ -14,9 +14,6 @@ class Background extends DataMap { this.renderer = renderer; this.nodes = nodes; - this.backgroundMesh = null; - this.backgroundMeshNode = null; - } update( scene, renderList, renderContext ) { @@ -49,11 +46,11 @@ class Background extends DataMap { _clearColor.copy( renderer._clearColor ); - let backgroundMesh = this.backgroundMesh; + let backgroundMesh = sceneData.backgroundMesh; - if ( backgroundMesh === null ) { + if ( backgroundMesh === undefined ) { - this.backgroundMeshNode = context( backgroundNode, { + const backgroundMeshNode = context( vec4( backgroundNode ), { // @TODO: Add Texture2D support using node context getUV: () => normalWorld, getTextureLevel: () => backgroundBlurriness @@ -68,9 +65,10 @@ class Background extends DataMap { nodeMaterial.depthWrite = false; nodeMaterial.fog = false; nodeMaterial.vertexNode = viewProj; - nodeMaterial.fragmentNode = this.backgroundMeshNode; + nodeMaterial.fragmentNode = backgroundMeshNode; - this.backgroundMesh = backgroundMesh = new Mesh( new SphereGeometry( 1, 32, 32 ), nodeMaterial ); + sceneData.backgroundMeshNode = backgroundMeshNode; + sceneData.backgroundMesh = backgroundMesh = new Mesh( new SphereGeometry( 1, 32, 32 ), nodeMaterial ); backgroundMesh.frustumCulled = false; backgroundMesh.onBeforeRender = function ( renderer, scene, camera ) { @@ -85,7 +83,7 @@ class Background extends DataMap { if ( sceneData.backgroundCacheKey !== backgroundCacheKey ) { - this.backgroundMeshNode.node = backgroundNode; + sceneData.backgroundMeshNode.node = vec4( backgroundNode ); backgroundMesh.material.needsUpdate = true; diff --git a/examples/jsm/renderers/common/PostProcessing.js b/examples/jsm/renderers/common/PostProcessing.js new file mode 100644 index 00000000000000..bbed444915ef50 --- /dev/null +++ b/examples/jsm/renderers/common/PostProcessing.js @@ -0,0 +1,25 @@ +import { vec4, MeshBasicNodeMaterial } from '../../nodes/Nodes.js'; +import QuadMesh from '../../objects/QuadMesh.js'; + +const quadMesh = new QuadMesh( new MeshBasicNodeMaterial() ); + +class PostProcessing { + + constructor( renderer, outputNode = vec4( 0, 0, 1, 1 ) ) { + + this.renderer = renderer; + this.outputNode = outputNode; + + } + + render() { + + quadMesh.material.fragmentNode = this.outputNode; + + quadMesh.render( this.renderer ); + + } + +} + +export default PostProcessing; diff --git a/examples/jsm/renderers/webgl/WebGLBackend.js b/examples/jsm/renderers/webgl/WebGLBackend.js index d05656a33123a4..8f3d2746c2fc84 100644 --- a/examples/jsm/renderers/webgl/WebGLBackend.js +++ b/examples/jsm/renderers/webgl/WebGLBackend.js @@ -453,12 +453,6 @@ class WebGLBackend extends Backend { } - destroySampler( /*texture*/ ) { - - console.warn( 'Abstract class.' ); - - } - createDefaultTexture( texture ) { const { gl, textureUtils, defaultTextures } = this; @@ -601,12 +595,19 @@ class WebGLBackend extends Backend { } - destroyTexture( /*texture*/ ) { + destroyTexture( texture ) { - console.warn( 'Abstract class.' ); + const { gl } = this; + const { textureGPU } = this.get( texture ); + + gl.deleteTexture( textureGPU ); + + this.delete( texture ); } + destroySampler() {} + copyTextureToBuffer( texture, x, y, width, height ) { return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height ); diff --git a/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js b/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js index ea67b86b56484c..b1f2811bb5fbc8 100644 --- a/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +++ b/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js @@ -583,7 +583,7 @@ void main() { getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); - const nodeData = this.getDataFromNode( node, shaderStage ); + const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); let uniformGPU = nodeData.uniformGPU; diff --git a/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js b/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js index 9145055eb86c68..f435b6446efda8 100644 --- a/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -342,7 +342,7 @@ class WGSLNodeBuilder extends NodeBuilder { getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); - const nodeData = this.getDataFromNode( node, shaderStage ); + const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); if ( nodeData.uniformGPU === undefined ) { diff --git a/examples/screenshots/webgpu_depth_texture.jpg b/examples/screenshots/webgpu_depth_texture.jpg index 835ad94e4422e3..27ddbc861bfba4 100644 Binary files a/examples/screenshots/webgpu_depth_texture.jpg and b/examples/screenshots/webgpu_depth_texture.jpg differ diff --git a/examples/screenshots/webgpu_instance_uniform.jpg b/examples/screenshots/webgpu_instance_uniform.jpg index 59e20f84e22402..2964de7f799f99 100644 Binary files a/examples/screenshots/webgpu_instance_uniform.jpg and b/examples/screenshots/webgpu_instance_uniform.jpg differ diff --git a/examples/screenshots/webgpu_portal.jpg b/examples/screenshots/webgpu_portal.jpg new file mode 100644 index 00000000000000..1b09eeed0f1573 Binary files /dev/null and b/examples/screenshots/webgpu_portal.jpg differ diff --git a/examples/screenshots/webgpu_skinning_instancing.jpg b/examples/screenshots/webgpu_skinning_instancing.jpg index 0622c5d6eb6386..9452ca82eb8e76 100644 Binary files a/examples/screenshots/webgpu_skinning_instancing.jpg and b/examples/screenshots/webgpu_skinning_instancing.jpg differ diff --git a/examples/webgpu_compute_particles_rain.html b/examples/webgpu_compute_particles_rain.html index b0665d84378956..5ca5d3f5fb8138 100644 --- a/examples/webgpu_compute_particles_rain.html +++ b/examples/webgpu_compute_particles_rain.html @@ -46,7 +46,7 @@ let clock; let collisionBox, collisionCamera, collisionPosRT, collisionPosMaterial; - let collisionBoxPos; + let collisionBoxPos, collisionBoxPosUI; init(); @@ -138,7 +138,7 @@ const computeUpdate = tslFn( () => { - const getCoord = ( pos ) => pos.add( 50 ).div( 100 ).mul( vec2( 1, - 1 ) ); + const getCoord = ( pos ) => pos.add( 50 ).div( 100 ); const position = positionBuffer.element( instanceIndex ); const velocity = velocityBuffer.element( instanceIndex ); @@ -346,9 +346,10 @@ const gui = new GUI(); // use lerp to smooth the movement - collisionBoxPos = new THREE.Vector3().copy( collisionBox.position ); + collisionBoxPosUI = new THREE.Vector3().copy( collisionBox.position ); + collisionBoxPos = new THREE.Vector3(); - gui.add( collisionBoxPos, 'z', - 50, 50, .001 ).name( 'position' ); + gui.add( collisionBoxPosUI, 'z', - 50, 50, .001 ).name( 'position' ); gui.add( collisionBox.scale, 'x', .1, 3.5, 0.01 ).name( 'scale' ); gui.add( rainParticles, 'count', 200, maxParticleCount, 1 ).name( 'drop count' ).onChange( ( v ) => rippleParticles.count = v ); @@ -377,6 +378,8 @@ } + collisionBoxPos.set( collisionBoxPosUI.x, collisionBoxPosUI.y, - collisionBoxPosUI.z ); + collisionBox.position.lerp( collisionBoxPos, 10 * delta ); // position diff --git a/examples/webgpu_depth_texture.html b/examples/webgpu_depth_texture.html index ae9516fb03aa72..8e6bf71ce4a860 100644 --- a/examples/webgpu_depth_texture.html +++ b/examples/webgpu_depth_texture.html @@ -31,11 +31,13 @@ import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js'; + import QuadMesh from 'three/addons/objects/QuadMesh.js'; + import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; let camera, scene, controls, renderer; - let cameraFX, sceneFX, renderTarget; + let quad, renderTarget; const dpr = window.devicePixelRatio; @@ -100,18 +102,10 @@ // FX - cameraFX = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - sceneFX = new THREE.Scene(); - - const geometryFX = new THREE.PlaneGeometry( 2, 2 ); - - // - const materialFX = new MeshBasicNodeMaterial(); materialFX.colorNode = texture( depthTexture ); - const quad = new THREE.Mesh( geometryFX, materialFX ); - sceneFX.add( quad ); + quad = new QuadMesh( materialFX ); // @@ -136,7 +130,7 @@ renderer.render( scene, camera ); renderer.setRenderTarget( null ); - renderer.render( sceneFX, cameraFX ); + quad.render( renderer ); } diff --git a/examples/webgpu_instance_uniform.html b/examples/webgpu_instance_uniform.html index a5773859a254aa..c71e11eaeb8cf3 100644 --- a/examples/webgpu_instance_uniform.html +++ b/examples/webgpu_instance_uniform.html @@ -98,7 +98,6 @@ // Grid const helper = new THREE.GridHelper( 1000, 40, 0x303030, 0x303030 ); - helper.material.colorNode = attribute( 'color' ); helper.position.y = - 75; scene.add( helper ); diff --git a/examples/webgpu_multiple_rendertargets.html b/examples/webgpu_multiple_rendertargets.html index 559be7e82b18b6..31137d350c54d5 100644 --- a/examples/webgpu_multiple_rendertargets.html +++ b/examples/webgpu_multiple_rendertargets.html @@ -34,9 +34,10 @@ import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js'; + import QuadMesh from 'three/addons/objects/QuadMesh.js'; + let camera, scene, renderer, torus; - let renderTarget; - let postScene, postCamera; + let quadMesh, renderTarget; /* @@ -156,13 +157,7 @@ // PostProcessing setup - postScene = new THREE.Scene(); - postCamera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - postScene.add( new THREE.Mesh( - new THREE.PlaneGeometry( 2, 2 ), - new ReadGBufferMaterial( renderTarget.texture[ 0 ], renderTarget.texture[ 1 ] ) - ) ); + quadMesh = new QuadMesh( new ReadGBufferMaterial( renderTarget.texture[ 0 ], renderTarget.texture[ 1 ] ) ); // Controls @@ -212,7 +207,7 @@ // render post FX renderer.setRenderTarget( null ); - renderer.render( postScene, postCamera ); + quadMesh.render( renderer ); } diff --git a/examples/webgpu_portal.html b/examples/webgpu_portal.html new file mode 100644 index 00000000000000..87adb4129e06b8 --- /dev/null +++ b/examples/webgpu_portal.html @@ -0,0 +1,196 @@ + + +
+