Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGPURenderer: Backdrop Node - Part 2/3 #26196

Merged
merged 12 commits into from
Jun 7, 2023
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
"webgpu": [
"webgpu_audio_processing",
"webgpu_backdrop",
"webgpu_backdrop_area",
"webgpu_compute",
"webgpu_cubemap_adjustments",
"webgpu_cubemap_dynamic",
Expand Down
13 changes: 8 additions & 5 deletions examples/jsm/nodes/Nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,25 @@ 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';
export { default as ReflectVectorNode, reflectVector } from './accessors/ReflectVectorNode.js';
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';

Expand All @@ -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';
Expand Down
26 changes: 23 additions & 3 deletions examples/jsm/nodes/accessors/CameraNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class CameraNode extends Object3DNode {

return 'mat4';

} else if ( scope === CameraNode.NEAR || scope === CameraNode.FAR ) {

return 'float';

}

return super.getNodeType( builder );
Expand All @@ -30,13 +34,21 @@ 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;

} else if ( scope === CameraNode.VIEW_MATRIX ) {
} else if ( scope === CameraNode.NEAR ) {

uniformNode.value = camera.matrixWorldInverse;
uniformNode.value = camera.near;

} else if ( scope === CameraNode.FAR ) {

uniformNode.value = camera.far;

} else {

Expand All @@ -56,6 +68,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 );
Expand All @@ -65,10 +81,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 );
Expand Down
1 change: 1 addition & 0 deletions examples/jsm/nodes/accessors/ModelNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
12 changes: 10 additions & 2 deletions examples/jsm/nodes/accessors/Object3DNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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';

Expand Down Expand Up @@ -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';

Expand All @@ -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 );
94 changes: 94 additions & 0 deletions examples/jsm/nodes/accessors/TextureBicubicNode.js
Original file line number Diff line number Diff line change
@@ -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 );
37 changes: 37 additions & 0 deletions examples/jsm/nodes/accessors/TextureNode.js
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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 );
Expand All @@ -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 );
35 changes: 35 additions & 0 deletions examples/jsm/nodes/accessors/TextureSizeNode.js
Original file line number Diff line number Diff line change
@@ -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 );
Loading