@@ -365,6 +365,17 @@ class OutlineNode extends TempNode {
365365 */
366366 this . _selectionCache = new Set ( ) ;
367367
368+ /**
369+ * The number of selected objects from the previous frame. Used to detect
370+ * the transition to an empty selection so the composite render target can
371+ * be cleared once and avoid leaving a stale outline on screen.
372+ *
373+ * @private
374+ * @type {number }
375+ * @default 0
376+ */
377+ this . _lastSelectionCount = 0 ;
378+
368379 /**
369380 * The result of the effect is represented as a separate texture node.
370381 *
@@ -449,6 +460,35 @@ class OutlineNode extends TempNode {
449460 const { renderer } = frame ;
450461 const { camera, scene } = this ;
451462
463+ this . _updateSelectionCache ( ) ;
464+
465+ // If no objects are selected, all subsequent passes can be skipped since
466+ // the outline would be empty anyway. The composite render target is cleared
467+ // once when transitioning to an empty selection so a previously rendered
468+ // outline does not linger on screen.
469+
470+ if ( this . _selectionCache . size === 0 ) {
471+
472+ if ( this . _lastSelectionCount > 0 ) {
473+
474+ _rendererState = RendererUtils . resetRendererState ( renderer , _rendererState ) ;
475+
476+ renderer . setRenderTarget ( this . _renderTargetComposite ) ;
477+ renderer . setClearColor ( 0x000000 , 0 ) ;
478+ renderer . clear ( ) ;
479+
480+ RendererUtils . restoreRendererState ( renderer , _rendererState ) ;
481+
482+ this . _lastSelectionCount = 0 ;
483+
484+ }
485+
486+ return ;
487+
488+ }
489+
490+ this . _lastSelectionCount = this . _selectionCache . size ;
491+
452492 _rendererState = RendererUtils . resetRendererAndSceneState ( renderer , scene , _rendererState ) ;
453493
454494 //
@@ -460,8 +500,6 @@ class OutlineNode extends TempNode {
460500
461501 renderer . setClearColor ( 0xffffff , 1 ) ;
462502
463- this . _updateSelectionCache ( ) ;
464-
465503 const currentSceneName = scene . name ;
466504
467505 // 1. Draw non-selected objects in the depth buffer
0 commit comments