From b75d0c368f797502f5bd0c75404ee50f39474fd4 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 6 Apr 2026 19:11:38 +0200 Subject: [PATCH] FSR1Node: Add FSR 1 port for `WebGPURenderer`. (#33339) --- examples/files.json | 1 + examples/jsm/tsl/display/FSR1Node.js | 476 ++++++++++++++++++ .../screenshots/webgpu_upscaling_fsr1.jpg | Bin 0 -> 53006 bytes examples/webgpu_upscaling_fsr1.html | 184 +++++++ 4 files changed, 661 insertions(+) create mode 100644 examples/jsm/tsl/display/FSR1Node.js create mode 100644 examples/screenshots/webgpu_upscaling_fsr1.jpg create mode 100644 examples/webgpu_upscaling_fsr1.html diff --git a/examples/files.json b/examples/files.json index 85dc5dc3d49bd8..4cf75f535716d9 100644 --- a/examples/files.json +++ b/examples/files.json @@ -490,6 +490,7 @@ "webgpu_tsl_vfx_linkedparticles", "webgpu_tsl_vfx_tornado", "webgpu_tsl_wood", + "webgpu_upscaling_fsr1", "webgpu_video_frame", "webgpu_video_panorama", "webgpu_volume_caustics", diff --git a/examples/jsm/tsl/display/FSR1Node.js b/examples/jsm/tsl/display/FSR1Node.js new file mode 100644 index 00000000000000..1376ba2cccec6e --- /dev/null +++ b/examples/jsm/tsl/display/FSR1Node.js @@ -0,0 +1,476 @@ +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'; + +const _quadMesh = /*@__PURE__*/ new QuadMesh(); +const _size = /*@__PURE__*/ new Vector2(); + +let _rendererState; + +/** + * Post processing node for applying AMD FidelityFX Super Resolution 1 (FSR 1). + * + * Combines two passes: + * - **EASU** (Edge-Adaptive Spatial Upsampling): Uses 12 texture samples in a cross pattern + * to detect local edge direction, then shapes an approximate Lanczos2 kernel into an + * ellipse aligned with the detected edge. + * - **RCAS** (Robust Contrast-Adaptive Sharpening): Uses a 5-tap cross pattern to apply + * contrast-aware sharpening that is automatically limited per-pixel to avoid artifacts. + * + * Note: Only use FSR 1 if your application is fragment-shader bound and cannot afford to render + * at full resolution. FSR 1 adds its own overhead, so simply shaded scenes will render faster + * at native resolution without it. + * + * Reference: {@link https://gpuopen.com/fidelityfx-superresolution/}. + * + * @augments TempNode + * @three_import import { fsr1 } from 'three/addons/tsl/display/fsr1/FSR1Node.js'; + */ +class FSR1Node extends TempNode { + + static get type() { + + return 'FSR1Node'; + + } + + /** + * Constructs a new FSR 1 node. + * + * @param {TextureNode} textureNode - The texture node that represents the input of the effect. + * @param {Node} [sharpness=0.2] - RCAS sharpening strength. 0 = maximum sharpening, 2 = no sharpening. + * @param {Node} [denoise=false] - Whether to attenuate RCAS sharpening in noisy areas. + */ + constructor( textureNode, sharpness = 0.2, denoise = false ) { + + super( 'vec4' ); + + /** + * The texture node that represents the input of the effect. + * + * @type {TextureNode} + */ + this.textureNode = textureNode; + + /** + * RCAS sharpening strength. 0 = maximum, 2 = none. + * + * @type {Node} + */ + this.sharpness = nodeObject( sharpness ); + + /** + * Whether to attenuate RCAS sharpening in noisy areas. + * + * @type {Node} + */ + this.denoise = nodeObject( denoise ); + + /** + * The render target for the EASU upscale pass. + * + * @private + * @type {RenderTarget} + */ + this._easuRT = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType } ); + this._easuRT.texture.name = 'FSR1Node.easu'; + + /** + * The render target for the RCAS sharpen pass. + * + * @private + * @type {RenderTarget} + */ + this._rcasRT = new RenderTarget( 1, 1, { depthBuffer: false, type: HalfFloatType } ); + this._rcasRT.texture.name = 'FSR1Node.rcas'; + + /** + * The result of the effect as a texture node. + * + * @private + * @type {PassTextureNode} + */ + this._textureNode = passTexture( this, this._rcasRT.texture ); + + /** + * The material for the EASU pass. + * + * @private + * @type {?NodeMaterial} + */ + this._easuMaterial = null; + + /** + * The material for the RCAS pass. + * + * @private + * @type {?NodeMaterial} + */ + this._rcasMaterial = null; + + /** + * The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node renders + * its effect once per frame in `updateBefore()`. + * + * @type {string} + * @default 'frame' + */ + this.updateBeforeType = NodeUpdateType.FRAME; + + } + + /** + * Sets the output size of the effect. + * + * @param {number} width - The width in pixels. + * @param {number} height - The height in pixels. + */ + setSize( width, height ) { + + this._easuRT.setSize( width, height ); + this._rcasRT.setSize( width, height ); + + } + + /** + * This method is used to render the effect once per frame. + * + * @param {NodeFrame} frame - The current node frame. + */ + updateBefore( frame ) { + + const { renderer } = frame; + + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); + + // + + renderer.getDrawingBufferSize( _size ); + this.setSize( _size.x, _size.y ); + + // EASU pass + + renderer.setRenderTarget( this._easuRT ); + + _quadMesh.material = this._easuMaterial; + _quadMesh.name = 'FSR1 [ EASU Pass ]'; + _quadMesh.render( renderer ); + + // RCAS pass + + renderer.setRenderTarget( this._rcasRT ); + + _quadMesh.material = this._rcasMaterial; + _quadMesh.name = 'FSR1 [ RCAS Pass ]'; + _quadMesh.render( renderer ); + + // + + RendererUtils.restoreRendererState( renderer, _rendererState ); + + } + + /** + * Returns the result of the effect as a texture node. + * + * @return {PassTextureNode} A texture node that represents the result of the effect. + */ + getTextureNode() { + + return this._textureNode; + + } + + /** + * This method is used to setup the effect's TSL code. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {PassTextureNode} + */ + setup( builder ) { + + const textureNode = this.textureNode; + const inputTex = textureNode.value; + + // Note on performance: Compared to the orginal FSR1 code, texture sampling does + // not make use of textureGather() yet. This is only available with WebGPU so the + // WebGL 2 backend needs a fallback. Besides, in WebGPU and WebGL 2 we also + // can't make use of packed math (e.g. FP16) which would considerably lower + // the arithmetic costs (e.g. two 16-bit ops in parallel). + + // Accumulate edge direction and length for one bilinear quadrant. + + const _accumulateEdge = ( dir, len, w, aL, bL, cL, dL, eL ) => { + + const dc = dL.sub( cL ).toConst(); + const cb = cL.sub( bL ).toConst(); + const dirX = dL.sub( bL ).toConst(); + const lenX = max( abs( dc ), abs( cb ) ).toConst(); + const sLenX = saturate( abs( dirX ).div( max( lenX, float( 1.0 / 65536.0 ) ) ) ).toConst(); + + dir.x.addAssign( dirX.mul( w ) ); + len.addAssign( sLenX.mul( sLenX ).mul( w ) ); + + const ec = eL.sub( cL ).toConst(); + const ca = cL.sub( aL ).toConst(); + const dirY = eL.sub( aL ).toConst(); + const lenY = max( abs( ec ), abs( ca ) ).toConst(); + const sLenY = saturate( abs( dirY ).div( max( lenY, float( 1.0 / 65536.0 ) ) ) ).toConst(); + + dir.y.addAssign( dirY.mul( w ) ); + len.addAssign( sLenY.mul( sLenY ).mul( w ) ); + + }; + + // Compute an approximate Lanczos2 tap weight and accumulate. + + const _accumulateTap = ( aC, aW, offset, dir, len2, lob, clp, color ) => { + + const vx = offset.x.mul( dir.x ).add( offset.y.mul( dir.y ) ).toConst(); + const vy = offset.x.mul( dir.y ).negate().add( offset.y.mul( dir.x ) ).toConst(); + + const sx = vx.mul( len2.x ).toConst(); + const sy = vy.mul( len2.y ).toConst(); + const d2 = min( sx.mul( sx ).add( sy.mul( sy ) ), clp ).toConst(); + + const wB = d2.mul( 2.0 / 5.0 ).sub( 1.0 ).toConst(); + const wA = d2.mul( lob ).sub( 1.0 ).toConst(); + const w = wB.mul( wB ).mul( 25.0 / 16.0 ).sub( 25.0 / 16.0 - 1.0 ).mul( wA.mul( wA ) ).toConst(); + + aC.addAssign( color.mul( w ) ); + aW.addAssign( w ); + + }; + + // EASU pass: edge-adaptive spatial upsampling. + + const easu = Fn( () => { + + const targetUV = uv(); + const texSize = vec2( textureSize( textureNode ) ); + + const pp = targetUV.mul( texSize ).sub( 0.5 ).toConst(); + const fp = floor( pp ).toConst(); + const f = fract( pp ).toConst(); + + // Fetch exact texel values at integer coordinates (no filtering). + + const ifp = ivec2( int( fp.x ), int( fp.y ) ).toConst(); + const tap = ( dx, dy ) => textureLoad( inputTex, ifp.add( ivec2( dx, dy ) ) ); + + // 12-tap cross pattern: + // b c + // e f g h + // i j k l + // n o + + const sB = tap( 0, - 1 ), sC = tap( 1, - 1 ); + const sE = tap( - 1, 0 ), sF = tap( 0, 0 ), sG = tap( 1, 0 ), sH = tap( 2, 0 ); + const sI = tap( - 1, 1 ), sJ = tap( 0, 1 ), sK = tap( 1, 1 ), sL = tap( 2, 1 ); + const sN = tap( 0, 2 ), sO = tap( 1, 2 ); + + // Approximate luminance for edge detection. + + const luma = ( s ) => s.r.mul( 0.5 ).add( s.g ).add( s.b.mul( 0.5 ) ); + + const bL = luma( sB ), cL = luma( sC ); + const eL = luma( sE ), fL = luma( sF ), gL = luma( sG ), hL = luma( sH ); + const iL = luma( sI ), jL = luma( sJ ), kL = luma( sK ), lL = luma( sL ); + const nL = luma( sN ), oL = luma( sO ); + + // Accumulate edge direction and length from 4 bilinear quadrants. + + const dir = vec2( 0 ).toVar(); + const len = float( 0 ).toVar(); + + const w0 = float( 1 ).sub( f.x ).mul( float( 1 ).sub( f.y ) ).toConst(); + const w1 = f.x.mul( float( 1 ).sub( f.y ) ).toConst(); + const w2 = float( 1 ).sub( f.x ).mul( f.y ).toConst(); + const w3 = f.x.mul( f.y ).toConst(); + + _accumulateEdge( dir, len, w0, bL, eL, fL, gL, jL ); + _accumulateEdge( dir, len, w1, cL, fL, gL, hL, kL ); + _accumulateEdge( dir, len, w2, fL, iL, jL, kL, nL ); + _accumulateEdge( dir, len, w3, gL, jL, kL, lL, oL ); + + // Normalize direction, defaulting to (1, 0) when gradient is negligible. + + const dirSq = dir.x.mul( dir.x ).add( dir.y.mul( dir.y ) ).toConst(); + const zro = dirSq.lessThan( 1.0 / 32768.0 ).toConst(); + const rDirLen = float( 1.0 ).div( sqrt( max( dirSq, float( 1.0 / 32768.0 ) ) ) ).toConst(); + + dir.x.assign( select( zro, float( 1.0 ), dir.x ) ); + dir.mulAssign( select( zro, float( 1.0 ), rDirLen ) ); + + // Shape the kernel based on edge strength. + + len.assign( len.mul( 0.5 ) ); + len.mulAssign( len ); + + // Stretch factor: 1.0 for axis-aligned edges, sqrt(2) on diagonals. + + const stretch = dir.x.mul( dir.x ).add( dir.y.mul( dir.y ) ).div( max( abs( dir.x ), abs( dir.y ) ) ).toConst(); + + // Anisotropic lengths: x stretches along edge, y shrinks perpendicular. + + const len2 = vec2( + float( 1.0 ).add( stretch.sub( 1.0 ).mul( len ) ), + float( 1.0 ).sub( len.mul( 0.5 ) ) + ).toConst(); + + // Negative lobe: strong on flat areas (0.5), reduced on edges (0.21). + + const lob = float( 0.5 ).add( float( 1.0 / 4.0 - 0.04 - 0.5 ).mul( len ) ).toConst(); + const clp = float( 1.0 ).div( lob ).toConst(); + + // Accumulate weighted taps. + + const aC = vec4( 0 ).toVar(); + const aW = float( 0 ).toVar(); + + _accumulateTap( aC, aW, vec2( 0, - 1 ).sub( f ), dir, len2, lob, clp, sB ); + _accumulateTap( aC, aW, vec2( 1, - 1 ).sub( f ), dir, len2, lob, clp, sC ); + _accumulateTap( aC, aW, vec2( - 1, 0 ).sub( f ), dir, len2, lob, clp, sE ); + _accumulateTap( aC, aW, vec2( 0, 0 ).sub( f ), dir, len2, lob, clp, sF ); + _accumulateTap( aC, aW, vec2( 1, 0 ).sub( f ), dir, len2, lob, clp, sG ); + _accumulateTap( aC, aW, vec2( 2, 0 ).sub( f ), dir, len2, lob, clp, sH ); + _accumulateTap( aC, aW, vec2( - 1, 1 ).sub( f ), dir, len2, lob, clp, sI ); + _accumulateTap( aC, aW, vec2( 0, 1 ).sub( f ), dir, len2, lob, clp, sJ ); + _accumulateTap( aC, aW, vec2( 1, 1 ).sub( f ), dir, len2, lob, clp, sK ); + _accumulateTap( aC, aW, vec2( 2, 1 ).sub( f ), dir, len2, lob, clp, sL ); + _accumulateTap( aC, aW, vec2( 0, 2 ).sub( f ), dir, len2, lob, clp, sN ); + _accumulateTap( aC, aW, vec2( 1, 2 ).sub( f ), dir, len2, lob, clp, sO ); + + // Normalize. + + aC.divAssign( aW ); + + // Anti-ringing: clamp to min/max of the 4 nearest samples (f, g, j, k). + + const min4 = min( min( sF, sG ), min( sJ, sK ) ).toConst(); + const max4 = max( max( sF, sG ), max( sJ, sK ) ).toConst(); + + return clamp( aC, min4, max4 ); + + } ); + + // RCAS pass: robust contrast-adaptive sharpening. + + const easuTex = this._easuRT.texture; + + const rcas = Fn( () => { + + const targetUV = uv(); + const texSize = vec2( textureSize( textureLoad( easuTex ) ) ); + + const p = ivec2( int( floor( targetUV.x.mul( texSize.x ) ) ), int( floor( targetUV.y.mul( texSize.y ) ) ) ).toConst(); + + const e = textureLoad( easuTex, p ); + const b = textureLoad( easuTex, p.add( ivec2( 0, - 1 ) ) ); + const d = textureLoad( easuTex, p.add( ivec2( - 1, 0 ) ) ); + const f = textureLoad( easuTex, p.add( ivec2( 1, 0 ) ) ); + const h = textureLoad( easuTex, p.add( ivec2( 0, 1 ) ) ); + + // Approximate luminance (luma times 2). + + const luma = ( s ) => s.g.add( s.b.add( s.r ).mul( 0.5 ) ); + + const bL = luma( b ); + const dL = luma( d ); + const eL = luma( e ); + const fL = luma( f ); + const hL = luma( h ); + + // Sharpening amount from user parameter. + + const con = exp2( this.sharpness.negate() ).toConst(); + + // Min and max of ring. + + const mn4 = min( min( b.rgb, d.rgb ), min( f.rgb, h.rgb ) ).toConst(); + const mx4 = max( max( b.rgb, d.rgb ), max( f.rgb, h.rgb ) ).toConst(); + + // Compute adaptive lobe weight. + // Limiters based on how much sharpening the local contrast can tolerate. + + const RCAS_LIMIT = float( 0.25 - 1.0 / 16.0 ).toConst(); + + const hitMin = min( mn4, e.rgb ).div( mx4.mul( 4.0 ) ).toConst(); + const hitMax = vec3( 1.0 ).sub( max( mx4, e.rgb ) ).div( mn4.mul( 4.0 ).sub( 4.0 ) ).toConst(); + const lobeRGB = max( hitMin.negate(), hitMax ).toConst(); + + const lobe = max( + RCAS_LIMIT.negate(), + min( max( lobeRGB.r, max( lobeRGB.g, lobeRGB.b ) ), float( 0.0 ) ) + ).mul( con ).toConst(); + + // Noise attenuation. + + const nz = bL.add( dL ).add( fL ).add( hL ).mul( 0.25 ).sub( eL ).toConst(); + const nzRange = max( max( bL, dL ), max( eL, max( fL, hL ) ) ).sub( min( min( bL, dL ), min( eL, min( fL, hL ) ) ) ).toConst(); + const nzFactor = float( 1.0 ).sub( abs( nz ).div( max( nzRange, float( 1.0 / 65536.0 ) ) ).saturate().mul( 0.5 ) ).toConst(); + + const effectiveLobe = this.denoise.equal( true ).select( lobe.mul( nzFactor ), lobe ).toConst(); + + // Resolve: weighted blend of cross neighbors and center. + + const result = b.rgb.add( d.rgb ).add( f.rgb ).add( h.rgb ).mul( effectiveLobe ).add( e.rgb ) + .div( effectiveLobe.mul( 4.0 ).add( 1.0 ) ).toConst(); + + return vec4( result, e.a ); + + } ); + + // + + const context = builder.getSharedContext(); + + const easuMaterial = this._easuMaterial || ( this._easuMaterial = new NodeMaterial() ); + easuMaterial.fragmentNode = easu().context( context ); + easuMaterial.name = 'FSR1_EASU'; + easuMaterial.needsUpdate = true; + + const rcasMaterial = this._rcasMaterial || ( this._rcasMaterial = new NodeMaterial() ); + rcasMaterial.fragmentNode = rcas().context( context ); + rcasMaterial.name = 'FSR1_RCAS'; + rcasMaterial.needsUpdate = true; + + // + + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; + + // + + return this._textureNode; + + } + + /** + * Frees internal resources. This method should be called + * when the effect is no longer required. + */ + dispose() { + + this._easuRT.dispose(); + this._rcasRT.dispose(); + + if ( this._easuMaterial !== null ) this._easuMaterial.dispose(); + if ( this._rcasMaterial !== null ) this._rcasMaterial.dispose(); + + } + +} + +export default FSR1Node; + +/** + * TSL function for creating an FSR 1 node for post processing. + * + * @tsl + * @function + * @param {Node} node - The node that represents the input of the effect. + * @param {(number|Node)} [sharpness=0.2] - RCAS sharpening strength. 0 = maximum, 2 = none. + * @param {(boolean|Node)} [denoise=false] - Whether to attenuate RCAS sharpening in noisy areas. + * @returns {FSR1Node} + */ +export const fsr1 = ( node, sharpness, denoise ) => new FSR1Node( convertToTexture( node ), sharpness, denoise ); diff --git a/examples/screenshots/webgpu_upscaling_fsr1.jpg b/examples/screenshots/webgpu_upscaling_fsr1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4139487ea49fe159f0358c740d0cbe2b35c51da6 GIT binary patch literal 53006 zcmeFYcT|&4v@RS(r3xa_5tQB$=`~gm5D<`FA|f@?JA_1~cj-!tNRt}rJ&`V5q)8|A zPC^YNgqz7V?{Kj|v@Kl!z*SIMtlzjpolzg!ell-DV!D6U_pq@kpu{wI;X z(b7=U{`2EsZ@Y4hoctO!#dV5*ss8_zUH$|xPy)`$K9Q3#0Io2Qku#88c9MM~$$0Hw zL?a3MuZipm`PFOJDM%vF+$4!jPEHc`8c9-8%V1I+;3~tlTlb_MU1!v{q2Tej{oq4l zE+y~d$~Gp05e%R78_$na)XXfbZ0!63f;p(+}QrB-i(x+^qyL#gAOC-8^uHDQ-}+om18B*~NCQUB0006mEb8m)wY{Hy08j$R)B#<-+?fdn zZ!Q5j+Lr*xZ?cuHOMpr`@$4&kZwxU&^5XCzMKTNF0EAzAPcI;Owt_kx1aQ3o9rnWZ zGXN@|QR_*UfCU*qfD~+){}O<71pMFs`ajlRWa-Q&`>q?9d)FxMes5#_O3^_qhRxju zYypG-U$4BU{vQ^!h&!`e#yM2udopHe%HyLBc*e??SLe+bF80(;l(1$K@ajC_6P;`Y z5mAQNBF&3p{?lewb4xfklo#@9ybO8^!VuomVIDj)ZLaG9e$&tOQqGdFlG=MeHg+W( zk=$R+IbC4IJ4ml8ehB=EgTHT4Yr|X!tAN9mlOA})1|+YI3nXdD9iyO;C)v^`{@B&| zY|f^hNbfkcZNY)?c{bPOla6F6f*euy2svMk7u~-EyobsX5sxncq{-V0Tg)=)<_>|? zz$1?l5q(L>y8RK35v1U!f<)$-}xi#KtAb7Y8~)qSE+YAezpa^Ypk-BH+xbbhd-u_F zKzif`Z@ooK$Q9|mySudcNlJ9!B&1v#SB~iqX~uE1846 z_>-n#zJH%Cv~G-B=49jEZZzQZ-7C&YSq54roR7%M{RQS^|9b@hV-CN~PLcN?c~wDzl$r_3@<*~Q;vT`5T?ub_u(GikAnfRRKft(Ej=9a~DY+*)z`IprZ8;53d1k174E-7sV86TpnNeo)R`LiU0Qg&VSM3 zKi=jEVn&KsK%__1Mz2NBg9f`=Tap7j)RlWh7k3`*&`8}S8`7Xt=6*t^ml24Ja=ipp ztdF}RDA%&g;!aF``n8mX@@qm_GPm%e3#C=f3T~XRHdW#S;s}VwO^pZF--WgCuQ+F2 z8HFf%0pf?iMzg(~XS5h8@kS=S{ts)+_HR&9iWA-a(-%j+d zK%h7)EUO~}&Z6^r06`P|Xh~IK>~XioDApCy&T^Og=)3xCk~XKqb!3Q-*MZ_lG0oh& z9iO!6)Y?(4@701S8)Xi4Nq4nHeoR|EbY-QJ4oOw{2+$A}{QBsht|yB_(@#w=EHA_y z)3boNM8S??MRI}8PuLrbLO%#R;$vKA8S*%N$h(U8G_-_msD0KqlCTAxL+{_z2=$Db zD0-$_;85y<@Uh}+_6hV;rPsa4M2h%JxZ&ziw_KP3p-;=#W|-bg&9rW0!^4W z(>b)XOam{17Ib^YCzfACNGA}4Z1@K!(b-3}>GGlpB`#+<%6NC^G>jW%V+HJx@?Y-? zq+RY}VYzAQoa}^OipqUve+$6dadZ1UJy0Gfsrt7}-6lk9@AM4*q>Ui`lhY}>RF~S@ zl4)lFI^BG{<8uk9TId8#=bbd-L~|h?RoJ!EJSU~C7bm@U8W(spR1)2&d50zrPU+#f zTY(t`v>hB8nVD%sSnk?726GrLEz-bhvuf`C=k(MUxd*~KZLolq^CcAr$#3gV(ipB_wGnj z+;CDySFerh8aAg1^eFo0ut(9bc=`B9@b~#wajYq6cM0exuip~p&L_tWx*or>6*vaF z4G^9%q?n|sl`Bcr@Eo~;RSi%k;Oot~&Pa~2h36CHw9?;7nSR~;v%0pZC zd*EwUV4~T0F}qBGfdxOTVWShCwI&TCB#G9 zo|OE+m)-tEsYr44;Kps|_Ew>>_(9M1J8xA8Cr#;rZ$vGW};xKK@yn*oAO> z1#u{sKkt^As&M(0flGV6dDXy$mlZUBf94QF&xY~%GRrfk@?b3;8bi1QNE#lugmh5% z#d@3_jk5!LeRla*CZ~>YO+n46YB!0$kWyI5T_f-kJ(p>ozs9p@RcGJlKrM^#tp zEUr7ylBe06>H`3rCLgY^3mWIGWo}&pp6pb|E~j7PY$m^^LC@sau4HuykZDGuGK1jm zGryAZUc3tTN}}9Q6|EATLwTXsvdpa#Xf7I2Z`~qLwcPDNcvUd^h#eJKlj+ceDd^Kp zo4h~IlYATO-sh`6c<|%(&+CG0R|@ivg19QI;>$zIN(@sofOilQuy=5rAh2uU22Q?f z{!R_1yV@2_qobs-V;}Ld4p|M3YYQRtlWU(a8@?~=zCHxCYAt25pm}UiAX+5RsuJDv z`k?G2Rbi=E$SCxdtCH~arsni?0Yb;E$rq@Pyg_isxOJDaAqdi5F_}UBb}hAh@@ZA! zf44eT-@Zxs2yF5sV?}sT#pT8o4eAwcSDvNcaz}#OakUz(sRe#)&x+V2wx$UgFLp}H z&VG~3u;TD7f*~d%bpOcWhV_z<60!Uu+va|q4MY0Qq2=3V8{eG|#MgRm=FA1%Sp`Af zN|JxKm%1ZLaJObmGi1D*!vj`ch$Kr7?B4&mtoGU!c;Rzk8riUHzt&WJEXL=O{wG#u z1ghbO1)aoVfbH78*q%t&!rIXqgp!rIQ7C$MoJNtR4eIfWwU=CV`(vT3jWgcvTRdVE zacn!^zFO63V|RUT73`;1^lh{8>;kU^YtyNLPiKt2#2}&x{DpdG)(S{JH(ft^Mn~P~ zHD$b0&gLCvOXi+57T4$f4zg$Ae%%C(&u_#-R|_;%B`Owj>ebeH(6JKMsn6th*{hv( z0t@;kathOTYA*rT>gsVpOR5}b!OlA(ecSE6-5f%3b#SJFwRE?z=Y9FgHc5QTtJL|D zPrB(FJ7yiS&|8n=U#D!=yS^JsH%rpkHNRbDQfE6{ltTG&dAhJ`dY1r7{+!J8@cu^= z@|jUpY61BoNay$Wc}0J$BvExM3!^P`*DJMYLUZ$5w{!Xz5jatw^<7bnawm|A;D*+r ze~5j7WNy%OEt;TiD|y4i5B8oq&~kqsS&5%zjK+8s8+V}j@;HhG5Yt2rM8}yLGwA_J z6D!VIa`Qtct)!77CsOs`tqGnuFuE3_n}~KK=%JNkQk%TIr1PhrR)3-{6%wt4i~m@> zKJTfBNGBmd%4jm%i4BLW`pNenzlC|Pm#Tnd`!ibYrCu>Da&pWb9kXQ^WB~m za+2Z!GHVK)J9kd;){hP>0GI9!*Q?QyUQM-of}!s~I=Jgi*&oabh?B{t2fUP3OipsQ z#rp2MKU8cZ&qdJH-$Y|-IR&``yio)iOPm;t9W$q5q-B^j6Cc$rI**?lClGyqZ?0Yf zK4wAQROM(lqo%6ndZT46SXI=u`9kZSNIxxU_;oe;z1BzPdtIM3-ytsne|mGg6_&%D zAB%_-?(L^KHu+4BYCGHchY+bZmoEWSPUIF?_)hCZ<~t;4nyp2>s)l39>{V3{o5J+= za4`Y=jZ-6{TusYKehWWSx%FBhJzT1x;kS_>N3&Iz(|TU8w;Cf!o&xAt6?6i|2xTWc z{nK*&oIlsrLA9f-O_Dk-?Qewl!x>0_7Uz8~kNsb#nA-Koj#oza`oXf3x~SX}(=2{k zeskS8UGF{k<~iJq*bBqF5D$8WlSCsTVK<;6)*CF=qL_Jja9Jxny5e}!-4JU0cl7LQkn1Q%dh~=a!b;(a9v5r~wy?2rp=5xdbFbBhrZ@YJwLCZ!dSGqi%H)}(jo!MSTmjZuWAJj1o46FHEqeI>Mx;_$8LdBP}(|OQ&DwuKPWKg6| zebe~)S(&;3Qlh%l*d$qEBK*JF9Fn$v|AR%JTZA}P4F=UpG%mqD8aG{SN)Lf3Qy12| z&^lumtRz_X?5_2sO+EZtOdGH3UVCsh;S`l;@fSUpF-MFzk_?-r|D-1x@0P6rpYH9> z;&2iw=NGg`_9?-YyoW19{XH#fmO{_sO~y z*1yWmC9kK>xjDqT6xIYATB)+DTB~6Wc{)~yxl_8-Uph6^O}nS=9Q)}$Xn9vt*Tk*7 zF@FQcSV4H4zQpxq*~LOri8V=weMm=*qX*?bFuXclUiZsXzq!jj)WYBe^k#CVkClT>cQt0Q_y#tTA^F?T#o1O>OgUf*HtVs9yp ztJo2|7GYQu>p=0NXPvE{c5N!`)iRSC$;H54<0H`^misGSCRGg;_LzOLy@}*HlJQXIx$&m3CA4D=HK}d za5v1~2{^^_#6b~EI4_yxtT(xoEAM5)_^YLgV^cumLUNB}__-*>)PZ#GVQq&PnhMIVDQlG^6DRJY3V7m*L^ph0aHB86i zaHw~%mgoX4xXy2S7yaiCjp?_Ke@rc()qaULfB4F!o5FH(<7S_<&~J|u-4ksz)Y@8O z`^by4DNDH9$kqoutu3aB_ zZEccizVW>=%@0HLs!Ge*ze^)N#*UZyDvoq%9j$t8MM*w=|Dfb>Q@@cqGYUgbV39n@ z#ZBTBO$oA1IQgaKI35?>V12i}dmn|FMwrJ+5_#l3^;kCoCmRzD4NGMueqj`1=(Wn( zA={;dgb)|hVj-yRVt^V;c-Knn{>VjOAi-TD)%viANt9crioh66f&h>Aqln5l#L4@M zR3sHa9aaAsmjR447pN@jC~_K2aTGhIdfkwD>TE<#nccSzxTPw+{>G!>1z%FREXS#Q zpMsvs;I@gGFPD+c?NO(9(@oYzL+AV91TP!>3;*;b`-rdp88lWJmSY0-;zd?GmR(}i znruc=420)1rXk&Q$~K?v73FNgUtQF=rX^IX^@}VbW&53lRc@%)=oyK})7Cqdbz0EEGes>e!#wOMS+~T~3?=mEgLAV5NmyCKCn4jex zwQy->>u03=7}Wv08bdw&4^ILwzN)eM$MhjFuGLo!rB$x&79702GiAYH7BGyc^{=>J zFScB=RjW$fVA)SQnk}q;F{%N^D?|H0Oc2`&Gcc4FI(bmECYn*(C z62)Ivo$=W}E(rtn)N0R{71xXR+{aG>R9{r3-81SmimoaLUnK(=UQL zS=i021+DLF;_Zk7sOxH!I8ijH3lzgV&plawWXhA)VOpOfZ_u;K-{;cyi*1N(D9~iA zrQ=#;$(&Nu+$oT2pg|+*hf(1+TJUzQU(5_D_ZT4Z^TDS_Y*+othtvKW_(F)R8dl>c3;sV(r?7jTSQd||XUbV8{D z7U32y{*W7YVMna7&*q7_1ekb66iE{_%TbF9l1Bx}Mi-?%XRnD0Uq{4kZF}tdZ4Yv> zx^5$PE#;Fz#)BkJFeC`V?Lm>UP?H`@p-B5<%Hi;!7*;mbF~8tG|0uDd%$X!v^E^Y8 zg~P7=vH_dBW_U+J;p=5g0kO({+sN%F=&uLWL$n759f5%LjRb8TzAi@NrgOm}Yap<`BxyI&XMAtmF^ zZ;a-vl1V|6z`xEf+sBip?`!YPo((Tu0tlQO_~&!PKS}DqtWcJ zH7jP>Ut-3jdHikCvnIAgA5GSEUrO|u0wUJ1e9-p%Rvo>V`e~Z)YYVRI3q5Kxc%GDC`HvRl^I4gtF z!&UwC4B48!>IcHc;#QKb2mDkmB_VuFg01j1cXd`R(=Q{j!Q%!r`w1{Bol+oR zXH#p3=E<P=>iH=yaccU3XI#c4nD1j(}YW$Snr@`>b6bLlU`XG9l=J4jAN9q7vO zp!&*|G;7|NYXE%{tdU#mcu(COHc0)>&kFBCMMracvV%?8n5ZXdUT5?>17tz zS8ugc5&dK*)i{U8wL^TvO;dVu``RGG@Hue$_gV`+w?^k1Uv(8`foUY`$`milgA`cr((WM zq`rm?(jK#|8b>YWz?sKc?N+P)4F1#~_I|;YQwvE9dOq{_@d7*7B>-b^A*fqzfx1Q7 z__7`?T7UzPw2AN4{;I&=y)4!^OJ62F_U4EAfif=443>%1b9hzL`ItKK};<8Tm5tZ6jOA-~ncvWr?QgJbmY z@4NM;Zw=ik;;{R(cc3@&M)0txe+_v|d~+TynXf$o$Gn35y>%e?1?c3$%pYrq9Cz`e z>iLm$S5J2=2vW7KQ&WgAp)I1|cW?j`X^A1|uB25(nFl))t+X$k z2KzXFd!D$S&&-?XY?o{WNJbLeaviyAE+RS;A{N+MluKtF|4eVC9fDb;`W+|l>z3WS zE^xPkQGtGBCJCID;$iA+u=;Jrc}9M+D02?3`I!`pi!V^}kL|v_STN}7*kf%WS~wr$ zSP?PJO#yS|4oM>ZPJ@bL-FjejP9s}Q*ILe_lsdJ+O#P3`F#F&u|5!{busa?oW%ylfVV2z3QwYCM+!a{OnJ zu}i?0;0>0OKNoRX>qPbrbkUtl09tYM5`a6FES)53oJs{bgLfrc86|h&c=qqT7iCEH zqy6P_;3Xiz&@}K8@Qb)+zuk6GaGKk5GISC5Q)Hnwp+mpHo&Fzzk4?ra8UE2K)jBg! zGkAlrL$b$V(E9{-+%jHzGlvfM2n&9SH70onRI0JtwrCe!)khOD^Mkx+v@^HK#?B{Q zLE)Vw)KRFW?9^EDewWR><=6boHFE*fW7KY*4_+2Jf~wx{%)EV(?;WG6b%-tu3C^E3 zb55ixLRLOevPhl#Vl_9QbCVUbqErHUXS zNyW6AMQ4@jYS*NUon8)78FR<#wP!QA9$M#r?1o zcLLowHh z#PTM(1wUQ5R8Ca51RQ9TMq+K>r;dr%bBo9#U<79O6HtxA&Ne!sZe{_Ouq*8IeY0Ar zhf!Wi*$qljI7_!;l1D_?A83E!+adnB1W0#7MKI6UlTSReQVOo`>VjP)ODym2d*as^zJwVc9p9Oj&Su&;hUDztAZ_Pv+m;IqeWtOF!#0q4czJ zkaJK}$t7-*cBasKaW%Y+aMz?c*~a#RZYDxkbLQ#XUd>k8)`G_wFbda*wGEfZ0Y&DC zSe~YA7O?0b!E%MW{el8HP1+Ww=dOAA8Xp}wT zOxzmof+D!rHF|)ou*Eu9-Sv8GPO#`=M40ylP`9Sp;t_hP=2yjPz>IT=NZx`T!#HV-k^{GeokEObL0g#Y`B+G>-mc2=~Daqus;BnxKnS z9fFH@m3M`ecDadt+IPAq%oo3fXMk6z8MAJHIaQs<`Np57gF)EF9G_$xcNtqldST$2 zfwt}hxM(TBVOJ5`(;euydxoX!*Jb`R;}5+AXoR`get2x%G~M<<$DQ(Q#W>N(;^Q}d z5;9LA(>)aKp-wG4KaDcn$C>bTEaP|?jXjgV*&9cHgozml=_ASIh;D9b2pLWr0kOyS z&B>*rcUAW#jr+JC7#r=BCJsH{dU!_@U@|(S#n5=h#X&D-E=pUMylE=gA zLS%@m4~jK;jA`%xM3`UMDV7g!QTAYb0$vbR%+c1+q@F%L;uVWBsK1NUuaLKdoK`SfVXq{hs=dy4!b7I{MOYpv1<*hIkgR<3 zjfYWT()Z&Tko-CCUh%4#0As{*ba6-#(1FXziXS%D-FGrqH+`fELW2mmMo&aA^1BG| zqAGZCFTM1MEgJU}Yh^Vz%+xjVUM%@cPgH=$?!98S|Ay2?i>t^>r(XnfRx!bvriis* zSU#+c_Y$y}bsoAcQHdAzcU^mSH9VT_?!yP}QXJobkurIa6~s{iBy+6Mn0`L#m3y9m z6L4}lAog0{xe@;@2u@Ts#>$dReipJ_(h<>cus^MRLPBpp%0UO%`2yix^i$0p+g?5# za_|C++Oc{TvgiG_gPo3a(!8nq+tVdXl}2|`z6{58zJ9P}dHiScZR*Ss=+EA8+Afjg zPqc9z0~rf*NRQQ1raX$UyrGBJ#aepBCZs&WosHKENQoY9`7dlU-#SOz^)Jk!h~%)b zbB)Dx!mVl|B?AA*-R;@05GhIS=+&<|vym`68rhVD#1*W1MVsE6hb?T}k$Kyn z(@#)5^UO)@&twmA{FfGRC#K|PQuq3$IkFZRBLvWs^=fw&ciK7|LEOqfybe@ z>P7GgA5n|QOTZ7F`=j4eD{mTp?J1Ke1noMcM2^Egf$Hr;ayV}kjB}@%3+U@U*U?!J*b1~n#XUxXdv7CW<0rCAJ zGa%Fad*M5`N>x6q>IVEG=e_}7^0>{*eOnKHk#T6=O_GWocb}KMwP}>< z)V;67CADelK_|^X{d*-jKEXvPfZGpktdsU;L zJn6WZQFJUK4|a370V5xT+{1LBxf1aYEv9=hpcm17GnVy-@0NeRrmC}2@|3^E3RIh5 zTfQ4)@^*VkFtqvm-lQL)|40pn=an?8DgNEwPNm~QSx_$Dn(j4TgyC+lsTvnQf`?2P zuS#k^qGgw%$y&bp`b`VU$y|Fr6DAit&p{s6;d$^oENxS$6uHI$QT$!*GY3_srz_7g z5$y0f)1MOgu)3A6vw6CFPgg0SyScbeH`>4thvM@Oh+_v!rxZVX2DA;nHJy*B_W_^X zF?2eoi~Z9t8M1D3jR=X{W#RYp3|wkiN!^<|o}bW75M!#@biwDP;r4^kcWAo(yMC!>cNB|9$C~elk^Mp5#=W5|gFN%gCs9FW=bgpopY-}& z>0K*(H_N9*{r*f*Fk$jRixsC2%dN zswc3JFGbRw*N39);M7~T1F!7sTd=z;I(;jz%bR|*?H~`h=YsR|2J?VSF-56{$YT&u z3mSrZ(ne&$!O$+iHZDrcZccLErd$-baI@|vCAuz*#rd1iBH+46lBOA#%(_yNXL7TB z>eaCSz^5g*zXZHm*vkOiBbBJVXn@ausQkCE>UEZ#`Z8EMTdx0_>JPq#*wamc$#fTfP?Jr&h#bVr}Hagd?F@d7mP{P#vS7y zT>{#_V!84sreQGd-@8HqI4J6KgAFFTY6|3%6T+2+VgHw zBrv-cJ;)fibwRI;p$L?8uoW_J;*MFUMRjItFYoULEJ-r^N8@IvOu@INHr-j2ZNpib zqZ#Ub?=z6wvMz{nJzt*eXnUMgc@}SHT_`DCt_TckK=7dkw+8%4;FCQPC+~rsA~NQy z(WadQ3CTvuHVnkoq09X);I50b(Her$qtlO!PW;A3RvRYM%dE31z07ic28-i{ZA4hm1< zYgMNt(-OvkV;8aY4Q7B}D<+rOR`*(+fEf%eP@1M7C$S7a@2%E~^HrFkay4TyR;5W+^ut>m%o2 zBTUQ^@FS9!*sjJfA~UC%<{_L=V?b!T!*5(h}YO zjgJj)vH6&Va5e2cH!Ji;{eXAskthwg$BpVpd$JHUg!$XVS)&8$Ne!hPgitc;P^c52SWp_I=!RN>enGd0zUGY$&4_{a76k7K_?$M; z$CRtcmTlIx-&VhIr~>pp99`>Ky8&75=oOd-zBwPFs}o4sJ1Z|D+@U9H#h{{VP}7XM znm(oz+A-zKrcZMX2e>S;3O!JFIv|oFaJ%UCMt(Z%P+@yan_E%0Aa&`&Ku0-n2CF*e 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�egS9rZ`m9ciEK_g~f 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 ZeHZ6k8f)eEpu1e5&5}KHL3Z)~n*a+R&GrBQ literal 0 HcmV?d00001 diff --git a/examples/webgpu_upscaling_fsr1.html b/examples/webgpu_upscaling_fsr1.html new file mode 100644 index 00000000000000..c96bea73312ee8 --- /dev/null +++ b/examples/webgpu_upscaling_fsr1.html @@ -0,0 +1,184 @@ + + + + three.js webgpu - fsr1 + + + + + + +
+ + +
+ three.jsFSR 1 +
+ + + Web Port of AMD FidelityFX Super Resolution 1.
+ Model: Littlest Tokyo by Glen Fox, CC Attribution. +
+
+ + + + + +