@@ -196,17 +196,17 @@ v4f_fragColor = vec4(accum.rgb / accum.a, revealage);
196196` ) ;
197197}
198198
199- // Copy the depth from opaque pass to the depth buffer for OIT.
200- // This copy is required because the OIT depth buffer might be
201- // smaller than the main depth buffer.
202- function defineDepthCopyShader ( builder : ShaderBuilder ) {
199+ function defineTransparentToTransparentCopyShader ( builder : ShaderBuilder ) {
203200 builder . addOutputBuffer ( "vec4" , "v4f_fragData0" , 0 ) ;
204201 builder . addOutputBuffer ( "vec4" , "v4f_fragData1" , 1 ) ;
202+ builder . addFragmentCode ( glsl_perspectivePanelEmitOIT ) ;
205203 builder . setFragmentMain ( `
206- v4f_fragData0 = vec4(0.0, 0.0, 0.0, 1.0);
207- v4f_fragData1 = vec4(0.0, 0.0, 0.0, 1.0);
208- vec4 v0 = getValue0();
209- gl_FragDepth = 1.0 - v0.r;
204+ vec4 v0 = getValue0();
205+ vec4 v1 = getValue1();
206+ vec4 accum = vec4(v0.rgb, v1.r);
207+ float revealage = v0.a;
208+
209+ emitAccumAndRevealage(accum, 1.0 - revealage, 0u);
210210` ) ;
211211}
212212
@@ -276,6 +276,7 @@ export class PerspectivePanel extends RenderedDataPanel {
276276 protected visibleLayerTracker : Owned <
277277 VisibleRenderLayerTracker < PerspectivePanel , PerspectiveViewRenderLayer >
278278 > ;
279+ private hasVolumeRendering = false ;
279280
280281 get rpc ( ) {
281282 return this . sharedObject . rpc ! ;
@@ -293,20 +294,18 @@ export class PerspectivePanel extends RenderedDataPanel {
293294 // to avoid flickering when the camera is moving
294295 private frameRateCalculator = new DownsamplingBasedOnFrameRateCalculator (
295296 6 /* numberOfStoredFrameDeltas */ ,
296- 4 /* maxDownsamplingFactor */ ,
297+ 8 /* maxDownsamplingFactor */ ,
297298 8 /* desiredFrameTimingMs */ ,
298299 60 /* downsamplingPersistenceDurationInFrames */ ,
299300 ) ;
300- private isCameraInContinuousMotion = false ;
301+ private isContinuousCameraMotionInProgress = false ;
301302 get shouldDownsample ( ) {
302303 return (
303304 this . viewer . enableAdaptiveDownsampling . value &&
304- this . isCameraInContinuousMotion &&
305+ this . isContinuousCameraMotionInProgress &&
305306 this . hasVolumeRendering
306307 ) ;
307308 }
308- private hasVolumeRendering = false ;
309- private hasTransparent = false ;
310309
311310 /**
312311 * If boolean value is true, sliceView is shown unconditionally, regardless of the value of
@@ -374,12 +373,16 @@ export class PerspectivePanel extends RenderedDataPanel {
374373 protected transparencyCopyHelper = this . registerDisposer (
375374 OffscreenCopyHelper . get ( this . gl , defineTransparencyCopyShader , 2 ) ,
376375 ) ;
376+ protected transparentToTransparentCopyHelper = this . registerDisposer (
377+ OffscreenCopyHelper . get (
378+ this . gl ,
379+ defineTransparentToTransparentCopyShader ,
380+ 2 ,
381+ ) ,
382+ ) ;
377383 protected maxProjectionColorCopyHelper = this . registerDisposer (
378384 OffscreenCopyHelper . get ( this . gl , defineMaxProjectionColorCopyShader , 2 ) ,
379385 ) ;
380- protected offscreenDepthCopyHelper = this . registerDisposer (
381- OffscreenCopyHelper . get ( this . gl , defineDepthCopyShader , 1 ) ,
382- ) ;
383386 protected maxProjectionPickCopyHelper = this . registerDisposer (
384387 OffscreenCopyHelper . get ( this . gl , defineMaxProjectionPickCopyShader , 2 ) ,
385388 ) ;
@@ -472,7 +475,7 @@ export class PerspectivePanel extends RenderedDataPanel {
472475
473476 this . registerDisposer (
474477 this . context . continuousCameraMotionFinished . add ( ( ) => {
475- this . isCameraInContinuousMotion = false ;
478+ this . isContinuousCameraMotionInProgress = false ;
476479 if ( this . hasVolumeRendering ) {
477480 this . scheduleRedraw ( ) ;
478481 this . frameRateCalculator . resetForNewFrameSet ( ) ;
@@ -481,7 +484,7 @@ export class PerspectivePanel extends RenderedDataPanel {
481484 ) ;
482485 this . registerDisposer (
483486 this . context . continuousCameraMotionStarted . add ( ( ) => {
484- this . isCameraInContinuousMotion = true ;
487+ this . isContinuousCameraMotionInProgress = true ;
485488 } ) ,
486489 ) ;
487490
@@ -995,7 +998,7 @@ export class PerspectivePanel extends RenderedDataPanel {
995998 frameNumber : this . context . frameNumber ,
996999 sliceViewsPresent : this . sliceViews . size > 0 ,
9971000 isContinuousCameraMotionInProgress :
998- this . context . isContinuousCameraMotionInProgress ,
1001+ this . isContinuousCameraMotionInProgress ,
9991002 } ;
10001003
10011004 mat4 . copy (
@@ -1005,8 +1008,8 @@ export class PerspectivePanel extends RenderedDataPanel {
10051008
10061009 const { visibleLayers } = this . visibleLayerTracker ;
10071010
1008- this . hasTransparent = false ;
1009- let hasMaxProjection = false ;
1011+ let hasTransparent = false ;
1012+ let hasVolumeRenderingPick = false ;
10101013 let hasAnnotation = false ;
10111014 let hasVolumeRendering = false ;
10121015
@@ -1019,11 +1022,14 @@ export class PerspectivePanel extends RenderedDataPanel {
10191022 hasAnnotation = true ;
10201023 }
10211024 } else {
1022- this . hasTransparent = true ;
1025+ hasTransparent = true ;
10231026 if ( renderLayer . isVolumeRendering ) {
10241027 hasVolumeRendering = true ;
1025- hasMaxProjection =
1026- hasMaxProjection ||
1028+ // Volume rendering layers are not pickable when the camera is moving.
1029+ // Unless the layer is a projection layer.
1030+ hasVolumeRenderingPick =
1031+ hasVolumeRenderingPick ||
1032+ ! this . isContinuousCameraMotionInProgress ||
10271033 isProjectionLayer ( renderLayer as VolumeRenderingRenderLayer ) ;
10281034 }
10291035 }
@@ -1070,7 +1076,7 @@ export class PerspectivePanel extends RenderedDataPanel {
10701076 /*dppass=*/ WebGL2RenderingContext . KEEP ,
10711077 ) ;
10721078
1073- if ( this . hasTransparent ) {
1079+ if ( hasTransparent ) {
10741080 //Draw transparent objects.
10751081
10761082 let volumeRenderingBufferWidth = width ;
@@ -1095,10 +1101,13 @@ export class PerspectivePanel extends RenderedDataPanel {
10951101 }
10961102 }
10971103
1098- // Create max projection buffer if needed .
1104+ // Create volume rendering related buffers .
10991105 let bindMaxProjectionBuffer : ( ) => void = ( ) => { } ;
11001106 let bindMaxProjectionPickingBuffer : ( ) => void = ( ) => { } ;
1101- if ( hasMaxProjection ) {
1107+ let bindVolumeRenderingBuffer : ( ) => void = ( ) => { } ;
1108+ if ( this . hasVolumeRendering ) {
1109+ // Max projection setup
1110+ renderContext . maxProjectionEmit = maxProjectionEmit ;
11021111 const { maxProjectionConfiguration } = this ;
11031112 bindMaxProjectionBuffer = ( ) => {
11041113 maxProjectionConfiguration . bind (
@@ -1116,6 +1125,7 @@ export class PerspectivePanel extends RenderedDataPanel {
11161125 WebGL2RenderingContext . DEPTH_BUFFER_BIT ,
11171126 ) ;
11181127
1128+ // Max projection picking setup
11191129 const { maxProjectionPickConfiguration } = this ;
11201130 bindMaxProjectionPickingBuffer = ( ) => {
11211131 maxProjectionPickConfiguration . bind (
@@ -1128,28 +1138,22 @@ export class PerspectivePanel extends RenderedDataPanel {
11281138 WebGL2RenderingContext . COLOR_BUFFER_BIT |
11291139 WebGL2RenderingContext . DEPTH_BUFFER_BIT ,
11301140 ) ;
1131- }
11321141
1133- let bindVolumeRenderingBuffer : ( ) => void = ( ) => { } ;
1134- if ( hasVolumeRendering ) {
1142+ // Volume rendering setup
11351143 bindVolumeRenderingBuffer = ( ) => {
11361144 this . volumeRenderingConfiguration . bind (
11371145 volumeRenderingBufferWidth ,
11381146 volumeRenderingBufferHeight ,
11391147 ) ;
11401148 } ;
11411149 bindVolumeRenderingBuffer ( ) ;
1142- // Copy the depth buffer from the offscreen framebuffer to the volume rendering framebuffer.
1143- gl . depthMask ( true ) ;
1150+ renderContext . bindVolumeRenderingBuffer = bindVolumeRenderingBuffer ;
11441151 gl . clearDepth ( 1.0 ) ;
11451152 gl . clearColor ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
11461153 gl . clear (
11471154 WebGL2RenderingContext . COLOR_BUFFER_BIT |
11481155 WebGL2RenderingContext . DEPTH_BUFFER_BIT ,
11491156 ) ;
1150- this . offscreenDepthCopyHelper . draw (
1151- this . offscreenFramebuffer . colorBuffers [ OffscreenTextures . Z ] . texture ,
1152- ) ;
11531157 }
11541158
11551159 const { transparentConfiguration } = this ;
@@ -1174,30 +1178,58 @@ export class PerspectivePanel extends RenderedDataPanel {
11741178 let currentTransparentRenderingState =
11751179 TransparentRenderingState . TRANSPARENT ;
11761180 for ( const [ renderLayer , attachment ] of visibleLayers ) {
1177- if ( renderLayer . isTransparent ) {
1181+ if ( renderLayer . isVolumeRendering ) {
11781182 renderContext . depthBufferTexture =
11791183 this . offscreenFramebuffer . colorBuffers [ OffscreenTextures . Z ] . texture ;
1180- }
1181- // Draw max projection layers
1182- if (
1183- renderLayer . isVolumeRendering &&
1184- isProjectionLayer ( renderLayer as VolumeRenderingRenderLayer )
1185- ) {
1186- // Set state for max projection mode and draw
1187- gl . depthMask ( true ) ;
1188- gl . disable ( WebGL2RenderingContext . BLEND ) ;
1189- gl . depthFunc ( WebGL2RenderingContext . GREATER ) ;
11901184
1191- if (
1192- currentTransparentRenderingState !==
1193- TransparentRenderingState . MAX_PROJECTION
1194- ) {
1195- renderContext . emitter = maxProjectionEmit ;
1196- bindMaxProjectionBuffer ( ) ;
1185+ const isVolumeProjectionLayer = isProjectionLayer (
1186+ renderLayer as VolumeRenderingRenderLayer ,
1187+ ) ;
1188+ const needsSecondPickingPass =
1189+ ! isVolumeProjectionLayer &&
1190+ ! this . isContinuousCameraMotionInProgress &&
1191+ ! renderContext . wireFrame ;
1192+
1193+ // Bind the appropriate buffer and set state
1194+ if ( isVolumeProjectionLayer ) {
1195+ gl . depthMask ( true ) ;
1196+ gl . disable ( WebGL2RenderingContext . BLEND ) ;
1197+ gl . depthFunc ( WebGL2RenderingContext . GREATER ) ;
1198+ if (
1199+ currentTransparentRenderingState !==
1200+ TransparentRenderingState . MAX_PROJECTION
1201+ ) {
1202+ renderContext . emitter = maxProjectionEmit ;
1203+ bindMaxProjectionBuffer ( ) ;
1204+ }
1205+ } else {
1206+ if (
1207+ currentTransparentRenderingState !==
1208+ TransparentRenderingState . VOLUME_RENDERING
1209+ ) {
1210+ renderContext . emitter = perspectivePanelEmitOIT ;
1211+ bindVolumeRenderingBuffer ( ) ;
1212+ }
1213+ gl . disable ( WebGL2RenderingContext . DEPTH_TEST ) ;
1214+ currentTransparentRenderingState =
1215+ TransparentRenderingState . VOLUME_RENDERING ;
11971216 }
1217+
1218+ // Two cases for volume rendering layers
1219+ // Either way, a draw call is needed first
11981220 renderLayer . draw ( renderContext , attachment ) ;
1221+ gl . enable ( WebGL2RenderingContext . DEPTH_TEST ) ;
11991222
1200- // Copy max projection result to picking buffer
1223+ // Case 1 - No picking pass needed and not a projection layer
1224+ // we already have the color information, so we skip the max projection pass
1225+ if ( ! needsSecondPickingPass && ! isVolumeProjectionLayer ) {
1226+ continue ;
1227+ }
1228+
1229+ // Case 2 - Picking will be computed from a max projection
1230+ // And a second pass may be needed to do this picking
1231+
1232+ // Copy the volume rendering picking result to the main picking buffer
12011233 // Depth testing on to combine max layers into one pick buffer via depth
12021234 bindMaxProjectionPickingBuffer ( ) ;
12031235 this . maxProjectionToPickCopyHelper . draw (
@@ -1207,25 +1239,30 @@ export class PerspectivePanel extends RenderedDataPanel {
12071239 this . maxProjectionConfiguration . colorBuffers [ 3 /*pick*/ ] . texture ,
12081240 ) ;
12091241
1210- // Copy max projection color result to the transparent buffer with OIT
1211- // Depth testing off to combine max layers into one color via blend
1212- bindVolumeRenderingBuffer ( ) ;
1213- gl . depthMask ( false ) ;
1214- gl . disable ( WebGL2RenderingContext . DEPTH_TEST ) ;
1242+ // Turn back on OIT blending
12151243 gl . enable ( WebGL2RenderingContext . BLEND ) ;
12161244 gl . blendFuncSeparate (
12171245 WebGL2RenderingContext . ONE ,
12181246 WebGL2RenderingContext . ONE ,
12191247 WebGL2RenderingContext . ZERO ,
12201248 WebGL2RenderingContext . ONE_MINUS_SRC_ALPHA ,
12211249 ) ;
1222- this . maxProjectionColorCopyHelper . draw (
1223- this . maxProjectionConfiguration . colorBuffers [ 0 /*color*/ ] . texture ,
1224- this . maxProjectionConfiguration . colorBuffers [ 1 /*depth*/ ] . texture ,
1225- ) ;
12261250
1227- // Reset the max projection buffer
1251+ // Copy max projection color result to the transparent buffer with OIT
1252+ // Depth testing off to combine max layers into one color via blending
1253+ if ( isVolumeProjectionLayer ) {
1254+ bindVolumeRenderingBuffer ( ) ;
1255+ gl . depthMask ( false ) ;
1256+ gl . disable ( WebGL2RenderingContext . DEPTH_TEST ) ;
1257+ this . maxProjectionColorCopyHelper . draw (
1258+ this . maxProjectionConfiguration . colorBuffers [ 0 /*color*/ ] . texture ,
1259+ this . maxProjectionConfiguration . colorBuffers [ 1 /*depth*/ ] . texture ,
1260+ ) ;
1261+ }
1262+
1263+ // Reset the max projection color, depth, and picking buffer
12281264 bindMaxProjectionBuffer ( ) ;
1265+ renderContext . emitter = maxProjectionEmit ;
12291266 gl . depthMask ( true ) ;
12301267 gl . clearColor ( 0.0 , 0.0 , 0.0 , 0.0 ) ;
12311268 gl . clearDepth ( 0.0 ) ;
@@ -1234,7 +1271,7 @@ export class PerspectivePanel extends RenderedDataPanel {
12341271 WebGL2RenderingContext . DEPTH_BUFFER_BIT ,
12351272 ) ;
12361273
1237- // Set back to non-max projection state
1274+ // Set some values back to non-max projection state
12381275 gl . clearDepth ( 1.0 ) ;
12391276 gl . clearColor ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
12401277 gl . depthMask ( false ) ;
@@ -1243,17 +1280,6 @@ export class PerspectivePanel extends RenderedDataPanel {
12431280
12441281 currentTransparentRenderingState =
12451282 TransparentRenderingState . MAX_PROJECTION ;
1246- } else if ( renderLayer . isVolumeRendering ) {
1247- if (
1248- currentTransparentRenderingState !==
1249- TransparentRenderingState . VOLUME_RENDERING
1250- ) {
1251- renderContext . emitter = perspectivePanelEmitOIT ;
1252- bindVolumeRenderingBuffer ( ) ;
1253- }
1254- currentTransparentRenderingState =
1255- TransparentRenderingState . VOLUME_RENDERING ;
1256- renderLayer . draw ( renderContext , attachment ) ;
12571283 }
12581284 // Draw regular transparent layers
12591285 else if ( renderLayer . isTransparent ) {
@@ -1271,18 +1297,18 @@ export class PerspectivePanel extends RenderedDataPanel {
12711297 }
12721298 // Copy transparent rendering result back to primary buffer.
12731299 gl . disable ( WebGL2RenderingContext . DEPTH_TEST ) ;
1274- gl . viewport ( 0 , 0 , width , height ) ;
1275- this . offscreenFramebuffer . bindSingle ( OffscreenTextures . COLOR ) ;
1276- gl . blendFunc (
1277- WebGL2RenderingContext . ONE_MINUS_SRC_ALPHA ,
1278- WebGL2RenderingContext . SRC_ALPHA ,
1279- ) ;
12801300 if ( hasVolumeRendering ) {
1281- this . transparencyCopyHelper . draw (
1301+ renderContext . bindFramebuffer ( ) ;
1302+ this . transparentToTransparentCopyHelper . draw (
12821303 this . volumeRenderingConfiguration . colorBuffers [ 0 ] . texture ,
12831304 this . volumeRenderingConfiguration . colorBuffers [ 1 ] . texture ,
12841305 ) ;
12851306 }
1307+ gl . blendFunc (
1308+ WebGL2RenderingContext . ONE_MINUS_SRC_ALPHA ,
1309+ WebGL2RenderingContext . SRC_ALPHA ,
1310+ ) ;
1311+ this . offscreenFramebuffer . bindSingle ( OffscreenTextures . COLOR ) ;
12861312 this . transparencyCopyHelper . draw (
12871313 transparentConfiguration . colorBuffers [ 0 ] . texture ,
12881314 transparentConfiguration . colorBuffers [ 1 ] . texture ,
@@ -1319,7 +1345,7 @@ export class PerspectivePanel extends RenderedDataPanel {
13191345 /*dppass=*/ WebGL2RenderingContext . REPLACE ,
13201346 ) ;
13211347 gl . stencilMask ( 2 ) ;
1322- if ( hasMaxProjection ) {
1348+ if ( hasVolumeRenderingPick ) {
13231349 this . maxProjectionPickCopyHelper . draw (
13241350 this . maxProjectionPickConfiguration . colorBuffers [ 0 ] . texture /*depth*/ ,
13251351 this . maxProjectionPickConfiguration . colorBuffers [ 1 ] . texture /*pick*/ ,
0 commit comments