From 3e030e0d9b5c4d7cbc7c80ae979903af3d60f2a2 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:46:24 -0300 Subject: [PATCH 01/12] WebGPURenderer: Depth buffer improvements --- examples/jsm/renderers/common/Renderer.js | 6 + .../jsm/renderers/webgpu/WebGPUBackend.js | 117 +++++++++++++----- .../webgpu/utils/WebGPUTextureUtils.js | 6 +- .../jsm/renderers/webgpu/utils/WebGPUUtils.js | 6 +- 4 files changed, 99 insertions(+), 36 deletions(-) diff --git a/examples/jsm/renderers/common/Renderer.js b/examples/jsm/renderers/common/Renderer.js index 77fb724074a53a..848b7f091b930b 100644 --- a/examples/jsm/renderers/common/Renderer.js +++ b/examples/jsm/renderers/common/Renderer.js @@ -42,6 +42,9 @@ class Renderer { this.sortObjects = true; + this.depth = true; + this.stencil = true; + // internals this._pixelRatio = 1; @@ -239,6 +242,9 @@ class Renderer { renderContext.scissorValue.copy( scissor ).multiplyScalar( pixelRatio ).floor(); renderContext.scissor = this._scissorTest && renderContext.scissorValue.equals( _screen ) === false; + renderContext.depth = this.depth; + renderContext.stencil = this.stencil; + // _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); diff --git a/examples/jsm/renderers/webgpu/WebGPUBackend.js b/examples/jsm/renderers/webgpu/WebGPUBackend.js index 203ed87903f58e..4b41c2372297c6 100644 --- a/examples/jsm/renderers/webgpu/WebGPUBackend.js +++ b/examples/jsm/renderers/webgpu/WebGPUBackend.js @@ -7,7 +7,7 @@ import { GPUFeatureName, GPUTextureFormat, GPULoadOp, GPUStoreOp, GPUIndexFormat import WebGPUNodeBuilder from './nodes/WGSLNodeBuilder.js'; import Backend from '../common/Backend.js'; -import { DepthFormat, WebGPUCoordinateSystem } from 'three'; +import { DepthTexture, DepthFormat, DepthStencilFormat, UnsignedInt248Type, UnsignedIntType, WebGPUCoordinateSystem } from 'three'; import WebGPUUtils from './utils/WebGPUUtils.js'; import WebGPUAttributeUtils from './utils/WebGPUAttributeUtils.js'; @@ -53,7 +53,8 @@ class WebGPUBackend extends Backend { this.device = null; this.context = null; this.colorBuffer = null; - this.depthBuffer = null; + + this.depthBuffers = new WeakMap(); this.utils = new WebGPUUtils( this ); this.attributeUtils = new WebGPUAttributeUtils( this ); @@ -184,7 +185,7 @@ class WebGPUBackend extends Backend { } - depthStencilAttachment.view = this.depthBuffer.createView(); + depthStencilAttachment.view = this._getDepthBufferGPU( renderContext ).createView(); } @@ -321,7 +322,7 @@ class WebGPUBackend extends Backend { } - descriptor.depthStencilAttachment.view = this.depthBuffer.createView(); + descriptor.depthStencilAttachment.view = this._getDepthBufferGPU( renderContext ).createView(); if ( color ) { @@ -670,7 +671,6 @@ class WebGPUBackend extends Backend { this._configureContext(); this._setupColorBuffer(); - this._setupDepthBuffer(); } @@ -696,30 +696,44 @@ class WebGPUBackend extends Backend { } - copyFramebufferToTexture( framebufferTexture, renderContext ) { + copyFramebufferToTexture( texture, renderContext ) { const renderContextData = this.get( renderContext ); const { encoder, descriptor } = renderContextData; - const sourceGPU = this.context.getCurrentTexture(); - const destinationGPU = this.get( framebufferTexture ).texture; + let sourceGPU = null; + + if ( texture.isFramebufferTexture ) { + + sourceGPU = this.context.getCurrentTexture(); + + } else if ( texture.isDepthTexture ) { + + sourceGPU = this._getDepthBufferGPU( renderContext ); + + } + + const destinationGPU = this.get( texture ).texture; renderContextData.currentPass.end(); encoder.copyTextureToTexture( { - texture: sourceGPU + texture: sourceGPU, + origin: { x: 0, y: 0, z: 0 } }, { - texture: destinationGPU + texture: destinationGPU }, [ - framebufferTexture.image.width, - framebufferTexture.image.height + texture.image.width, + texture.image.height ] ); + if ( texture.generateMipmaps ) this.textureUtils.generateMipmaps( texture ); + descriptor.colorAttachments[ 0 ].loadOp = GPULoadOp.Load; if ( renderContext.depth ) descriptor.depthStencilAttachment.depthLoadOp = GPULoadOp.Load; if ( renderContext.stencil ) descriptor.depthStencilAttachment.stencilLoadOp = GPULoadOp.Load; @@ -731,6 +745,65 @@ class WebGPUBackend extends Backend { // utils + _getDepthBufferGPU( renderContext ) { + + const { depthBuffers } = this; + const { width, height } = this.getDrawingBufferSize(); + + let depthTexture = depthBuffers.get( renderContext ); + + if ( depthTexture !== undefined && depthTexture.image.width === width && depthTexture.image.height === height ) { + + return this.get( depthTexture ).texture; + + } + + this._destroyDepthBufferGPU( renderContext ); + + depthTexture = new DepthTexture(); + depthTexture.name = 'depthBuffer'; + + if ( renderContext.stencil ) { + + depthTexture = new DepthTexture(); + depthTexture.format = DepthStencilFormat; + depthTexture.type = UnsignedInt248Type; + + } else if ( renderContext.depth ) { + + depthTexture = new DepthTexture(); + depthTexture.format = DepthFormat; + depthTexture.type = UnsignedIntType; + + } + + depthTexture.image.width = width; + depthTexture.image.height = height; + + this.textureUtils.createTexture( depthTexture, { sampleCount: this.parameters.sampleCount } ); + + depthBuffers.set( renderContext, depthTexture ); + + return this.get( depthTexture ).texture; + + } + + _destroyDepthBufferGPU( renderContext ) { + + const { depthBuffers } = this; + + const depthTexture = depthBuffers.get( renderContext ); + + if ( depthTexture !== undefined ) { + + this.textureUtils.destroyTexture( depthTexture ); + + depthBuffers.delete( renderContext ); + + } + + } + _configureContext() { this.context.configure( { @@ -763,26 +836,6 @@ class WebGPUBackend extends Backend { } - _setupDepthBuffer() { - - if ( this.depthBuffer ) this.depthBuffer.destroy(); - - const { width, height } = this.getDrawingBufferSize(); - - this.depthBuffer = this.device.createTexture( { - label: 'depthBuffer', - size: { - width: width, - height: height, - depthOrArrayLayers: 1 - }, - sampleCount: this.parameters.sampleCount, - format: GPUTextureFormat.Depth24PlusStencil8, - usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC - } ); - - } - } export default WebGPUBackend; diff --git a/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js b/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js index cf8c8033a7d9d1..b85aeffd353b16 100644 --- a/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -86,7 +86,7 @@ class WebGPUTextureUtils { } - createTexture( texture ) { + createTexture( texture, options = {} ) { const backend = this.backend; const textureData = backend.get( texture ); @@ -104,9 +104,9 @@ class WebGPUTextureUtils { const mipLevelCount = this._getMipLevelCount( texture, width, height, needsMipmaps ); const format = texture.internalFormat || this._getFormat( texture ); //const sampleCount = texture.isRenderTargetTexture || texture.isDepthTexture ? backend.utils.getSampleCount( renderContext ) : 1; - const sampleCount = 1; + const sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1; - let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST; + let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC; if ( texture.isCompressedTexture !== true ) { diff --git a/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js b/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js index f99ed6eb88ee28..39d8d85d5b2990 100644 --- a/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js +++ b/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js @@ -16,10 +16,14 @@ class WebGPUUtils { format = this.getTextureFormatGPU( renderContext.depthTexture ); - } else { + } else if ( renderContext.depth && renderContext.stencil ) { format = GPUTextureFormat.Depth24PlusStencil8; + } else if ( renderContext.depth ) { + + format = GPUTextureFormat.Depth24Plus; + } return format; From dcd8301e1fdf866f11588c314437b1f0bccff512 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:46:48 -0300 Subject: [PATCH 02/12] CameraNode: Added cameraNear, cameraFar --- examples/jsm/nodes/accessors/CameraNode.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/jsm/nodes/accessors/CameraNode.js b/examples/jsm/nodes/accessors/CameraNode.js index 7e41af5a01f62b..0dcf7c03d49680 100644 --- a/examples/jsm/nodes/accessors/CameraNode.js +++ b/examples/jsm/nodes/accessors/CameraNode.js @@ -18,6 +18,10 @@ class CameraNode extends Object3DNode { return 'mat4'; + } else if ( scope === CameraNode.NEAR || scope === CameraNode.FAR ) { + + return 'float'; + } return super.getNodeType( builder ); @@ -34,9 +38,13 @@ class CameraNode extends Object3DNode { uniformNode.value = camera.projectionMatrix; - } else if ( scope === CameraNode.VIEW_MATRIX ) { + } else if ( scope === CameraNode.NEAR ) { + + uniformNode.value = camera.near; - uniformNode.value = camera.matrixWorldInverse; + } else if ( scope === CameraNode.FAR ) { + + uniformNode.value = camera.far; } else { @@ -56,6 +64,10 @@ class CameraNode extends Object3DNode { this._uniformNode.nodeType = 'mat4'; + } else if ( scope === CameraNode.NEAR || scope === CameraNode.FAR ) { + + this._uniformNode.nodeType = 'float'; + } return super.generate( builder ); @@ -65,10 +77,14 @@ class CameraNode extends Object3DNode { } CameraNode.PROJECTION_MATRIX = 'projectionMatrix'; +CameraNode.NEAR = 'near'; +CameraNode.FAR = 'far'; export default CameraNode; export const cameraProjectionMatrix = nodeImmutable( CameraNode, CameraNode.PROJECTION_MATRIX ); +export const cameraNear = nodeImmutable( CameraNode, CameraNode.NEAR ); +export const cameraFar = nodeImmutable( CameraNode, CameraNode.FAR ); export const cameraViewMatrix = nodeImmutable( CameraNode, CameraNode.VIEW_MATRIX ); export const cameraNormalMatrix = nodeImmutable( CameraNode, CameraNode.NORMAL_MATRIX ); export const cameraWorldMatrix = nodeImmutable( CameraNode, CameraNode.WORLD_MATRIX ); From 1a6ea9f3792138f4f9e6685288f02c82b1abc096 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:47:13 -0300 Subject: [PATCH 03/12] Object3DNode: Added modelScale, objectScale() --- examples/jsm/nodes/accessors/ModelNode.js | 1 + examples/jsm/nodes/accessors/Object3DNode.js | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/jsm/nodes/accessors/ModelNode.js b/examples/jsm/nodes/accessors/ModelNode.js index d63adbd57b1242..831369a2fac17a 100644 --- a/examples/jsm/nodes/accessors/ModelNode.js +++ b/examples/jsm/nodes/accessors/ModelNode.js @@ -27,6 +27,7 @@ export const modelViewMatrix = nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX ) export const modelNormalMatrix = nodeImmutable( ModelNode, ModelNode.NORMAL_MATRIX ); export const modelWorldMatrix = nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX ); export const modelPosition = nodeImmutable( ModelNode, ModelNode.POSITION ); +export const modelScale = nodeImmutable( ModelNode, ModelNode.SCALE ); export const modelViewPosition = nodeImmutable( ModelNode, ModelNode.VIEW_POSITION ); addNodeClass( ModelNode ); diff --git a/examples/jsm/nodes/accessors/Object3DNode.js b/examples/jsm/nodes/accessors/Object3DNode.js index 516fc32a8d82bb..9cfa4505b08664 100644 --- a/examples/jsm/nodes/accessors/Object3DNode.js +++ b/examples/jsm/nodes/accessors/Object3DNode.js @@ -32,7 +32,7 @@ class Object3DNode extends Node { return 'mat3'; - } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION ) { + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { return 'vec3'; @@ -64,6 +64,12 @@ class Object3DNode extends Node { uniformNode.value.setFromMatrixPosition( object.matrixWorld ); + } else if ( scope === Object3DNode.SCALE ) { + + uniformNode.value = uniformNode.value || new Vector3(); + + uniformNode.value.setFromMatrixScale( object.matrixWorld ); + } else if ( scope === Object3DNode.DIRECTION ) { uniformNode.value = uniformNode.value || new Vector3(); @@ -95,7 +101,7 @@ class Object3DNode extends Node { this._uniformNode.nodeType = 'mat3'; - } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION ) { + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { this._uniformNode.nodeType = 'vec3'; @@ -127,6 +133,7 @@ Object3DNode.VIEW_MATRIX = 'viewMatrix'; Object3DNode.NORMAL_MATRIX = 'normalMatrix'; Object3DNode.WORLD_MATRIX = 'worldMatrix'; Object3DNode.POSITION = 'position'; +Object3DNode.SCALE = 'scale'; Object3DNode.VIEW_POSITION = 'viewPosition'; Object3DNode.DIRECTION = 'direction'; @@ -137,6 +144,7 @@ export const objectViewMatrix = nodeProxy( Object3DNode, Object3DNode.VIEW_MATRI export const objectNormalMatrix = nodeProxy( Object3DNode, Object3DNode.NORMAL_MATRIX ); export const objectWorldMatrix = nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX ); export const objectPosition = nodeProxy( Object3DNode, Object3DNode.POSITION ); +export const objectScale = nodeProxy( Object3DNode, Object3DNode.SCALE ); export const objectViewPosition = nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION ); addNodeClass( Object3DNode ); From c636ba5dc810a999fac041e023df860b03c02375 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:47:48 -0300 Subject: [PATCH 04/12] Added TextureBicubicNode, textureBicubic --- .../jsm/nodes/accessors/TextureBicubicNode.js | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 examples/jsm/nodes/accessors/TextureBicubicNode.js diff --git a/examples/jsm/nodes/accessors/TextureBicubicNode.js b/examples/jsm/nodes/accessors/TextureBicubicNode.js new file mode 100644 index 00000000000000..846450d8f12aca --- /dev/null +++ b/examples/jsm/nodes/accessors/TextureBicubicNode.js @@ -0,0 +1,94 @@ +import TempNode from '../core/TempNode.js'; +import { addNodeClass } from '../core/Node.js'; +import { add, mul, div } from '../math/OperatorNode.js'; +import { floor, ceil, fract, pow } from '../math/MathNode.js'; +import { nodeProxy, addNodeElement, float, vec2, vec4, int } from '../shadernode/ShaderNode.js'; + +// Mipped Bicubic Texture Filtering by N8 +// https://www.shadertoy.com/view/Dl2SDW + +const bC = 1.0 / 6.0; + +const w0 = ( a ) => mul( bC, mul( a, mul( a, a.negate().add( 3.0 ) ).sub( 3.0 ) ).add( 1.0 ) ); + +const w1 = ( a ) => mul( bC, mul( a, mul( a, mul( 3.0, a ).sub( 6.0 ) ) ).add( 4.0 ) ); + +const w2 = ( a ) => mul( bC, mul( a, mul( a, mul( - 3.0, a ).add( 3.0 ) ).add( 3.0 ) ).add( 1.0 ) ); + +const w3 = ( a ) => mul( bC, pow( a, 3 ) ); + +const g0 = ( a ) => w0( a ).add( w1( a ) ); + +const g1 = ( a ) => w2( a ).add( w3( a ) ); + +// h0 and h1 are the two offset functions +const h0 = ( a ) => add( - 1.0, w1( a ).div( w0( a ).add( w1( a ) ) ) ); + +const h1 = ( a ) => add( 1.0, w3( a ).div( w2( a ).add( w3( a ) ) ) ); + +const bicubic = ( textureNode, texelSize, lod ) => { + + const uv = textureNode.uvNode; + const uvScaled = mul( uv, texelSize.zw ).add( 0.5 ); + + const iuv = floor( uvScaled ); + const fuv = fract( uvScaled ); + + const g0x = g0( fuv.x ); + const g1x = g1( fuv.x ); + const h0x = h0( fuv.x ); + const h1x = h1( fuv.x ); + const h0y = h0( fuv.y ); + const h1y = h1( fuv.y ); + + const p0 = vec2( iuv.x.add( h0x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p1 = vec2( iuv.x.add( h1x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p2 = vec2( iuv.x.add( h0x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p3 = vec2( iuv.x.add( h1x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + + const a = g0( fuv.y ).mul( add( g0x.mul( textureNode.uv( p0 ).level( lod ) ), g1x.mul( textureNode.uv( p1 ).level( lod ) ) ) ); + const b = g1( fuv.y ).mul( add( g0x.mul( textureNode.uv( p2 ).level( lod ) ), g1x.mul( textureNode.uv( p3 ).level( lod ) ) ) ); + + return a.add( b ); + +}; + +const textureBicubicMethod = ( textureNode, lodNode ) => { + + const fLodSize = vec2( textureNode.size( int( lodNode ) ) ); + const cLodSize = vec2( textureNode.size( int( lodNode.add( 1.0 ) ) ) ); + const fLodSizeInv = div( 1.0, fLodSize ); + const cLodSizeInv = div( 1.0, cLodSize ); + const fSample = bicubic( textureNode, vec4( fLodSizeInv, fLodSize ), floor( lodNode ) ); + const cSample = bicubic( textureNode, vec4( cLodSizeInv, cLodSize ), ceil( lodNode ) ); + + return fract( lodNode ).mix( fSample, cSample ); + +}; + +class TextureBicubicNode extends TempNode { + + constructor( textureNode, blurNode = float( 3 ) ) { + + super( 'vec4' ); + + this.textureNode = textureNode; + this.blurNode = blurNode; + + } + + construct() { + + return textureBicubicMethod( this.textureNode, this.blurNode ); + + } + +} + +export default TextureBicubicNode; + +export const textureBicubic = nodeProxy( TextureBicubicNode ); + +addNodeElement( 'bicubic', textureBicubic ); + +addNodeClass( TextureBicubicNode ); From 0242355d1ff38533904e71ad05eee5a240abd9ad Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:49:48 -0300 Subject: [PATCH 05/12] TextureNode: Added .size(), level() and uv() --- examples/jsm/nodes/accessors/TextureNode.js | 37 +++++++++++++++++++ .../jsm/nodes/accessors/TextureSizeNode.js | 35 ++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 examples/jsm/nodes/accessors/TextureSizeNode.js diff --git a/examples/jsm/nodes/accessors/TextureNode.js b/examples/jsm/nodes/accessors/TextureNode.js index fce9e2f6fcfcdb..a2c33d40ec1c1c 100644 --- a/examples/jsm/nodes/accessors/TextureNode.js +++ b/examples/jsm/nodes/accessors/TextureNode.js @@ -1,5 +1,7 @@ import UniformNode from '../core/UniformNode.js'; import { uv } from './UVNode.js'; +import { textureSize } from './TextureSizeNode.js'; +import { context } from '../core/ContextNode.js'; import { addNodeClass } from '../core/Node.js'; import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; @@ -140,6 +142,32 @@ class TextureNode extends UniformNode { } + uv( uvNode ) { + + const textureNode = this.clone(); + textureNode.uvNode = uvNode; + + return textureNode; + + } + + level( levelNode ) { + + const textureNode = this.clone(); + textureNode.levelNode = levelNode; + + return context( textureNode, { + getMIPLevelAlgorithmNode: ( textureNode, levelNode ) => levelNode + } ); + + } + + size( levelNode ) { + + return textureSize( this, levelNode ); + + } + serialize( data ) { super.serialize( data ); @@ -156,13 +184,22 @@ class TextureNode extends UniformNode { } + clone() { + + return new this.constructor( this.value, this.uvNode, this.levelNode ); + + } + } export default TextureNode; export const texture = nodeProxy( TextureNode ); +//export const textureLevel = ( value, uv, level ) => texture( value, uv ).level( level ); + export const sampler = ( aTexture ) => ( aTexture.isNode === true ? aTexture : texture( aTexture ) ).convert( 'sampler' ); addNodeElement( 'texture', texture ); +//addNodeElement( 'textureLevel', textureLevel ); addNodeClass( TextureNode ); diff --git a/examples/jsm/nodes/accessors/TextureSizeNode.js b/examples/jsm/nodes/accessors/TextureSizeNode.js new file mode 100644 index 00000000000000..04501f1a16fdd1 --- /dev/null +++ b/examples/jsm/nodes/accessors/TextureSizeNode.js @@ -0,0 +1,35 @@ +import Node from '../core/Node.js'; +import { addNodeClass } from '../core/Node.js'; +import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; + +class TextureSizeNode extends Node { + + constructor( textureNode, levelNode = null ) { + + super( 'uvec2' ); + + this.isTextureSizeNode = true; + + this.textureNode = textureNode; + this.levelNode = levelNode; + + } + + generate( builder, output ) { + + const textureProperty = this.textureNode.build( builder, 'property' ); + const levelNode = this.levelNode.build( builder, 'int' ); + + return builder.format( `textureDimensions( ${textureProperty}, ${levelNode} )`, this.getNodeType( builder ), output ); + + } + +} + +export default TextureSizeNode; + +export const textureSize = nodeProxy( TextureSizeNode ); + +addNodeElement( 'textureSize', textureSize ); + +addNodeClass( TextureSizeNode ); From e861564f079e5f5ae3783c54c0c7e8c9e72e7768 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:51:44 -0300 Subject: [PATCH 06/12] Added ViewportDepthTextureNode: viewportDepthTexture() --- .../nodes/display/ViewportDepthTextureNode.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 examples/jsm/nodes/display/ViewportDepthTextureNode.js diff --git a/examples/jsm/nodes/display/ViewportDepthTextureNode.js b/examples/jsm/nodes/display/ViewportDepthTextureNode.js new file mode 100644 index 00000000000000..d090ad2b020b64 --- /dev/null +++ b/examples/jsm/nodes/display/ViewportDepthTextureNode.js @@ -0,0 +1,34 @@ +import ViewportTextureNode from './ViewportTextureNode.js'; +import { addNodeClass } from '../core/Node.js'; +import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; +import { viewportTopLeft } from './ViewportNode.js'; +import { DepthTexture, LinearMipmapLinearFilter, DepthFormat, UnsignedIntType } from 'three'; + +let sharedDepthbuffer = null; + +class ViewportDepthTextureNode extends ViewportTextureNode { + + constructor( uvNode = viewportTopLeft, levelNode = null ) { + + if ( sharedDepthbuffer === null ) { + + sharedDepthbuffer = new DepthTexture(); + sharedDepthbuffer.minFilter = LinearMipmapLinearFilter; + sharedDepthbuffer.type = UnsignedIntType; + sharedDepthbuffer.format = DepthFormat; + + } + + super( uvNode, levelNode, sharedDepthbuffer ); + + } + +} + +export default ViewportDepthTextureNode; + +export const viewportDepthTexture = nodeProxy( ViewportDepthTextureNode ); + +addNodeElement( 'viewportDepthTexture', viewportDepthTexture ); + +addNodeClass( ViewportDepthTextureNode ); From 543452dfa1491ffbda87b91e6f52158a7f5d10e8 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:51:57 -0300 Subject: [PATCH 07/12] Added ViewportDepthNode: depth, depthTexture() --- .../jsm/nodes/display/ViewportDepthNode.js | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 examples/jsm/nodes/display/ViewportDepthNode.js diff --git a/examples/jsm/nodes/display/ViewportDepthNode.js b/examples/jsm/nodes/display/ViewportDepthNode.js new file mode 100644 index 00000000000000..7c31c7f4d6349e --- /dev/null +++ b/examples/jsm/nodes/display/ViewportDepthNode.js @@ -0,0 +1,69 @@ +import Node, { addNodeClass } from '../core/Node.js'; +import { nodeImmutable, nodeProxy } from '../shadernode/ShaderNode.js'; +import { cameraNear, cameraFar } from '../accessors/CameraNode.js'; +import { positionView } from '../accessors/PositionNode.js'; +import { viewportDepthTexture } from './ViewportDepthTextureNode.js'; + +class ViewportDepthNode extends Node { + + constructor( scope, textureNode = null ) { + + super( 'float' ); + + this.scope = scope; + this.textureNode = textureNode; + + this.isViewportDepthNode = true; + + } + + construct( /*builder*/ ) { + + const { scope } = this; + + let node = null; + + if ( scope === ViewportDepthNode.DEPTH ) { + + node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); + + } else if ( scope === ViewportDepthNode.DEPTH_TEXTURE ) { + + const texture = this.textureNode || viewportDepthTexture(); + + const viewZ = perspectiveDepthToViewZ( texture, cameraNear, cameraFar ); + node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); + + } + + return node; + + } + +} + +// NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera + +// -near maps to 0; -far maps to 1 +export const viewZToOrthographicDepth = ( viewZ, near, far ) => viewZ.add( near ).div( near.sub( far ) ); + +// maps orthographic depth in [ 0, 1 ] to viewZ +export const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).mul( depth ).sub( near ); + +// NOTE: https://twitter.com/gonnavis/status/1377183786949959682 + +// -near maps to 0; -far maps to 1 +export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( near.sub( far ).mul( viewZ ) ); + +// maps perspective depth in [ 0, 1 ] to viewZ +export const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) ); + +ViewportDepthNode.DEPTH = 'depth'; +ViewportDepthNode.DEPTH_TEXTURE = 'depthTexture'; + +export default ViewportDepthNode; + +export const depth = nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH ); +export const depthTexture = nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH_TEXTURE ); + +addNodeClass( ViewportDepthNode ); From 5709d49a23552d9fb98225ab9da80181c60136f4 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:52:18 -0300 Subject: [PATCH 08/12] Added viewportMipTexture() --- .../display/ViewportSharedTextureNode.js | 11 +++--- .../jsm/nodes/display/ViewportTextureNode.js | 38 +++++++++++-------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/examples/jsm/nodes/display/ViewportSharedTextureNode.js b/examples/jsm/nodes/display/ViewportSharedTextureNode.js index 108631ceb77921..853f26feeda7e6 100644 --- a/examples/jsm/nodes/display/ViewportSharedTextureNode.js +++ b/examples/jsm/nodes/display/ViewportSharedTextureNode.js @@ -2,20 +2,21 @@ import ViewportTextureNode from './ViewportTextureNode.js'; import { addNodeClass } from '../core/Node.js'; import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; import { viewportTopLeft } from './ViewportNode.js'; +import { FramebufferTexture } from 'three'; let sharedFramebuffer = null; class ViewportSharedTextureNode extends ViewportTextureNode { - constructor( uv = viewportTopLeft ) { + constructor( uvNode = viewportTopLeft, levelNode = null ) { - super( uv ); + if ( sharedFramebuffer === null ) { - } + sharedFramebuffer = new FramebufferTexture(); - constructFramebuffer( builder ) { + } - return sharedFramebuffer || ( sharedFramebuffer = super.constructFramebuffer( builder ) ); + super( uvNode, levelNode, sharedFramebuffer ); } diff --git a/examples/jsm/nodes/display/ViewportTextureNode.js b/examples/jsm/nodes/display/ViewportTextureNode.js index e1af41eb04ea1d..356f5c28b4681d 100644 --- a/examples/jsm/nodes/display/ViewportTextureNode.js +++ b/examples/jsm/nodes/display/ViewportTextureNode.js @@ -3,33 +3,28 @@ import { NodeUpdateType } from '../core/constants.js'; import { addNodeClass } from '../core/Node.js'; import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; import { viewportTopLeft } from './ViewportNode.js'; -import { Vector2, FramebufferTexture } from 'three'; +import { Vector2, FramebufferTexture, LinearMipmapLinearFilter } from 'three'; const _size = new Vector2(); class ViewportTextureNode extends TextureNode { - constructor( uv = viewportTopLeft, level = null ) { + constructor( uvNode = viewportTopLeft, levelNode = null, framebufferTexture = null ) { - super( null, uv, level ); + if ( framebufferTexture === null ) { - this.isOutputTextureNode = true; - - this.updateBeforeType = NodeUpdateType.FRAME; - - } - - constructFramebuffer( /*builder*/ ) { + framebufferTexture = new FramebufferTexture(); + framebufferTexture.minFilter = LinearMipmapLinearFilter; - return new FramebufferTexture(); + } - } + super( framebufferTexture, uvNode, levelNode ); - construct( builder ) { + this.generateMipmaps = false; - if ( this.value === null ) this.value = this.constructFramebuffer( builder ); + this.isOutputTextureNode = true; - return super.construct( builder ); + this.updateBeforeType = NodeUpdateType.FRAME; } @@ -52,8 +47,19 @@ class ViewportTextureNode extends TextureNode { // + const currentGenerateMipmaps = framebufferTexture.generateMipmaps; + framebufferTexture.generateMipmaps = this.generateMipmaps; + renderer.copyFramebufferToTexture( framebufferTexture ); + framebufferTexture.generateMipmaps = currentGenerateMipmaps; + + } + + clone() { + + return new this.constructor( this.uvNode, this.levelNode, this.value ); + } } @@ -61,7 +67,9 @@ class ViewportTextureNode extends TextureNode { export default ViewportTextureNode; export const viewportTexture = nodeProxy( ViewportTextureNode ); +export const viewportMipTexture = nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } ); addNodeElement( 'viewportTexture', viewportTexture ); +addNodeElement( 'viewportMipTexture', viewportMipTexture ); addNodeClass( ViewportTextureNode ); From bf3fbe7b89f26fa7c03039bc295cbbed3df406ef Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:52:41 -0300 Subject: [PATCH 09/12] Update imports --- examples/jsm/nodes/Nodes.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/jsm/nodes/Nodes.js b/examples/jsm/nodes/Nodes.js index 9eaed9ad339f83..90a19fbbab3585 100644 --- a/examples/jsm/nodes/Nodes.js +++ b/examples/jsm/nodes/Nodes.js @@ -65,16 +65,17 @@ export * from './shadernode/ShaderNode.js'; export { default as BitangentNode, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, transformedBitangentView, transformedBitangentWorld } from './accessors/BitangentNode.js'; export { default as BufferAttributeNode, bufferAttribute, dynamicBufferAttribute } from './accessors/BufferAttributeNode.js'; export { default as BufferNode, buffer } from './accessors/BufferNode.js'; -export { default as CameraNode, cameraProjectionMatrix, cameraViewMatrix, cameraNormalMatrix, cameraWorldMatrix, cameraPosition } from './accessors/CameraNode.js'; +export { default as CameraNode, cameraProjectionMatrix, cameraViewMatrix, cameraNormalMatrix, cameraWorldMatrix, cameraPosition, cameraNear, cameraFar } from './accessors/CameraNode.js'; export { default as CubeTextureNode, cubeTexture } from './accessors/CubeTextureNode.js'; export { default as ExtendedMaterialNode, materialNormal } from './accessors/ExtendedMaterialNode.js'; export { default as InstanceNode, instance } from './accessors/InstanceNode.js'; export { default as MaterialNode, materialUV, materialAlphaTest, materialColor, materialShininess, materialEmissive, materialOpacity, materialSpecularColor, materialReflectivity, materialRoughness, materialMetalness, materialRotation } from './accessors/MaterialNode.js'; export { default as MaterialReferenceNode, materialReference } from './accessors/MaterialReferenceNode.js'; -export { default as ModelNode, modelDirection, modelViewMatrix, modelNormalMatrix, modelWorldMatrix, modelPosition, modelViewPosition } from './accessors/ModelNode.js'; +export { default as TextureBicubicNode, textureBicubic } from './accessors/TextureBicubicNode.js'; +export { default as ModelNode, modelDirection, modelViewMatrix, modelNormalMatrix, modelWorldMatrix, modelPosition, modelViewPosition, modelScale } from './accessors/ModelNode.js'; export { default as ModelViewProjectionNode, modelViewProjection } from './accessors/ModelViewProjectionNode.js'; export { default as NormalNode, normalGeometry, normalLocal, normalView, normalWorld, transformedNormalView, transformedNormalWorld } from './accessors/NormalNode.js'; -export { default as Object3DNode, objectDirection, objectViewMatrix, objectNormalMatrix, objectWorldMatrix, objectPosition, objectViewPosition } from './accessors/Object3DNode.js'; +export { default as Object3DNode, objectDirection, objectViewMatrix, objectNormalMatrix, objectWorldMatrix, objectPosition, objectScale, objectViewPosition } from './accessors/Object3DNode.js'; export { default as PointUVNode, pointUV } from './accessors/PointUVNode.js'; export { default as PositionNode, positionGeometry, positionLocal, positionWorld, positionWorldDirection, positionView, positionViewDirection } from './accessors/PositionNode.js'; export { default as ReferenceNode, reference } from './accessors/ReferenceNode.js'; @@ -82,7 +83,7 @@ export { default as ReflectVectorNode, reflectVector } from './accessors/Reflect export { default as SkinningNode, skinning } from './accessors/SkinningNode.js'; export { default as StorageBufferNode, storage } from './accessors/StorageBufferNode.js'; export { default as TangentNode, tangentGeometry, tangentLocal, tangentView, tangentWorld, transformedTangentView, transformedTangentWorld } from './accessors/TangentNode.js'; -export { default as TextureNode, texture, sampler } from './accessors/TextureNode.js'; +export { default as TextureNode, texture, /*textureLevel,*/ sampler } from './accessors/TextureNode.js'; export { default as UVNode, uv } from './accessors/UVNode.js'; export { default as UserDataNode, userData } from './accessors/UserDataNode.js'; @@ -95,8 +96,10 @@ export { default as NormalMapNode, normalMap, TBNViewMatrix } from './display/No export { default as PosterizeNode, posterize } from './display/PosterizeNode.js'; export { default as ToneMappingNode, toneMapping } from './display/ToneMappingNode.js'; export { default as ViewportNode, viewportCoordinate, viewportResolution, viewportTopLeft, viewportBottomLeft, viewportTopRight, viewportBottomRight } from './display/ViewportNode.js'; -export { default as ViewportTextureNode, viewportTexture } from './display/ViewportTextureNode.js'; +export { default as ViewportTextureNode, viewportTexture, viewportMipTexture } from './display/ViewportTextureNode.js'; 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 } from './display/ViewportDepthNode.js'; // code export { default as ExpressionNode, expression } from './code/ExpressionNode.js'; From 42b78c778d749fb1a8ed7d1b100759b7f78866eb Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 11:52:54 -0300 Subject: [PATCH 10/12] Add webgpu_backdrop_area example --- examples/files.json | 1 + examples/screenshots/webgpu_backdrop_area.jpg | Bin 0 -> 3413 bytes examples/webgpu_backdrop_area.html | 181 ++++++++++++++++++ test/e2e/puppeteer.js | 1 + 4 files changed, 183 insertions(+) create mode 100644 examples/screenshots/webgpu_backdrop_area.jpg create mode 100644 examples/webgpu_backdrop_area.html diff --git a/examples/files.json b/examples/files.json index fda127ff56df75..8a231b23885987 100644 --- a/examples/files.json +++ b/examples/files.json @@ -307,6 +307,7 @@ "webgpu": [ "webgpu_audio_processing", "webgpu_backdrop", + "webgpu_backdrop_area", "webgpu_compute", "webgpu_cubemap_adjustments", "webgpu_cubemap_dynamic", diff --git a/examples/screenshots/webgpu_backdrop_area.jpg b/examples/screenshots/webgpu_backdrop_area.jpg new file mode 100644 index 0000000000000000000000000000000000000000..001fe203e0b94e476d12e5c1c76aa979a0fbc77f GIT binary patch literal 3413 zcmex=iF;N$`UAd82aiwDGkXk%h!W@hDLXJZFTlSKSKz#z!M@QZN*Gov5_lOQ9r zAmjfdjEjJ7WCc47=uik?WMXDvWn%|Afm;CRY-VPlV_AVN1*)tC$}zAAvI;30I#U-U>$dGXcJ4ZK_{h;?$4{I*b?NeztJkjIxOwa0qsLF4K70P+<*SdMK7aZ8?fZ|P zzZe;qA>IL!82$lzoRJ9>=IkK_0Zp(e6?1osf!KmTtr@Gvt1BaB&)!Jgq?{R@T#ObuKN n8l%)`5R9gR(Tp%!7K|2$qcy^4Z8%yRj@E|5u{QkA@c$+N?bpn5 literal 0 HcmV?d00001 diff --git a/examples/webgpu_backdrop_area.html b/examples/webgpu_backdrop_area.html new file mode 100644 index 00000000000000..0d6ef01f164e86 --- /dev/null +++ b/examples/webgpu_backdrop_area.html @@ -0,0 +1,181 @@ + + + + three.js - WebGPU - Backdrop + + + + + + +
+ three.js WebGPU - Backdrop Area +
+ + + + + + + + diff --git a/test/e2e/puppeteer.js b/test/e2e/puppeteer.js index 7e76a9a93825ac..43c3e5af4284e6 100644 --- a/test/e2e/puppeteer.js +++ b/test/e2e/puppeteer.js @@ -94,6 +94,7 @@ const exceptionList = [ // Awaiting for WebGPU support 'webgpu_audio_processing', 'webgpu_backdrop', + 'webgpu_backdrop_area', 'webgpu_compute', 'webgpu_cubemap_adjustments', 'webgpu_cubemap_dynamic', From c19346834f2765d9f3c07067f4b9dda1c8c684ec Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 5 Jun 2023 15:53:37 -0300 Subject: [PATCH 11/12] update title --- examples/webgpu_backdrop_area.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webgpu_backdrop_area.html b/examples/webgpu_backdrop_area.html index 0d6ef01f164e86..5d5cd1a7f00d8a 100644 --- a/examples/webgpu_backdrop_area.html +++ b/examples/webgpu_backdrop_area.html @@ -1,7 +1,7 @@ - three.js - WebGPU - Backdrop + three.js - WebGPU - Backdrop Area From b2a5c7255609b0fa4a233208c38bd2c8a2b39bae Mon Sep 17 00:00:00 2001 From: sunag Date: Wed, 7 Jun 2023 13:10:10 -0300 Subject: [PATCH 12/12] CameraNode: Fix VIEW_MATRIX --- examples/jsm/nodes/accessors/CameraNode.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/jsm/nodes/accessors/CameraNode.js b/examples/jsm/nodes/accessors/CameraNode.js index 0dcf7c03d49680..df37f6150be612 100644 --- a/examples/jsm/nodes/accessors/CameraNode.js +++ b/examples/jsm/nodes/accessors/CameraNode.js @@ -34,7 +34,11 @@ class CameraNode extends Object3DNode { const uniformNode = this._uniformNode; const scope = this.scope; - if ( scope === CameraNode.PROJECTION_MATRIX ) { + if ( scope === CameraNode.VIEW_MATRIX ) { + + uniformNode.value = camera.matrixWorldInverse; + + } else if ( scope === CameraNode.PROJECTION_MATRIX ) { uniformNode.value = camera.projectionMatrix;