From b99a4afb180dba92dc099d495acca679c7e249bb Mon Sep 17 00:00:00 2001 From: AlexandruPopovici Date: Thu, 8 Sep 2022 12:53:34 +0300 Subject: [PATCH] fix: fixed #987 Fixed #987 and an additonal issue with null clipping planes #987 --- .../viewer/src/modules/SpeckleRenderer.ts | 5 +- .../viewer/src/modules/batching/Batcher.ts | 7 ++- .../viewer/src/modules/materials/Materials.ts | 34 +++++++--- .../modules/materials/SpeckleGhostMaterial.ts | 10 ++- .../materials/shaders/speckle-depth-frag.ts | 11 +++- .../materials/shaders/speckle-ghost-frag.ts | 54 ++++++++++++++++ .../materials/shaders/speckle-ghost-vert.ts | 63 +++++++++++++++++++ 7 files changed, 164 insertions(+), 20 deletions(-) create mode 100644 packages/viewer/src/modules/materials/shaders/speckle-ghost-frag.ts create mode 100644 packages/viewer/src/modules/materials/shaders/speckle-ghost-vert.ts diff --git a/packages/viewer/src/modules/SpeckleRenderer.ts b/packages/viewer/src/modules/SpeckleRenderer.ts index 4e9271272..c206db6d9 100644 --- a/packages/viewer/src/modules/SpeckleRenderer.ts +++ b/packages/viewer/src/modules/SpeckleRenderer.ts @@ -126,7 +126,7 @@ export default class SpeckleRenderer { this._renderer.toneMappingExposure = 0.5 this.renderer.shadowMap.enabled = true this.renderer.shadowMap.type = VSMShadowMap - this.renderer.shadowMap.autoUpdate = true + this.renderer.shadowMap.autoUpdate = false this.renderer.shadowMap.needsUpdate = true this.renderer.physicallyCorrectLights = true @@ -277,7 +277,7 @@ export default class SpeckleRenderer { { depthPacking: RGBADepthPacking }, - ['USE_RTE'] + ['USE_RTE', 'ALPHATEST_REJECTION'] ) } }) @@ -327,6 +327,7 @@ export default class SpeckleRenderer { } } }) + this.renderer.shadowMap.needsUpdate = true } private addDirectLights() { diff --git a/packages/viewer/src/modules/batching/Batcher.ts b/packages/viewer/src/modules/batching/Batcher.ts index 0e1fb7c31..3c9848788 100644 --- a/packages/viewer/src/modules/batching/Batcher.ts +++ b/packages/viewer/src/modules/batching/Batcher.ts @@ -8,7 +8,7 @@ import { NodeRenderView } from '../tree/NodeRenderView' import { Batch, BatchUpdateRange, GeometryType, HideAllBatchUpdateRange } from './Batch' import PointBatch from './PointBatch' // import { FilterMaterialType } from '../FilteringManager' -import { WebGLRenderer } from 'three' +import { Material, WebGLRenderer } from 'three' import { FilterMaterial, FilterMaterialType } from '../filtering/FilteringManager' export default class Batcher { @@ -157,7 +157,10 @@ export default class Batcher { return { offset: rv.batchStart, count: rv.batchCount, - material: this.materials.getFilterMaterial(rv, filterMaterial.filterType), + material: this.materials.getFilterMaterial( + rv, + filterMaterial.filterType + ) as Material, materialOptions: this.materials.getFilterMaterialOptions(filterMaterial) } as BatchUpdateRange }) diff --git a/packages/viewer/src/modules/materials/Materials.ts b/packages/viewer/src/modules/materials/Materials.ts index d93c289e7..8c5dd3d6d 100644 --- a/packages/viewer/src/modules/materials/Materials.ts +++ b/packages/viewer/src/modules/materials/Materials.ts @@ -132,6 +132,7 @@ export default class Materials { ['USE_RTE'] ) this.meshGhostMaterial.depthWrite = false + this.meshGhostMaterial.alphaTest = 1 this.meshGradientMaterial = new SpeckleStandardColoredMaterial( { @@ -196,7 +197,8 @@ export default class Materials { emissive: 0x0, roughness: 1, metalness: 0, - side: DoubleSide // TBD + side: DoubleSide // TBD, + // clippingPlanes: [] }, ['USE_RTE'] ) @@ -563,6 +565,10 @@ export default class Materials { break } } + /** There's a bug in three.js where it checks for the length of the planes without checking if they exist first + * It's been allegedly fixed in a later version but until we update we'll just assing an empty array + */ + this.materialMap[hash].clippingPlanes = [] return this.materialMap[hash] } @@ -712,21 +718,33 @@ export default class Materials { public getFilterMaterial( renderView: NodeRenderView, filterMaterial: FilterMaterialType - ) { + ): Material { + let retMaterial: Material switch (filterMaterial) { case FilterMaterialType.SELECT: - return this.getHighlightMaterial(renderView) + retMaterial = this.getHighlightMaterial(renderView) + break case FilterMaterialType.GHOST: - return this.getGhostMaterial(renderView) + retMaterial = this.getGhostMaterial(renderView) + break case FilterMaterialType.GRADIENT: - return this.getGradientMaterial(renderView) + retMaterial = this.getGradientMaterial(renderView) + break case FilterMaterialType.COLORED: - return this.getColoredMaterial(renderView) + retMaterial = this.getColoredMaterial(renderView) + break case FilterMaterialType.OVERLAY: - return this.getOverlayMaterial(renderView) + retMaterial = this.getOverlayMaterial(renderView) + break case FilterMaterialType.HIDDEN: - return this.getHiddenMaterial(renderView) + retMaterial = this.getHiddenMaterial(renderView) + break } + /** There's a bug in three.js where it checks for the length of the planes without checking if they exist first + * It's been allegedly fixed in a later version but until we update we'll just assing an empty array + */ + retMaterial.clippingPlanes = [] + return retMaterial } public getFilterMaterialOptions(filterMaterial: FilterMaterial) { diff --git a/packages/viewer/src/modules/materials/SpeckleGhostMaterial.ts b/packages/viewer/src/modules/materials/SpeckleGhostMaterial.ts index e94a74971..5941177b0 100644 --- a/packages/viewer/src/modules/materials/SpeckleGhostMaterial.ts +++ b/packages/viewer/src/modules/materials/SpeckleGhostMaterial.ts @@ -2,8 +2,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable camelcase */ import { Matrix4, ShaderLib, UniformsUtils, Vector3 } from 'three' -import { speckleBasicVert } from './shaders/speckle-basic-vert' -import { speckleBasicFrag } from './shaders/speckle-basic-frag' +import { speckleGhostVert } from './shaders/speckle-ghost-vert' +import { speckleGhostFrag } from './shaders/speckle-ghost-frag' import SpeckleBasicMaterial from './SpeckleBasicMaterial' class SpeckleGhostMaterial extends SpeckleBasicMaterial { @@ -15,8 +15,8 @@ class SpeckleGhostMaterial extends SpeckleBasicMaterial { this.userData.uViewer_low = { value: new Vector3() } - ;(this as any).vertProgram = speckleBasicVert - ;(this as any).fragProgram = speckleBasicFrag + ;(this as any).vertProgram = speckleGhostVert + ;(this as any).fragProgram = speckleGhostFrag ;(this as any).uniforms = UniformsUtils.merge([ ShaderLib.standard.uniforms, { @@ -42,8 +42,6 @@ class SpeckleGhostMaterial extends SpeckleBasicMaterial { for (let k = 0; k < defines.length; k++) { this.defines[defines[k]] = ' ' } - - this.defines['NO_SHADOWS'] = '' } } diff --git a/packages/viewer/src/modules/materials/shaders/speckle-depth-frag.ts b/packages/viewer/src/modules/materials/shaders/speckle-depth-frag.ts index 15f41f665..3d5ac0417 100644 --- a/packages/viewer/src/modules/materials/shaders/speckle-depth-frag.ts +++ b/packages/viewer/src/modules/materials/shaders/speckle-depth-frag.ts @@ -19,10 +19,17 @@ void main() { #endif #include #include - #include + // #include + #ifdef USE_ALPHATEST + if ( diffuseColor.a < alphaTest ) discard; + /** This is a workaround for rejecting shadows for certain materials, since three.js gave me no choice*/ + #ifdef ALPHATEST_REJECTION + if (alphaTest > 0. ) discard; + #endif + #endif #include // Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values. - float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5; + float fragCoordZ = (0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5); #if DEPTH_PACKING == 3200 gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity ); #elif DEPTH_PACKING == 3201 diff --git a/packages/viewer/src/modules/materials/shaders/speckle-ghost-frag.ts b/packages/viewer/src/modules/materials/shaders/speckle-ghost-frag.ts new file mode 100644 index 000000000..ac0eb7d5b --- /dev/null +++ b/packages/viewer/src/modules/materials/shaders/speckle-ghost-frag.ts @@ -0,0 +1,54 @@ +export const speckleGhostFrag = /* glsl */ ` +uniform vec3 diffuse; +uniform float opacity; +#ifndef FLAT_SHADED + varying vec3 vNormal; +#endif +#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 + // We're disabling alpha testing because we need to use it for shadow rejection. Three.js gave me no choice + // #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 + #include + #include + #include + #include + #include +} +` diff --git a/packages/viewer/src/modules/materials/shaders/speckle-ghost-vert.ts b/packages/viewer/src/modules/materials/shaders/speckle-ghost-vert.ts new file mode 100644 index 000000000..00380bf54 --- /dev/null +++ b/packages/viewer/src/modules/materials/shaders/speckle-ghost-vert.ts @@ -0,0 +1,63 @@ +export const speckleGhostVert = /* 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 +#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; + + gl_Position = projectionMatrix * mvPosition; + #include + #include + #include + #include + #include +} +`