From 0891f41848ed9fe4eeb13b9477fc8d585d2a5f20 Mon Sep 17 00:00:00 2001 From: Alexandru Popovici Date: Mon, 16 Jan 2023 21:04:41 +0200 Subject: [PATCH] Alex/shadowcatcher (#1316) * Some messing around with a virtual plane * WIP on virtual plane vertex baking * Added a pass for generating the shadowcatcher texture. Implementation WIP * PoC for the baked ray traced AO for the shadowcatcher * WIP on shadowcatcher proper implementation. Removed the shadocatcher pass from the pipeline, and added it as standalone. Implemented the Shadowcatcher class which handles the entire generation process in a centralized way. Added real time parameters in the sandbox so we can see how different configurations work * Added some more debug funationality. Working on improving vertex level ao calculation * Dynamic max hit distance calculation for the shadowcatcher * Added proper AO contribution value calculation and in the process removed the need for specifying a max hit distance * Implemented explicit materials and shaders for shadowcatcher generation and display * Proper materials, shaders and blending so that any backround will work correctly * Added auto corection for texture size for situations where the AO was overly/under saturated. * Fixed an issue where batches were incorrectly tested. Fixed an issue where blending for existing overlapping transparent surfaces was incorrect * WIP for render based ao generation * First draft of detail preserving shadowcatcher * Improvement that removes over dakened areas * Weigthed color0 and color1 evenly when extracting color3 from their sum * Formalized the shadowcatcher and integrated it better with the speckle renderer or anything else it might use it * Pipeline needs reset after shadowcatcher update * Added RTE to the virtual plane and shadowcatcher AO generation material. Removed unused library * Shadowcather now updated with the clipping planes as well as any filters apply, such that only opaque and non clipped scene objects contribute to the shadowcatcher's AO * Fixed an old issue which makes extended three materials not get their custom uniforms properly updated when they are being used as scene material overrides. Tested shadowcatcher with multiple streams and it works as expected * Improved plane fringing on streams that manifest it * Added enabling/disabling shadowcatcher via the light configuration * Removed unused material and shader. Fixed an issue where pow of negative value would return undefined on some platforms, messing up the final shadowcatcher result * WIP on better blending for other scene transparent materials * Changed the way shadowcatcher levels are blended together. Now they are initially added on top of another, then a sigmoid function is used to tone map the final value. This comes as a solution to reducing the very low darks signaled in some streams. On top of data, it also improves general contrast to streams with little surface contact. * Removed the third shadowcatcher level from blending. It doesn't bring much value and it over-darkens most of the time * Shadowcatcher is updated when streams are unloaded * Enabled on-demand rendering of shadowcatcher levels Co-authored-by: Alex --- packages/viewer-sandbox/src/Sandbox.ts | 34 ++++++++- packages/viewer-sandbox/src/main.ts | 9 ++- packages/viewer/src/modules/Shadowcatcher.ts | 16 ++-- .../viewer/src/modules/SpeckleRenderer.ts | 1 + .../SpeckleShadowcatcherGenerateMaterial.ts | 47 ------------ .../materials/SpeckleShadowcatcherMaterial.ts | 19 +++-- .../shaders/speckle-shadowcatche-frag.ts | 73 ++++--------------- .../speckle-shadowcatcher-generate-frag.ts | 57 --------------- .../speckle-shadowcatcher-generate-vert.ts | 65 ----------------- .../src/modules/pipeline/ShadowcatcherPass.ts | 11 ++- 10 files changed, 87 insertions(+), 245 deletions(-) delete mode 100644 packages/viewer/src/modules/materials/SpeckleShadowcatcherGenerateMaterial.ts delete mode 100644 packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-frag.ts delete mode 100644 packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-vert.ts diff --git a/packages/viewer-sandbox/src/Sandbox.ts b/packages/viewer-sandbox/src/Sandbox.ts index 5e50d9f4f..769f6ea2d 100644 --- a/packages/viewer-sandbox/src/Sandbox.ts +++ b/packages/viewer-sandbox/src/Sandbox.ts @@ -81,7 +81,9 @@ export default class Sandbox { textureSize: 512, weights: { x: 1, y: 1, z: 0, w: 1 }, blurRadius: 16, - stdDeviation: 4 + stdDeviation: 4, + sigmoidRange: 2, + sigmoidStrength: 2.43 } public constructor(viewer: DebugViewer, selectionList: SelectionEvent[]) { @@ -702,8 +704,8 @@ export default class Sandbox { label: 'weights', x: { min: 0, max: 100 }, y: { min: 0, max: 100 }, - z: { min: 0, max: 100 }, - w: { min: 0, max: 100 } + z: { min: -100, max: 100 }, + w: { min: -100, max: 100 } }) .on('change', (value) => { value @@ -737,6 +739,32 @@ export default class Sandbox { Sandbox.shadowCatcherParams this.viewer.getRenderer().updateShadowCatcher() }) + shadowcatcherFolder + .addInput(Sandbox.shadowCatcherParams, 'sigmoidRange', { + label: 'Sigmoid Range', + min: -10, + max: 10, + step: 0.1 + }) + .on('change', (value) => { + value + this.viewer.getRenderer().shadowcatcher.configuration = + Sandbox.shadowCatcherParams + this.viewer.getRenderer().updateShadowCatcher() + }) + shadowcatcherFolder + .addInput(Sandbox.shadowCatcherParams, 'sigmoidStrength', { + label: 'Sigmoid Strength', + min: -10, + max: 10, + step: 0.1 + }) + .on('change', (value) => { + value + this.viewer.getRenderer().shadowcatcher.configuration = + Sandbox.shadowCatcherParams + this.viewer.getRenderer().updateShadowCatcher() + }) } makeFilteringUI() { diff --git a/packages/viewer-sandbox/src/main.ts b/packages/viewer-sandbox/src/main.ts index e0d84ae90..796db1d0e 100644 --- a/packages/viewer-sandbox/src/main.ts +++ b/packages/viewer-sandbox/src/main.ts @@ -84,7 +84,7 @@ sandbox.makeBatchesUI() await sandbox.loadUrl( // 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D' // Revit sample house (good for bim-like stuff with many display meshes) - 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8' + // 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8' // 'Super' heavy revit shit // 'https://speckle.xyz/streams/e6f9156405/commits/0694d53bb5' // IFC building (good for a tree based structure) @@ -172,4 +172,11 @@ await sandbox.loadUrl( // 'https://speckle.xyz/streams/7ce9010d71/commits/d29e56fe75' // Filter issue // 'https://speckle.xyz/streams/f95d8deb90/commits/30f31becb6' + // Transparent + // 'https://latest.speckle.dev/streams/b5cc4e967c/objects/20343e0e8d469613a9d407499a6c38b1' + // dark + // 'https://latest.speckle.dev/streams/b5cc4e967c/commits/efdf3e2728?c=%5B-59.16128,-41.76491,-4.77376,-4.08052,-12.63558,-4.77376,0,1%5D' + // 'https://latest.speckle.dev/streams/92b620fb17/commits/b4366a7086?filter=%7B%7D&c=%5B-31.02357,37.60008,96.58899,11.01564,7.40652,66.0411,0,1%5D)' + // double + 'https://latest.speckle.dev/streams/92b620fb17/commits/b4366a7086?overlay=c009dbe144&filter=%7B%7D&c=%5B-104.70053,-98.80617,67.44669,6.53096,1.8739,38.584,0,1%5D' ) diff --git a/packages/viewer/src/modules/Shadowcatcher.ts b/packages/viewer/src/modules/Shadowcatcher.ts index ac7ad4676..ae073792f 100644 --- a/packages/viewer/src/modules/Shadowcatcher.ts +++ b/packages/viewer/src/modules/Shadowcatcher.ts @@ -4,6 +4,7 @@ import { CustomBlending, DstAlphaFactor, Matrix4, + MaxEquation, Mesh, OneFactor, Plane, @@ -24,13 +25,17 @@ export interface ShadowcatcherConfig { weights: { x: number; y: number; z: number; w: number } blurRadius: number stdDeviation: number + sigmoidRange: number + sigmoidStrength: number } export const DefaultShadowcatcherConfig: ShadowcatcherConfig = { textureSize: 512, weights: { x: 1, y: 1, z: 0, w: 1 }, blurRadius: 16, - stdDeviation: 4 + stdDeviation: 4, + sigmoidRange: 2, + sigmoidStrength: 2.43 } export class Shadowcatcher { @@ -60,22 +65,23 @@ export class Shadowcatcher { // this.displayMaterial.map.wrapS = RepeatWrapping // this.displayMaterial.map.repeat.x = -1 this.displayMaterial.map.needsUpdate = true - this.displayMaterial.transparent = true this.displayMaterial.toneMapped = false + this.displayMaterial.transparent = true this.displayMaterial.blending = CustomBlending this.displayMaterial.blendEquation = AddEquation - this.displayMaterial.blendEquationAlpha = AddEquation + this.displayMaterial.blendEquationAlpha = MaxEquation this.displayMaterial.blendSrc = ZeroFactor this.displayMaterial.blendSrcAlpha = OneFactor this.displayMaterial.blendDst = DstAlphaFactor - this.displayMaterial.blendDstAlpha = ZeroFactor + this.displayMaterial.blendDstAlpha = OneFactor + this.displayMaterial.alphaTest = 0.001 this.planeMesh = new Mesh() this.planeMesh.material = this.displayMaterial this.planeMesh.layers.set(layer) this.planeMesh.name = Shadowcatcher.MESH_NAME this.planeMesh.frustumCulled = false - this.planeMesh.renderOrder = layer + // this.planeMesh.renderOrder = layer } public update(scene: Scene) { diff --git a/packages/viewer/src/modules/SpeckleRenderer.ts b/packages/viewer/src/modules/SpeckleRenderer.ts index 0750b49b5..f9b55376f 100644 --- a/packages/viewer/src/modules/SpeckleRenderer.ts +++ b/packages/viewer/src/modules/SpeckleRenderer.ts @@ -510,6 +510,7 @@ export default class SpeckleRenderer { public removeRenderTree(subtreeId: string) { this.rootGroup.remove(this.rootGroup.getObjectByName(subtreeId)) + this.updateShadowCatcher() this.batcher.purgeBatches(subtreeId) this.updateDirectLights() diff --git a/packages/viewer/src/modules/materials/SpeckleShadowcatcherGenerateMaterial.ts b/packages/viewer/src/modules/materials/SpeckleShadowcatcherGenerateMaterial.ts deleted file mode 100644 index a83f09a8b..000000000 --- a/packages/viewer/src/modules/materials/SpeckleShadowcatcherGenerateMaterial.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable camelcase */ -import { speckleShadowcatcherGenerateVert } from './shaders/speckle-shadowcatcher-generate-vert' -import { speckleShadowcatcherGenerateFrag } from './shaders/speckle-shadowcatcher-generate-frag' -import { UniformsUtils, ShaderLib, Vector3 } from 'three' -import SpeckleBasicMaterial from './SpeckleBasicMaterial' - -class SpeckleShadowcatcherGenerateMaterial extends SpeckleBasicMaterial { - constructor(parameters, defines = []) { - super(parameters, defines) - this.userData.uViewer_high = { - value: new Vector3() - } - this.userData.uViewer_low = { - value: new Vector3() - } - ;(this as any).vertProgram = speckleShadowcatcherGenerateVert - ;(this as any).fragProgram = speckleShadowcatcherGenerateFrag - ;(this as any).uniforms = UniformsUtils.merge([ - ShaderLib.basic.uniforms, - { - uViewer_high: { - value: this.userData.uViewer_high.value - }, - uViewer_low: { - value: this.userData.uViewer_low.value - } - } - ]) - - this.onBeforeCompile = function (shader) { - shader.uniforms.uViewer_high = this.userData.uViewer_high - shader.uniforms.uViewer_low = this.userData.uViewer_low - shader.vertexShader = this.vertProgram - shader.fragmentShader = this.fragProgram - } - - if (defines) { - this.defines = {} - } - for (let k = 0; k < defines.length; k++) { - this.defines[defines[k]] = ' ' - } - } -} - -export default SpeckleShadowcatcherGenerateMaterial diff --git a/packages/viewer/src/modules/materials/SpeckleShadowcatcherMaterial.ts b/packages/viewer/src/modules/materials/SpeckleShadowcatcherMaterial.ts index b3aa34b31..bc9840776 100644 --- a/packages/viewer/src/modules/materials/SpeckleShadowcatcherMaterial.ts +++ b/packages/viewer/src/modules/materials/SpeckleShadowcatcherMaterial.ts @@ -4,7 +4,7 @@ import { speckleShadowcatcherVert } from './shaders/speckle-shadowcatcher-vert' import { speckleShadowcatcherFrag } from './shaders/speckle-shadowcatche-frag' import SpeckleBasicMaterial from './SpeckleBasicMaterial' -import { ShaderLib, UniformsUtils, Vector2, Vector3, Vector4 } from 'three' +import { ShaderLib, UniformsUtils, Vector3, Vector4 } from 'three' class SpeckleShadowcatcherMaterial extends SpeckleBasicMaterial { constructor(parameters, defines = []) { @@ -30,8 +30,11 @@ class SpeckleShadowcatcherMaterial extends SpeckleBasicMaterial { this.userData.weights = { value: new Vector4() } - this.userData.size = { - value: new Vector2() + this.userData.sigmoidRange = { + value: 0 + } + this.userData.sigmoidStrength = { + value: 0 } ;(this as any).vertProgram = speckleShadowcatcherVert ;(this as any).fragProgram = speckleShadowcatcherFrag @@ -59,8 +62,11 @@ class SpeckleShadowcatcherMaterial extends SpeckleBasicMaterial { weights: { value: this.userData.weights.value }, - size: { - value: this.userData.size.value + sigmoidRange: { + value: this.userData.sigmoidRange.value + }, + sigmoidStrength: { + value: this.userData.sigmoidStrength.value } } ]) @@ -73,7 +79,8 @@ class SpeckleShadowcatcherMaterial extends SpeckleBasicMaterial { shader.uniforms.tex2 = this.userData.tex2 shader.uniforms.tex3 = this.userData.tex3 shader.uniforms.weights = this.userData.weights - shader.uniforms.size = this.userData.size + shader.uniforms.sigmoidRange = this.userData.sigmoidRange + shader.uniforms.sigmoidStrength = this.userData.sigmoidStrength shader.vertexShader = this.vertProgram shader.fragmentShader = this.fragProgram } diff --git a/packages/viewer/src/modules/materials/shaders/speckle-shadowcatche-frag.ts b/packages/viewer/src/modules/materials/shaders/speckle-shadowcatche-frag.ts index 908a07c23..be582057d 100644 --- a/packages/viewer/src/modules/materials/shaders/speckle-shadowcatche-frag.ts +++ b/packages/viewer/src/modules/materials/shaders/speckle-shadowcatche-frag.ts @@ -6,51 +6,8 @@ uniform sampler2D tex1; uniform sampler2D tex2; uniform sampler2D tex3; uniform vec4 weights; -uniform sampler2D depth; -uniform vec2 size; -#include - -float getDepth( const in vec2 screenPosition ) { - // return unpackRGBAToDepth( texture2D( depth, screenPosition ) ); - return texture2D( depth, screenPosition ).x; -} - -float averageDepth() { - float du = 1./size.x; - float dv = 1./size.y; - - float d = getDepth(vUv + vec2(-2. * du, 2. * dv)); - d += getDepth(vUv + vec2(-1. * du, 2. * dv)); - d += getDepth(vUv + vec2(0., 2. * dv)); - d += getDepth(vUv + vec2(1. * du, 2. * dv)); - d += getDepth(vUv + vec2(2. * du, 2. * dv)); - - d += getDepth(vUv + vec2(-2. * du, 1. * dv)); - d += getDepth(vUv + vec2(-1. * du, 1. * dv)); - d += getDepth(vUv + vec2(0., 1. * dv)); - d += getDepth(vUv + vec2(1. * du, 1. * dv)); - d += getDepth(vUv + vec2(2. * du, 1. * dv)); - - d += getDepth(vUv + vec2(-2. * du, 0.)); - d += getDepth(vUv + vec2(-1. * du, 0.)); - d += getDepth(vUv + vec2(0., 0.)); - d += getDepth(vUv + vec2(1. * du, 0.)); - d += getDepth(vUv + vec2(2. * du, 0.)); - - d += getDepth(vUv + vec2(-2. * du, -1. * dv)); - d += getDepth(vUv + vec2(-1. * du, -1. * dv)); - d += getDepth(vUv + vec2(0., -1. * dv)); - d += getDepth(vUv + vec2(1. * du, -1. * dv)); - d += getDepth(vUv + vec2(2. * du, -1. * dv)); - - d += getDepth(vUv + vec2(-2. * du, -2. * dv)); - d += getDepth(vUv + vec2(-1. * du, -2. * dv)); - d += getDepth(vUv + vec2(0., -2. * dv)); - d += getDepth(vUv + vec2(1. * du, -2. * dv)); - d += getDepth(vUv + vec2(2. * du, -2. * dv)); - - return d/25.; -} +uniform float sigmoidRange; +uniform float sigmoidStrength; void main() { float color0 = texture2D(tex0, vUv).r * weights.x; @@ -58,22 +15,24 @@ void main() { float color2 = texture2D(tex2, vUv).r * weights.z; float color3 = texture2D(tex3, vUv).r * weights.w; - float d = averageDepth();//getDepth(vUv); + // float c0 = mix(color0, 0., color1); + // float c1 = mix(color1, 0., color0); + // float c2 = mix(color3, 0., color0 * 0.5 + color1 * 0.5); + // float sum = c0 + c1 + c2; - float c0 = mix(color0, 0., color1); - float c1 = mix(color1, 0., color0); - float c2 = mix(color3, 0., color0 * 0.5 + color1 * 0.5); - float sum = c0 + c1 + c2; + float sum = color0 + color1 + color3 + color2; + + float a = sigmoidRange;//2.; + float b = 0.03; + float c = sigmoidStrength;//2.43; + float d = 0.59; + float e = 0.14; + sum = clamp((sum*(a*sum+b))/(sum*(c*sum+d)+e), 0., 1.); vec2 sUv = vUv * 2. - 1.; - sum *= 1. - pow(sUv.x, 6.); - sum *= 1. - pow(sUv.y, 6.); - // float c0 = color0 + color1 + color2; - // float c1 = mix(color3, 0., c0); - // float sum = c0 + c1; + sum *= 1. - pow(abs(sUv.x), 6.); + sum *= 1. - pow(abs(sUv.y), 6.); - // float sum = color0+color1+color3; - gl_FragColor = vec4( vec3(sum), sum ); } ` diff --git a/packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-frag.ts b/packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-frag.ts deleted file mode 100644 index 0287fdaee..000000000 --- a/packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-frag.ts +++ /dev/null @@ -1,57 +0,0 @@ -export const speckleShadowcatcherGenerateFrag = /* glsl */ ` -uniform vec3 diffuse; -uniform float opacity; -#ifndef FLAT_SHADED - varying vec3 vNormal; -#endif -varying vec2 vAoData; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - #include - #include - #include - #include - #include - ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); - // accumulation (baked indirect lighting only) - #ifdef USE_LIGHTMAP - vec4 lightMapTexel = texture2D( lightMap, vUv2 ); - reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI; - #else - reflectedLight.indirectDiffuse += vec3( 1.0 ); - #endif - // modulation - #include - reflectedLight.indirectDiffuse *= diffuseColor.rgb; - vec3 outgoingLight = reflectedLight.indirectDiffuse; - #include - #include - vec3 aoColor = vec3(vAoData.xy, vAoData.x); - float aoAlpha = 1.; - gl_FragColor = vec4(aoColor, aoAlpha); - #include - #include - #include - #include - #include -} -` diff --git a/packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-vert.ts b/packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-vert.ts deleted file mode 100644 index 8d6a5cc89..000000000 --- a/packages/viewer/src/modules/materials/shaders/speckle-shadowcatcher-generate-vert.ts +++ /dev/null @@ -1,65 +0,0 @@ -export const speckleShadowcatcherGenerateVert = /* glsl */ ` -#include -#ifdef USE_RTE - // The high component is stored as the default 'position' attribute buffer - attribute vec3 position_low; - uniform vec3 uViewer_high; - uniform vec3 uViewer_low; -#endif -attribute vec2 aoData; -varying vec2 vAoData; -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING ) - #include - #include - #include - #include - #include - #endif - #include - #include - #include - // #include COMMENTED CHUNK - #ifdef USE_RTE - /* - Source https://github.com/virtualglobebook/OpenGlobe/blob/master/Source/Examples/Chapter05/Jitter/GPURelativeToEyeDSFUN90/Shaders/VS.glsl - Note here, we're storing the high part of the position encoding inside three's default 'position' attribute buffer so we avoid redundancy - */ - vec3 t1 = position_low.xyz - uViewer_low; - vec3 e = t1 - position_low.xyz; - vec3 t2 = ((-uViewer_low - e) + (position_low.xyz - (t1 - e))) + position.xyz - uViewer_high; - vec3 highDifference = t1 + t2; - vec3 lowDifference = t2 - (highDifference - t1); - vec4 mvPosition = vec4(highDifference.xyz + lowDifference.xyz , 1.); - #else - vec4 mvPosition = vec4( transformed, 1.0 ); - #endif - - #ifdef USE_INSTANCING - - mvPosition = instanceMatrix * mvPosition; - - #endif - mvPosition = modelViewMatrix * mvPosition; - vAoData = aoData; - gl_Position = projectionMatrix * mvPosition; - #include - #include - #include - #include - #include -} -` diff --git a/packages/viewer/src/modules/pipeline/ShadowcatcherPass.ts b/packages/viewer/src/modules/pipeline/ShadowcatcherPass.ts index d18c63a0a..4466a748d 100644 --- a/packages/viewer/src/modules/pipeline/ShadowcatcherPass.ts +++ b/packages/viewer/src/modules/pipeline/ShadowcatcherPass.ts @@ -191,9 +191,11 @@ export class ShadowcatcherPass extends BaseSpecklePass implements SpecklePass { const maxCameraFar = this.camera.far for (let k = 0; k < this.renderTargets.length; k++) { this.camera.far = maxCameraFar - if (k !== 3) { + if (k < 2) { this.camera.far = maxCameraFar / 100 - this.camera.updateProjectionMatrix() + } + if (k === 2) { + this.camera.far = maxCameraFar / 4 } this.camera.updateProjectionMatrix() @@ -258,9 +260,7 @@ export class ShadowcatcherPass extends BaseSpecklePass implements SpecklePass { this.renderTargets[0].width !== width || this.renderTargets[0].height !== height ) { - const depthSize = new Vector2(Math.ceil(width * 1), Math.ceil(height * 1)) this.outputTarget.setSize(width, height) - this.blendMaterial.userData.size.value = depthSize this.blendMaterial.needsUpdate = true let div = 1 for (let k = 0; k < this.renderTargets.length; k++) { @@ -302,6 +302,9 @@ export class ShadowcatcherPass extends BaseSpecklePass implements SpecklePass { public updateConfig(config: ShadowcatcherConfig) { this.blurRadius = config.blurRadius this.blurStdDev = config.stdDeviation + this.blendMaterial.userData.sigmoidRange.value = config.sigmoidRange + this.blendMaterial.userData.sigmoidStrength.value = config.sigmoidStrength + this.blendMaterial.needsUpdate = true } public setSize(width: number, height: number) {