Skip to content

Commit

Permalink
Feature - adaptive downsampling of volume rendering based on framerate (
Browse files Browse the repository at this point in the history
  • Loading branch information
seankmartin authored Jul 3, 2024
1 parent b0d3291 commit c9081c0
Show file tree
Hide file tree
Showing 14 changed files with 652 additions and 36 deletions.
4 changes: 4 additions & 0 deletions python/neuroglancer/viewer_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -1668,6 +1668,10 @@ class ViewerState(JsonObjectWrapper):
show_axis_lines = showAxisLines = wrapped_property(
"showAxisLines", optional(bool, True)
)
wire_frame = wireFrame = wrapped_property("wireFrame", optional(bool, False))
enable_adaptive_downsampling = enableAdaptiveDownsampling = wrapped_property(
"enableAdaptiveDownsampling", optional(bool, True)
)
show_scale_bar = showScaleBar = wrapped_property(
"showScaleBar", optional(bool, True)
)
Expand Down
2 changes: 2 additions & 0 deletions src/data_panel_layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export interface ViewerUIState
showPerspectiveSliceViews: TrackableBoolean;
showAxisLines: TrackableBoolean;
wireFrame: TrackableBoolean;
enableAdaptiveDownsampling: TrackableBoolean;
showScaleBar: TrackableBoolean;
scaleBarOptions: TrackableValue<ScaleBarOptions>;
visibleLayerRoles: WatchableSet<RenderLayerRole>;
Expand Down Expand Up @@ -174,6 +175,7 @@ export function getCommonViewerState(viewer: ViewerUIState) {
layerManager: viewer.layerManager,
showAxisLines: viewer.showAxisLines,
wireFrame: viewer.wireFrame,
enableAdaptiveDownsampling: viewer.enableAdaptiveDownsampling,
visibleLayerRoles: viewer.visibleLayerRoles,
selectedLayer: viewer.selectedLayer,
visibility: viewer.visibility,
Expand Down
37 changes: 37 additions & 0 deletions src/display_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@
* limitations under the License.
*/

import { debounce } from "lodash-es";

import type { FrameNumberCounter } from "#src/chunk_manager/frontend.js";
import { TrackableValue } from "#src/trackable_value.js";
import { animationFrameDebounce } from "#src/util/animation_frame_debounce.js";
import type { Borrowed } from "#src/util/disposable.js";
import { RefCounted } from "#src/util/disposable.js";
import { FramerateMonitor } from "#src/util/framerate.js";
import type { mat4 } from "#src/util/geom.js";
import { parseFixedLengthArray, verifyFloat01 } from "#src/util/json.js";
import { NullarySignal } from "#src/util/signal.js";
import type { WatchableVisibilityPriority } from "#src/visibility_priority/frontend.js";
import type { GL } from "#src/webgl/context.js";
import { initializeWebGL } from "#src/webgl/context.js";

const DELAY_AFTER_CONTINUOUS_CAMERA_MOTION_MS = 300;

export class RenderViewport {
// Width of visible portion of panel in canvas pixels.
width = 0;
Expand Down Expand Up @@ -390,12 +395,17 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
gl: GL;
updateStarted = new NullarySignal();
updateFinished = new NullarySignal();
continuousCameraMotionStarted = new NullarySignal();
continuousCameraMotionFinished = new NullarySignal();
changed = this.updateFinished;
panels = new Set<RenderedPanel>();
canvasRect: DOMRect | undefined;
rootRect: DOMRect | undefined;
resizeGeneration = 0;
boundsGeneration = -1;
private framerateMonitor = new FramerateMonitor();

private continuousCameraMotionInProgress = false;

// Panels ordered by `drawOrder`. If length is 0, needs to be recomputed.
private orderedPanels: RenderedPanel[] = [];
Expand Down Expand Up @@ -447,6 +457,25 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {

private resizeObserver = new ResizeObserver(this.resizeCallback);

private debouncedEndContinuousCameraMotion = this.registerCancellable(
debounce(() => {
this.continuousCameraMotionInProgress = false;
this.continuousCameraMotionFinished.dispatch();
}, DELAY_AFTER_CONTINUOUS_CAMERA_MOTION_MS),
);

flagContinuousCameraMotion() {
if (!this.continuousCameraMotionInProgress) {
this.continuousCameraMotionStarted.dispatch();
}
this.continuousCameraMotionInProgress = true;
this.debouncedEndContinuousCameraMotion();
}

get isContinuousCameraMotionInProgress() {
return this.continuousCameraMotionInProgress;
}

constructor(public container: HTMLElement) {
super();
const { canvas, resizeObserver } = this;
Expand Down Expand Up @@ -557,6 +586,8 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
++this.frameNumber;
this.updateStarted.dispatch();
const gl = this.gl;
const ext = this.framerateMonitor.getTimingExtension(gl);
const query = this.framerateMonitor.startFrameTimeQuery(gl, ext);
this.ensureBoundsUpdated();
this.gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
Expand All @@ -580,6 +611,8 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
gl.clear(gl.COLOR_BUFFER_BIT);
this.gl.colorMask(true, true, true, true);
this.updateFinished.dispatch();
this.framerateMonitor.endFrameTimeQuery(gl, ext, query);
this.framerateMonitor.grabAnyFinishedQueryResults(gl);
}

getDepthArray(): Float32Array {
Expand Down Expand Up @@ -607,4 +640,8 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
}
return depthArray;
}

getLastFrameTimesInMs(numberOfFrames: number = 10) {
return this.framerateMonitor.getLastFrameTimesInMs(numberOfFrames);
}
}
4 changes: 4 additions & 0 deletions src/layer_group_viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export interface LayerGroupViewerState {
mouseState: MouseSelectionState;
showAxisLines: TrackableBoolean;
wireFrame: TrackableBoolean;
enableAdaptiveDownsampling: TrackableBoolean;
showScaleBar: TrackableBoolean;
scaleBarOptions: TrackableScaleBarOptions;
showPerspectiveSliceViews: TrackableBoolean;
Expand Down Expand Up @@ -356,6 +357,9 @@ export class LayerGroupViewer extends RefCounted {
get wireFrame() {
return this.viewerState.wireFrame;
}
get enableAdaptiveDownsampling() {
return this.viewerState.enableAdaptiveDownsampling;
}
get showScaleBar() {
return this.viewerState.showScaleBar;
}
Expand Down
1 change: 1 addition & 0 deletions src/layer_groups_layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ function getCommonViewerState(viewer: Viewer) {
mouseState: viewer.mouseState,
showAxisLines: viewer.showAxisLines,
wireFrame: viewer.wireFrame,
enableAdaptiveDownsampling: viewer.enableAdaptiveDownsampling,
showScaleBar: viewer.showScaleBar,
scaleBarOptions: viewer.scaleBarOptions,
showPerspectiveSliceViews: viewer.showPerspectiveSliceViews,
Expand Down
Loading

0 comments on commit c9081c0

Please sign in to comment.