From a75b89dd671a76a236aa90f6e4e8fd23d82b0f7f Mon Sep 17 00:00:00 2001 From: Alexandru Popovici Date: Mon, 20 Jan 2025 14:12:14 +0200 Subject: [PATCH] fix(viewer-lib): Handles WEB-2475. Shaded view mode no longer eats up cpu time on large streams (#3849) - FilteringExtension now emits the filtering state changed event when reseting the filtering state - BasitPass no longer applies the per vertex color indices each frame - ViewModes extension now listens for filtering state changes and have any active BasitPass reset it's color indices on a filtering reset event. Not great, not terrible but it avoids us having to double cache the per vertex color indices. --- packages/viewer-sandbox/src/main.ts | 3 +- .../modules/extensions/FilteringExtension.ts | 2 ++ .../src/modules/extensions/ViewModes.ts | 33 ++++++++++++++++++- .../src/modules/pipeline/Passes/BasitPass.ts | 4 +-- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/packages/viewer-sandbox/src/main.ts b/packages/viewer-sandbox/src/main.ts index b63965434..8abf6834a 100644 --- a/packages/viewer-sandbox/src/main.ts +++ b/packages/viewer-sandbox/src/main.ts @@ -113,7 +113,7 @@ const getStream = () => { // prettier-ignore // 'https://app.speckle.systems/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://app.speckle.systems/streams/da9e320dad/commits/5388ef24b8' + // 'https://app.speckle.systems/streams/da9e320dad/commits/5388ef24b8' // 'https://latest.speckle.systems/streams/c1faab5c62/commits/ab1a1ab2b6' // 'https://app.speckle.systems/streams/da9e320dad/commits/5388ef24b8' // 'https://latest.speckle.systems/streams/58b5648c4d/commits/60371ecb2d' @@ -469,6 +469,7 @@ const getStream = () => { // 'https://app.speckle.systems/projects/e89b61b65c/models/2a0995f124' // 'https://latest.speckle.systems/projects/3fe1880c36/models/65bb4287a8' + 'https://latest.speckle.systems/projects/db06488e1c/models/21f3930771' ) } diff --git a/packages/viewer/src/modules/extensions/FilteringExtension.ts b/packages/viewer/src/modules/extensions/FilteringExtension.ts index ad82dd8ac..c796467cd 100644 --- a/packages/viewer/src/modules/extensions/FilteringExtension.ts +++ b/packages/viewer/src/modules/extensions/FilteringExtension.ts @@ -417,7 +417,9 @@ export class FilteringExtension extends Extension { this.UserspaceColorState = null this.StateKey = undefined this.Renderer.resetMaterials() + this.CurrentFilteringState = {} this.viewer.requestRender(UpdateFlags.RENDER_RESET | UpdateFlags.SHADOWS) + this.emit(ViewerEvent.FilteringStateSet, this.CurrentFilteringState) return null } diff --git a/packages/viewer/src/modules/extensions/ViewModes.ts b/packages/viewer/src/modules/extensions/ViewModes.ts index 59ead1581..70eaffd6a 100644 --- a/packages/viewer/src/modules/extensions/ViewModes.ts +++ b/packages/viewer/src/modules/extensions/ViewModes.ts @@ -1,4 +1,6 @@ -import { UpdateFlags } from '../../IViewer.js' +import { IViewer, UpdateFlags, ViewerEvent } from '../../IViewer.js' +import { BasitPass } from '../pipeline/Passes/BasitPass.js' +import { GPass } from '../pipeline/Passes/GPass.js' import { ArcticViewPipeline } from '../pipeline/Pipelines/ArcticViewPipeline.js' import { BasitPipeline } from '../pipeline/Pipelines/BasitViewPipeline.js' import { DefaultPipeline } from '../pipeline/Pipelines/DefaultPipeline.js' @@ -9,6 +11,7 @@ import { MRTShadedViewPipeline } from '../pipeline/Pipelines/MRT/MRTShadedViewPi import { PenViewPipeline } from '../pipeline/Pipelines/PenViewPipeline.js' import { ShadedViewPipeline } from '../pipeline/Pipelines/ShadedViewPipeline.js' import { Extension } from './Extension.js' +import { FilteringExtension, FilteringState } from './FilteringExtension.js' export enum ViewMode { DEFAULT, @@ -28,6 +31,34 @@ export interface ViewModeEventPayload { } export class ViewModes extends Extension { + public get inject() { + return [FilteringExtension] + } + + public constructor( + viewer: IViewer, + protected filteringExtension: FilteringExtension + ) { + super(viewer) + /** Not a super fan of this, but it avoids us caching another set of per vertex color indices */ + if (filteringExtension) + filteringExtension.on(ViewerEvent.FilteringStateSet, (arg: FilteringState) => { + /** If no texture colored filters are present */ + if ( + (!arg.colorGroups || !arg.colorGroups.length) && + (!arg.userColorGroups || !arg.userColorGroups.length) + ) { + /** If any basit pass exists, set it's required color indices */ + this.viewer + .getRenderer() + .pipeline.getPass('BASIT') + .forEach((pass: GPass) => { + ;(pass as BasitPass).applyColorIndices() + }) + } + }) + } + public on( eventType: T, listener: (arg: ViewModeEventPayload[T]) => void diff --git a/packages/viewer/src/modules/pipeline/Passes/BasitPass.ts b/packages/viewer/src/modules/pipeline/Passes/BasitPass.ts index 2bdf9f89b..02ccc68ed 100644 --- a/packages/viewer/src/modules/pipeline/Passes/BasitPass.ts +++ b/packages/viewer/src/modules/pipeline/Passes/BasitPass.ts @@ -33,6 +33,7 @@ export class BasitPass extends BaseGPass { this.tree = tree this.speckleRenderer = renderer this.buildMaterials() + this.applyColorIndices() } public get displayName(): string { @@ -82,7 +83,7 @@ export class BasitPass extends BaseGPass { } } - protected applyColorIndices() { + public applyColorIndices() { for (const item in this.materialMap) { const batch = this.materialMap[item][0] const colorMap = this.materialMap[item][1] @@ -131,7 +132,6 @@ export class BasitPass extends BaseGPass { ): boolean { if (!camera || !scene) return false - this.applyColorIndices() this.overrideMaterials() if (this.onBeforeRender) this.onBeforeRender()