From 07830aaf43952fc1b3e9527a700335a14949a651 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Tue, 17 Sep 2024 08:43:40 +0100 Subject: [PATCH 1/6] wip --- src/renderers/common/extras/PMREMGenerator.js | 104 +++++++++++------- 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/src/renderers/common/extras/PMREMGenerator.js b/src/renderers/common/extras/PMREMGenerator.js index 110bc0f7639053..41cd23a9d4f9d2 100644 --- a/src/renderers/common/extras/PMREMGenerator.js +++ b/src/renderers/common/extras/PMREMGenerator.js @@ -1,8 +1,7 @@ import NodeMaterial from '../../../materials/nodes/NodeMaterial.js'; import { getDirection, blur } from '../../../nodes/pmrem/PMREMUtils.js'; import { equirectUV } from '../../../nodes/utils/EquirectUVNode.js'; -import { uniform } from '../../../nodes/core/UniformNode.js'; -import { uniformArray } from '../../../nodes/accessors/UniformArrayNode.js'; +import { userData } from '../../../nodes/accessors/UserDataNode.js'; import { texture } from '../../../nodes/accessors/TextureNode.js'; import { cubeTexture } from '../../../nodes/accessors/CubeTextureNode.js'; import { float, vec3 } from '../../../nodes/tsl/TSLBase.js'; @@ -113,6 +112,7 @@ class PMREMGenerator { this._cubemapMaterial = null; this._equirectMaterial = null; this._backgroundBox = null; + this._userData = {}; } @@ -516,20 +516,49 @@ class PMREMGenerator { const renderer = this._renderer; const blurMaterial = this._blurMaterial; + const blurMesh = this._lodMeshes[ lodOut ]; + + blurMesh.material = blurMaterial; + blurMesh.userData = this._getUserDataBlur( targetIn, lodIn, sigmaRadians, direction, poleAxis ); + + targetIn.texture.frame = ( targetIn.texture.frame || 0 ) + 1; + + blurMaterial._envMap.value = targetIn.texture; + + const { _lodMax } = this; + + const outputSize = this._sizeLods[ lodOut ]; + const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); + const y = 4 * ( this._cubeSize - outputSize ); + + _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( targetOut ); + renderer.render( blurMesh, _flatCamera ); + + } + + _getUserDataBlur( targetIn, lodIn, sigmaRadians, direction, poleAxis ) { + + const cacheKey = `${ direction }-${ lodIn }`; + + const u = this._userData[ cacheKey ]; + + if ( u !== undefined ) return u; + + + // populate data for this pass + if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { console.error( 'blur direction must be either latitudinal or longitudinal!' ); } + const { _lodMax } = this; + // Number of standard deviations at which to cut off the discrete approximation. const STANDARD_DEVIATIONS = 3; - const blurMesh = this._lodMeshes[ lodOut ]; - blurMesh.material = blurMaterial; - - const blurUniforms = blurMaterial.uniforms; - const pixels = this._sizeLods[ lodIn ] - 1; const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); const sigmaPixels = sigmaRadians / radiansPerPixel; @@ -543,14 +572,15 @@ class PMREMGenerator { } - const weights = []; + const weights = new Array( MAX_SAMPLES ).fill( 0 ); + let sum = 0; for ( let i = 0; i < MAX_SAMPLES; ++ i ) { const x = i / sigmaPixels; const weight = Math.exp( - x * x / 2 ); - weights.push( weight ); + weights[ i ] = weight; if ( i === 0 ) { @@ -570,30 +600,20 @@ class PMREMGenerator { } - targetIn.texture.frame = ( targetIn.texture.frame || 0 ) + 1; - - blurUniforms.envMap.value = targetIn.texture; - blurUniforms.samples.value = samples; - blurUniforms.weights.array = weights; - blurUniforms.latitudinal.value = direction === 'latitudinal' ? 1 : 0; - - if ( poleAxis ) { - - blurUniforms.poleAxis.value = poleAxis; - - } - - const { _lodMax } = this; - blurUniforms.dTheta.value = radiansPerPixel; - blurUniforms.mipInt.value = _lodMax - lodIn; + const userData = { + latitudinal: direction === 'latitudinal' ? 1 : 0, + weights, + poleAxis, + outputDirection, + dTheta: radiansPerPixel, + samples, + envMap: targetIn.texture, + mipInt: _lodMax - lodIn + }; - const outputSize = this._sizeLods[ lodOut ]; - const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); - const y = 4 * ( this._cubeSize - outputSize ); + this._userData[ cacheKey ] = userData; - _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); - renderer.setRenderTarget( targetOut ); - renderer.render( blurMesh, _flatCamera ); + return userData; } @@ -715,18 +735,20 @@ function _getMaterial( type ) { function _getBlurShader( lodMax, width, height ) { - const weights = uniformArray( new Array( MAX_SAMPLES ).fill( 0 ) ); - const poleAxis = uniform( new Vector3( 0, 1, 0 ) ); - const dTheta = uniform( 0 ); + const weights = userData( 'weights', 'float' ); + const poleAxis = userData( 'poleAxis', 'vec3' ); + const dTheta = userData( 'dTheta', 'float' ); const n = float( MAX_SAMPLES ); - const latitudinal = uniform( 0 ); // false, bool - const samples = uniform( 1 ); // int - const envMap = texture( null ); - const mipInt = uniform( 0 ); // int + const latitudinal = userData( 'latitudinal', 'float' ); // false, bool + const samples = userData( 'samples', 'float' ); // int + const mipInt = userData( 'mipInt', 'float' ); // int const CUBEUV_TEXEL_WIDTH = float( 1 / width ); const CUBEUV_TEXEL_HEIGHT = float( 1 / height ); const CUBEUV_MAX_MIP = float( lodMax ); + const material = _getMaterial( 'blur' ); + material._envMap = texture( null ); + const materialUniforms = { n, latitudinal, @@ -735,15 +757,15 @@ function _getBlurShader( lodMax, width, height ) { outputDirection, dTheta, samples, - envMap, + envMap: texture( null ), mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP }; - const material = _getMaterial( 'blur' ); - material.uniforms = materialUniforms; // TODO: Move to outside of the material + material._envMap = materialUniforms.envMap; + material.fragmentNode = blur( { ...materialUniforms, latitudinal: latitudinal.equal( 1 ) } ); return material; From 45d85f5d96595db99f9a09d880c1f5b8dacc16c2 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Thu, 14 Nov 2024 21:50:28 +0000 Subject: [PATCH 2/6] remove string creation --- src/renderers/common/extras/PMREMGenerator.js | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/renderers/common/extras/PMREMGenerator.js b/src/renderers/common/extras/PMREMGenerator.js index 41cd23a9d4f9d2..d76282fcc926ea 100644 --- a/src/renderers/common/extras/PMREMGenerator.js +++ b/src/renderers/common/extras/PMREMGenerator.js @@ -112,7 +112,7 @@ class PMREMGenerator { this._cubemapMaterial = null; this._equirectMaterial = null; this._backgroundBox = null; - this._userData = {}; + this._userData = { longitudinal: [], latitudinal: [] }; } @@ -539,20 +539,19 @@ class PMREMGenerator { _getUserDataBlur( targetIn, lodIn, sigmaRadians, direction, poleAxis ) { - const cacheKey = `${ direction }-${ lodIn }`; + const cache = this._userData[ direction ]; - const u = this._userData[ cacheKey ]; - - if ( u !== undefined ) return u; + if ( cache === undefined ) { + console.error( 'blur direction must be either latitudinal or longitudinal!' ); - // populate data for this pass + } - if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { + const u = cache[ lodIn ]; - console.error( 'blur direction must be either latitudinal or longitudinal!' ); + if ( u !== undefined ) return u; - } + // populate data for this pass const { _lodMax } = this; @@ -611,7 +610,7 @@ class PMREMGenerator { mipInt: _lodMax - lodIn }; - this._userData[ cacheKey ] = userData; + cache[ lodIn ] = userData; return userData; @@ -747,7 +746,6 @@ function _getBlurShader( lodMax, width, height ) { const CUBEUV_MAX_MIP = float( lodMax ); const material = _getMaterial( 'blur' ); - material._envMap = texture( null ); const materialUniforms = { n, From b2bb8844fdc63b047f4a89fc783af859175342ce Mon Sep 17 00:00:00 2001 From: aardgoose Date: Thu, 14 Nov 2024 22:23:00 +0000 Subject: [PATCH 3/6] make more calcs once only --- src/renderers/common/extras/PMREMGenerator.js | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/renderers/common/extras/PMREMGenerator.js b/src/renderers/common/extras/PMREMGenerator.js index d76282fcc926ea..97ad7a4ae5135e 100644 --- a/src/renderers/common/extras/PMREMGenerator.js +++ b/src/renderers/common/extras/PMREMGenerator.js @@ -468,11 +468,7 @@ class PMREMGenerator { for ( let i = 1; i < n; i ++ ) { - const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); - - const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; - - this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); + this._blur( cubeUVRenderTarget, i - 1, i ); } @@ -487,7 +483,7 @@ class PMREMGenerator { * the poles) to approximate the orthogonally-separable blur. It is least * accurate at the poles, but still does a decent job. */ - _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { + _blur( cubeUVRenderTarget, lodIn, lodOut ) { const pingPongRenderTarget = this._pingPongRenderTarget; @@ -496,22 +492,18 @@ class PMREMGenerator { pingPongRenderTarget, lodIn, lodOut, - sigma, - 'latitudinal', - poleAxis ); + 'latitudinal' ); this._halfBlur( pingPongRenderTarget, cubeUVRenderTarget, lodOut, lodOut, - sigma, - 'longitudinal', - poleAxis ); + 'longitudinal' ); } - _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { + _halfBlur( targetIn, targetOut, lodIn, lodOut, direction ) { const renderer = this._renderer; const blurMaterial = this._blurMaterial; @@ -519,7 +511,7 @@ class PMREMGenerator { const blurMesh = this._lodMeshes[ lodOut ]; blurMesh.material = blurMaterial; - blurMesh.userData = this._getUserDataBlur( targetIn, lodIn, sigmaRadians, direction, poleAxis ); + blurMesh.userData = this._getUserDataBlur( targetIn, lodIn, lodOut, direction ); targetIn.texture.frame = ( targetIn.texture.frame || 0 ) + 1; @@ -537,7 +529,7 @@ class PMREMGenerator { } - _getUserDataBlur( targetIn, lodIn, sigmaRadians, direction, poleAxis ) { + _getUserDataBlur( targetIn, lodIn, lodOut, direction ) { const cache = this._userData[ direction ]; @@ -555,6 +547,8 @@ class PMREMGenerator { const { _lodMax } = this; + const sigmaRadians = Math.sqrt( this._sigmas[ lodOut ] * this._sigmas[ lodOut ] - this._sigmas[ lodOut - 1 ] * this._sigmas[ lodOut - 1 ] ); + // Number of standard deviations at which to cut off the discrete approximation. const STANDARD_DEVIATIONS = 3; @@ -599,6 +593,9 @@ class PMREMGenerator { } + const n = this._lodPlanes.length; + const poleAxis = _axisDirections[ ( n - lodOut - 1 ) % _axisDirections.length ]; + const userData = { latitudinal: direction === 'latitudinal' ? 1 : 0, weights, From 5b562c1cae6e984d4224d6933b92cfe4a3bad9c3 Mon Sep 17 00:00:00 2001 From: aardgoose Date: Fri, 15 Nov 2024 15:32:18 +0000 Subject: [PATCH 4/6] cache userData per texture --- src/renderers/common/extras/PMREMGenerator.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/renderers/common/extras/PMREMGenerator.js b/src/renderers/common/extras/PMREMGenerator.js index 97ad7a4ae5135e..2d07b1a93d630a 100644 --- a/src/renderers/common/extras/PMREMGenerator.js +++ b/src/renderers/common/extras/PMREMGenerator.js @@ -112,7 +112,8 @@ class PMREMGenerator { this._cubemapMaterial = null; this._equirectMaterial = null; this._backgroundBox = null; - this._userData = { longitudinal: [], latitudinal: [] }; + this._userDataMap = new WeakMap(); + this._userData = null; } @@ -129,6 +130,8 @@ class PMREMGenerator { _oldActiveCubeFace = this._renderer.getActiveCubeFace(); _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + if ( this._userData === null ) this._userData = { longitudinal: [], latitudinal: [] }; + this._setSize( 256 ); const cubeUVRenderTarget = this._allocateTargets(); @@ -265,6 +268,17 @@ class PMREMGenerator { } + let userData = this._userDataMap.get( texture ); + + if ( userData === undefined ) { + + userData = { longitudinal: [], latitudinal: [] }; + this._userDataMap.set( texture, userData ); + + } + + this._userData = userData; + _oldTarget = this._renderer.getRenderTarget(); _oldActiveCubeFace = this._renderer.getActiveCubeFace(); _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); From 92a1717475305230b72d67896286bc764044f1dd Mon Sep 17 00:00:00 2001 From: sunag Date: Wed, 18 Dec 2024 15:08:30 -0300 Subject: [PATCH 5/6] using integers --- src/renderers/common/extras/PMREMGenerator.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/renderers/common/extras/PMREMGenerator.js b/src/renderers/common/extras/PMREMGenerator.js index f6c53e9df2b199..f1f8a697b332fd 100644 --- a/src/renderers/common/extras/PMREMGenerator.js +++ b/src/renderers/common/extras/PMREMGenerator.js @@ -4,7 +4,7 @@ import { equirectUV } from '../../../nodes/utils/EquirectUVNode.js'; import { userData } from '../../../nodes/accessors/UserDataNode.js'; import { texture } from '../../../nodes/accessors/TextureNode.js'; import { cubeTexture } from '../../../nodes/accessors/CubeTextureNode.js'; -import { float, vec3 } from '../../../nodes/tsl/TSLBase.js'; +import { float, int, vec3 } from '../../../nodes/tsl/TSLBase.js'; import { uv } from '../../../nodes/accessors/UV.js'; import { attribute } from '../../../nodes/core/AttributeNode.js'; @@ -848,9 +848,9 @@ function _getBlurShader( lodMax, width, height ) { const poleAxis = userData( 'poleAxis', 'vec3' ); const dTheta = userData( 'dTheta', 'float' ); const n = float( MAX_SAMPLES ); - const latitudinal = userData( 'latitudinal', 'float' ); // false, bool - const samples = userData( 'samples', 'float' ); // int - const mipInt = userData( 'mipInt', 'float' ); // int + const latitudinal = userData( 'latitudinal', 'int' ); // bool + const samples = userData( 'samples', 'int' ); + const mipInt = userData( 'mipInt', 'int' ); const CUBEUV_TEXEL_WIDTH = float( 1 / width ); const CUBEUV_TEXEL_HEIGHT = float( 1 / height ); const CUBEUV_MAX_MIP = float( lodMax ); @@ -874,7 +874,7 @@ function _getBlurShader( lodMax, width, height ) { material._envMap = materialUniforms.envMap; - material.fragmentNode = blur( { ...materialUniforms, latitudinal: latitudinal.equal( 1 ) } ); + material.fragmentNode = blur( { ...materialUniforms, latitudinal: latitudinal.equal( int( 1 ) ) } ); return material; From 3494bf222a7f2720f12ab8215139e2cdf252fc96 Mon Sep 17 00:00:00 2001 From: sunag Date: Wed, 18 Dec 2024 15:17:40 -0300 Subject: [PATCH 6/6] cleanup --- src/renderers/common/extras/PMREMGenerator.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderers/common/extras/PMREMGenerator.js b/src/renderers/common/extras/PMREMGenerator.js index f1f8a697b332fd..f21f1933c32ccc 100644 --- a/src/renderers/common/extras/PMREMGenerator.js +++ b/src/renderers/common/extras/PMREMGenerator.js @@ -159,8 +159,6 @@ class PMREMGenerator { if ( this._userData === null ) this._userData = { longitudinal: [], latitudinal: [] }; - this._setSize( 256 ); - const cubeUVRenderTarget = renderTarget || this._allocateTargets(); cubeUVRenderTarget.depthBuffer = true;