@gnsx/three 0.186.5 → 0.186.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gnsx/three",
3
- "version": "0.186.5",
3
+ "version": "0.186.6",
4
4
  "description": "JavaScript 3D library",
5
5
  "type": "module",
6
6
  "main": "./build/three.cjs",
@@ -26,10 +26,30 @@ import { vertexColor } from '../../nodes/accessors/VertexColorNode.js';
26
26
  import { premultiplyAlpha } from '../../nodes/display/PremultiplyAlphaFunctions.js';
27
27
  import { subBuild } from '../../nodes/core/SubBuildNode.js';
28
28
  // WITH_GENESYS
29
- import { DEBUG_VIEW_LIGHTING_COMPLEXITY, DEBUG_VIEW_QUAD_OVERDRAW, DEBUG_VIEW_SHADER_COMPLEXITY, DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS, quadOverdrawOutput, shaderComplexityAndQuadsOutput, shaderComplexityOutput } from '../../nodes/display/ComplexityDebug.js';
29
+ import { DEBUG_VIEW_LIGHTING_COMPLEXITY, DEBUG_VIEW_SHADER_COMPLEXITY, DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS, debugDrawAccumulates, quadOverdrawOutput, shaderComplexityAndQuadsOutput, shaderComplexityOutput } from '../../nodes/display/ComplexityDebug.js';
30
+ import { mrt } from '../../nodes/core/MRTNode.js';
30
31
  import { DEBUG_VIEW_BUFFER, assignBufferDefaults, bufferVisualizationOutput } from '../../nodes/display/BufferDebug.js';
31
32
  import { DEBUG_VIEW_DETAIL_LIGHTING, DEBUG_VIEW_LIGHTING_ONLY, applyLightingDebug, lightingOnlyNormal } from '../../nodes/display/LightingDebug.js';
32
33
  import { DEBUG_VIEW_DRAW_CALL, applyDrawCallDebug } from '../../nodes/display/DrawCallDebug.js';
34
+
35
+ /**
36
+ * Replaces the color a material writes with a debug output. With MRT, only the `output`
37
+ * attachment is replaced so the other attachments keep their members. Converting the
38
+ * whole MRT struct to a color leaves WGSL with an empty output struct.
39
+ *
40
+ * @param {Node} resultNode - The material's fragment result, possibly an MRT node.
41
+ * @param {function(Node): Node} createOutput - Builds the debug color from the shaded color.
42
+ * @return {Node} The fragment result with the debug color in place.
43
+ */
44
+ function replaceColorOutput( resultNode, createOutput ) {
45
+
46
+ if ( resultNode.isMRTNode !== true ) return createOutput( resultNode );
47
+
48
+ if ( resultNode.has( 'output' ) !== true ) return resultNode;
49
+
50
+ return resultNode.merge( mrt( { output: createOutput( resultNode.get( 'output' ) ) } ) );
51
+
52
+ }
33
53
  // !WITH_GENESYS
34
54
 
35
55
  /**
@@ -548,11 +568,11 @@ class NodeMaterial extends Material {
548
568
  // for detail lighting and can be replaced for lighting only.
549
569
  if ( ( renderer.debug.view === DEBUG_VIEW_LIGHTING_ONLY || renderer.debug.view === DEBUG_VIEW_DETAIL_LIGHTING ) && this.isShadowPassMaterial !== true ) {
550
570
 
551
- applyLightingDebug( builder, renderer.debug.view );
571
+ applyLightingDebug( builder, this, renderer.debug.view );
552
572
 
553
573
  } else if ( renderer.debug.view === DEBUG_VIEW_DRAW_CALL && this.isShadowPassMaterial !== true ) {
554
574
 
555
- applyDrawCallDebug( builder );
575
+ applyDrawCallDebug( builder, this );
556
576
 
557
577
  }
558
578
  // !WITH_GENESYS
@@ -627,27 +647,32 @@ class NodeMaterial extends Material {
627
647
  }
628
648
 
629
649
  // WITH_GENESYS
630
- // The screen output pass colorizes the accumulated ratio. Wrapping that pass
631
- // would replace the heatmap with this material's own constant cost.
632
- if ( renderer.debug.view === DEBUG_VIEW_SHADER_COMPLEXITY && this.isShadowPassMaterial !== true && renderer.isOutputTarget !== true ) {
650
+ // The screen output pass colorizes the accumulated ratio. Wrapping that pass, or a
651
+ // post-processing quad that copies the scene target, would replace the heatmap with
652
+ // that quad's own constant cost.
653
+ if ( debugDrawAccumulates( renderer, this, builder.object ) ) {
654
+
655
+ if ( renderer.debug.view === DEBUG_VIEW_SHADER_COMPLEXITY ) {
633
656
 
634
- builder.shaderComplexityBase = this.getShaderComplexity();
635
- resultNode = shaderComplexityOutput( resultNode );
657
+ builder.shaderComplexityBase = this.getShaderComplexity();
658
+ resultNode = replaceColorOutput( resultNode, shaderComplexityOutput );
636
659
 
637
- } else if ( renderer.debug.view === DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS && this.isShadowPassMaterial !== true && renderer.isOutputTarget !== true ) {
660
+ } else if ( renderer.debug.view === DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS ) {
638
661
 
639
- builder.shaderComplexityBase = this.getShaderComplexity();
640
- resultNode = shaderComplexityAndQuadsOutput( resultNode );
662
+ builder.shaderComplexityBase = this.getShaderComplexity();
663
+ resultNode = replaceColorOutput( resultNode, shaderComplexityAndQuadsOutput );
641
664
 
642
- } else if ( renderer.debug.view === DEBUG_VIEW_QUAD_OVERDRAW && this.isShadowPassMaterial !== true && renderer.isOutputTarget !== true ) {
665
+ } else {
666
+
667
+ resultNode = replaceColorOutput( resultNode, quadOverdrawOutput );
643
668
 
644
- resultNode = quadOverdrawOutput( resultNode );
669
+ }
645
670
 
646
671
  } else if ( renderer.debug.view === DEBUG_VIEW_BUFFER && this.isShadowPassMaterial !== true && this.fragmentNode === null ) {
647
672
 
648
673
  // The fullscreen output pass sets fragmentNode. Scene materials do not, including
649
674
  // when the scene is drawn straight to the canvas.
650
- resultNode = bufferVisualizationOutput( renderer.debug.buffer );
675
+ resultNode = replaceColorOutput( resultNode, () => bufferVisualizationOutput( renderer.debug.buffer ) );
651
676
 
652
677
  }
653
678
  // !WITH_GENESYS
@@ -5,6 +5,7 @@
5
5
  import Node from '../core/Node.js';
6
6
  import { float, vec3, vec4, If, Fn } from '../tsl/TSLCore.js';
7
7
  import { fract, min, mix, round } from '../math/MathNode.js';
8
+ import { DEBUG_VIEW_BUFFER } from './BufferDebug.js';
8
9
 
9
10
  /**
10
11
  * Shaded output. No complexity debug view.
@@ -224,6 +225,37 @@ export function debugViewAccumulates( view ) {
224
225
 
225
226
  }
226
227
 
228
+ /**
229
+ * Whether a draw adds its scalar to the accumulating target instead of shading normally.
230
+ * Shadow passes, draws to the screen, and fullscreen quads draw normally. A post-processing
231
+ * quad copies the accumulated scene target, so its own cost must not replace it.
232
+ *
233
+ * @param {Renderer} renderer - The renderer.
234
+ * @param {Material} material - The material being drawn.
235
+ * @param {?Object3D} object - The object being drawn.
236
+ * @return {boolean} `true` when the draw accumulates.
237
+ */
238
+ export function debugDrawAccumulates( renderer, material, object ) {
239
+
240
+ return debugViewAccumulates( renderer.debug.view ) &&
241
+ material.isShadowPassMaterial !== true &&
242
+ renderer.isOutputTarget !== true &&
243
+ ( object === null || object === undefined || object.isQuadMesh !== true );
244
+
245
+ }
246
+
247
+ /**
248
+ * Views that output data or a heatmap, so tone mapping would distort them.
249
+ *
250
+ * @param {string} view - `renderer.debug.view`.
251
+ * @return {boolean} `true` when the view is drawn without tone mapping.
252
+ */
253
+ export function debugViewSkipsToneMapping( view ) {
254
+
255
+ return debugViewAccumulates( view ) || view === DEBUG_VIEW_LIGHTING_COMPLEXITY || view === DEBUG_VIEW_BUFFER;
256
+
257
+ }
258
+
227
259
  /**
228
260
  * Unreal's nonlinear shader-complexity ramp (`ColorizeComplexity`).
229
261
  * The first third of the normalized cost spreads across the first seven stops.
@@ -77,10 +77,11 @@ function writeDrawCallColor( color, object, material ) {
77
77
  * The color is an object uniform, so meshes that share a material still differ.
78
78
  *
79
79
  * @param {NodeBuilder} builder - The current node builder.
80
+ * @param {NodeMaterial} material - The node material being set up. `builder.material` can be the
81
+ * source material of a converted one, such as a glTF `MeshStandardMaterial`.
80
82
  */
81
- export function applyDrawCallDebug( builder ) {
83
+ export function applyDrawCallDebug( builder, material ) {
82
84
 
83
- const material = builder.material;
84
85
  const colorNode = uniform( new Color() ).onObjectUpdate( ( { object, material: drawnMaterial }, self ) => {
85
86
 
86
87
  if ( object === null || drawnMaterial === null ) return;
@@ -59,11 +59,12 @@ export const lightingOnlyNormal = /*@__PURE__*/ Fn( ( builder ) => {
59
59
  * Lit materials become a dielectric gray. Unlit materials become flat gray.
60
60
  *
61
61
  * @param {NodeBuilder} builder - The current node builder.
62
+ * @param {NodeMaterial} material - The node material being set up. `builder.material` can be the
63
+ * source material of a converted one, such as a glTF `MeshStandardMaterial`.
62
64
  * @param {string} view - `renderer.debug.view`.
63
65
  */
64
- export function applyLightingDebug( builder, view ) {
66
+ export function applyLightingDebug( builder, material, view ) {
65
67
 
66
- const material = builder.material;
67
68
  const gray = vec3( LIGHTING_ONLY_BRIGHTNESS );
68
69
 
69
70
  diffuseColor.rgb.assign( gray );
@@ -4,6 +4,9 @@ import { vec4, renderOutput, context } from '../../nodes/TSL.js';
4
4
  import { NoToneMapping } from '../../constants.js';
5
5
  import QuadMesh from '../../renderers/common/QuadMesh.js';
6
6
  import { warnOnce } from '../../utils.js';
7
+ // WITH_GENESYS
8
+ import { debugViewAccumulates, debugViewSkipsToneMapping } from '../../nodes/display/ComplexityDebug.js';
9
+ // !WITH_GENESYS
7
10
 
8
11
  /**
9
12
  * This module is responsible to manage the rendering pipeline setups in apps.
@@ -139,7 +142,12 @@ class RenderPipeline {
139
142
  const outputColorSpace = renderer.outputColorSpace;
140
143
 
141
144
  renderer.toneMapping = NoToneMapping;
142
- renderer.outputColorSpace = ColorManagement.workingColorSpace;
145
+
146
+ // WITH_GENESYS
147
+ // Accumulating views colorize in the renderer's output pass, which must still encode the color space.
148
+ if ( debugViewAccumulates( renderer.debug.view ) !== true ) renderer.outputColorSpace = ColorManagement.workingColorSpace;
149
+ // !WITH_GENESYS
150
+ // renderer.outputColorSpace = ColorManagement.workingColorSpace;
143
151
 
144
152
  //
145
153
 
@@ -215,19 +223,40 @@ class RenderPipeline {
215
223
  */
216
224
  _update() {
217
225
 
218
- if ( this._toneMapping !== this.renderer.toneMapping ) {
226
+ // WITH_GENESYS
227
+ // Debug views drawn without tone mapping must match the direct path. An accumulating
228
+ // view copies the raw ratio here, and the renderer's output pass colorizes it.
229
+ const view = this.renderer.debug.view;
230
+ const toneMapping = debugViewSkipsToneMapping( view ) ? NoToneMapping : this.renderer.toneMapping;
231
+ const outputColorSpace = debugViewAccumulates( view ) ? ColorManagement.workingColorSpace : this.renderer.outputColorSpace;
232
+
233
+ if ( this._toneMapping !== toneMapping ) {
219
234
 
220
- this._toneMapping = this.renderer.toneMapping;
235
+ this._toneMapping = toneMapping;
221
236
  this.needsUpdate = true;
222
237
 
223
238
  }
224
239
 
225
- if ( this._outputColorSpace !== this.renderer.outputColorSpace ) {
240
+ if ( this._outputColorSpace !== outputColorSpace ) {
226
241
 
227
- this._outputColorSpace = this.renderer.outputColorSpace;
242
+ this._outputColorSpace = outputColorSpace;
228
243
  this.needsUpdate = true;
229
244
 
230
245
  }
246
+ // !WITH_GENESYS
247
+ // if ( this._toneMapping !== this.renderer.toneMapping ) {
248
+ //
249
+ // this._toneMapping = this.renderer.toneMapping;
250
+ // this.needsUpdate = true;
251
+ //
252
+ // }
253
+ //
254
+ // if ( this._outputColorSpace !== this.renderer.outputColorSpace ) {
255
+ //
256
+ // this._outputColorSpace = this.renderer.outputColorSpace;
257
+ // this.needsUpdate = true;
258
+ //
259
+ // }
231
260
 
232
261
  if ( this.needsUpdate === true ) {
233
262
 
@@ -37,8 +37,8 @@ import { float, vec3, vec4, Fn } from '../../nodes/tsl/TSLCore.js';
37
37
  import { detachRendererReference } from '../../nodes/accessors/RendererReferenceNode.js';
38
38
  import { toneMappingExposure } from '../../nodes/display/ToneMappingNode.js';
39
39
  import { ProfilerService } from '../../profiler/ProfilerService.js';
40
- import { DEBUG_VIEW_LIGHTING_COMPLEXITY, DEBUG_VIEW_NONE, DEBUG_VIEW_QUAD_OVERDRAW, DEBUG_VIEW_SHADER_COMPLEXITY, DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS, DEFAULT_QUAD_OVERDRAW_BUDGET, DEFAULT_SHADER_COMPLEXITY_BUDGET, debugViewAccumulates } from '../../nodes/display/ComplexityDebug.js';
41
- import { DEBUG_VIEW_BUFFER, DEFAULT_BUFFER } from '../../nodes/display/BufferDebug.js';
40
+ import { DEBUG_VIEW_NONE, DEFAULT_QUAD_OVERDRAW_BUDGET, DEFAULT_SHADER_COMPLEXITY_BUDGET, debugViewAccumulates, debugViewSkipsToneMapping } from '../../nodes/display/ComplexityDebug.js';
41
+ import { DEFAULT_BUFFER } from '../../nodes/display/BufferDebug.js';
42
42
  // !WITH_GENESYS
43
43
  import { reference } from '../../nodes/accessors/ReferenceNode.js';
44
44
  import { highpModelNormalViewMatrix, highpModelViewMatrix } from '../../nodes/accessors/ModelNode.js';
@@ -2705,7 +2705,8 @@ class Renderer {
2705
2705
 
2706
2706
  // WITH_GENESYS
2707
2707
  // Accumulating views write a scalar into an intermediate target, then the output pass colorizes it.
2708
- return useToneMapping || useColorSpace || debugViewAccumulates( this.debug.view );
2708
+ // Only screen output needs one. An off-screen target, such as a scene pass, already is the target.
2709
+ return useToneMapping || useColorSpace || ( debugViewAccumulates( this.debug.view ) && this.isOutputTarget );
2709
2710
  // !WITH_GENESYS
2710
2711
  // return useToneMapping || useColorSpace;
2711
2712
 
@@ -2759,9 +2760,7 @@ class Renderer {
2759
2760
  get currentToneMapping() {
2760
2761
 
2761
2762
  // WITH_GENESYS
2762
- const view = this.debug.view;
2763
-
2764
- if ( view === DEBUG_VIEW_SHADER_COMPLEXITY || view === DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS || view === DEBUG_VIEW_LIGHTING_COMPLEXITY || view === DEBUG_VIEW_QUAD_OVERDRAW || view === DEBUG_VIEW_BUFFER ) {
2763
+ if ( debugViewSkipsToneMapping( this.debug.view ) ) {
2765
2764
 
2766
2765
  return NoToneMapping;
2767
2766
 
@@ -1124,7 +1124,10 @@ class WebGLBackend extends Backend {
1124
1124
 
1125
1125
  const frontFaceCW = ( object.isMesh && object.matrixWorld.determinantAffine() < 0 );
1126
1126
 
1127
- state.setMaterial( material, frontFaceCW, hardwareClippingPlanes );
1127
+ // WITH_GENESYS
1128
+ state.setMaterial( material, frontFaceCW, hardwareClippingPlanes, object );
1129
+ // !WITH_GENESYS
1130
+ // state.setMaterial( material, frontFaceCW, hardwareClippingPlanes );
1128
1131
 
1129
1132
  if ( context.mrt !== null && context.textures !== null ) {
1130
1133
 
@@ -12,7 +12,7 @@ import { Color } from '../../../math/Color.js';
12
12
  import { Vector4 } from '../../../math/Vector4.js';
13
13
  import { error, ReversedDepthFuncs, warnOnce } from '../../../utils.js';
14
14
  // WITH_GENESYS
15
- import { debugViewAccumulates } from '../../../nodes/display/ComplexityDebug.js';
15
+ import { debugDrawAccumulates } from '../../../nodes/display/ComplexityDebug.js';
16
16
  // !WITH_GENESYS
17
17
 
18
18
  let equationToGL, factorToGL;
@@ -923,8 +923,9 @@ class WebGLState {
923
923
  * @param {Material} material - The material to configure the state for.
924
924
  * @param {number} frontFaceCW - Whether the front faces are counter-clockwise or not.
925
925
  * @param {number} hardwareClippingPlanes - The number of hardware clipping planes.
926
+ * @param {?Object3D} [object=null] - The object being drawn. Used by the accumulating debug views.
926
927
  */
927
- setMaterial( material, frontFaceCW, hardwareClippingPlanes ) {
928
+ setMaterial( material, frontFaceCW, hardwareClippingPlanes, object = null ) {
928
929
 
929
930
  const { gl } = this;
930
931
 
@@ -939,7 +940,7 @@ class WebGLState {
939
940
 
940
941
  // WITH_GENESYS
941
942
  // WebGL has no cached render pipeline. One+One is applied on each draw instead.
942
- if ( debugViewAccumulates( this.backend.renderer.debug.view ) && material.isShadowPassMaterial !== true && this.backend.renderer.isOutputTarget !== true ) {
943
+ if ( debugDrawAccumulates( this.backend.renderer, material, object ) ) {
943
944
 
944
945
  this.setBlending( AdditiveBlending, AddEquation, OneFactor, OneFactor, AddEquation, OneFactor, OneFactor, material.blendColor, material.blendAlpha, true );
945
946
 
@@ -16,7 +16,7 @@ import {
16
16
 
17
17
  import { error, ReversedDepthFuncs, warn, warnOnce } from '../../../utils.js';
18
18
  // WITH_GENESYS
19
- import { debugViewAccumulates } from '../../../nodes/display/ComplexityDebug.js';
19
+ import { debugDrawAccumulates } from '../../../nodes/display/ComplexityDebug.js';
20
20
  // !WITH_GENESYS
21
21
 
22
22
  import GPUComputePipelineDescriptor from '../descriptors/GPUComputePipelineDescriptor.js';
@@ -111,7 +111,7 @@ class WebGPUPipelineUtils {
111
111
 
112
112
  // WITH_GENESYS
113
113
  // Accumulate shader cost with One+One. Opaque materials normally disable blending.
114
- if ( debugViewAccumulates( backend.renderer.debug.view ) && material.isShadowPassMaterial !== true && backend.renderer.isOutputTarget !== true ) {
114
+ if ( debugDrawAccumulates( backend.renderer, material, object ) ) {
115
115
 
116
116
  materialBlending = {
117
117
  color: {