@gnsx/three 0.186.4 → 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.
Files changed (27) hide show
  1. package/build/three.webgpu.js +1563 -761
  2. package/build/three.webgpu.nodes.js +1563 -761
  3. package/examples/jsm/inspector/tabs/Settings.js +64 -3
  4. package/package.json +1 -1
  5. package/src/materials/nodes/MeshBasicNodeMaterial.js +13 -0
  6. package/src/materials/nodes/MeshLambertNodeMaterial.js +13 -0
  7. package/src/materials/nodes/MeshMatcapNodeMaterial.js +13 -0
  8. package/src/materials/nodes/MeshPhongNodeMaterial.js +13 -0
  9. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +25 -0
  10. package/src/materials/nodes/MeshSSSNodeMaterial.js +15 -0
  11. package/src/materials/nodes/MeshStandardNodeMaterial.js +13 -0
  12. package/src/materials/nodes/MeshToonNodeMaterial.js +13 -0
  13. package/src/materials/nodes/NodeMaterial.js +107 -7
  14. package/src/materials/nodes/ShadowNodeMaterial.js +13 -0
  15. package/src/materials/nodes/VolumeNodeMaterial.js +13 -0
  16. package/src/nodes/display/BufferDebug.js +143 -0
  17. package/src/nodes/display/ComplexityDebug.js +188 -34
  18. package/src/nodes/display/DrawCallDebug.js +119 -0
  19. package/src/nodes/display/LightingDebug.js +109 -0
  20. package/src/renderers/common/Background.js +5 -2
  21. package/src/renderers/common/RenderObject.js +1 -1
  22. package/src/renderers/common/RenderPipeline.js +34 -5
  23. package/src/renderers/common/Renderer.js +11 -9
  24. package/src/renderers/common/nodes/NodeManager.js +13 -3
  25. package/src/renderers/webgl-fallback/WebGLBackend.js +4 -1
  26. package/src/renderers/webgl-fallback/utils/WebGLState.js +6 -2
  27. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +4 -1
@@ -137,12 +137,20 @@ class Settings extends Parameters {
137
137
  // WITH_GENESYS
138
138
  // Values match Renderer.debug.view. Not stored with inspector settings.
139
139
  const debugViewState = { view: 'none' };
140
+ const bufferState = { buffer: 'baseColor' };
140
141
 
141
142
  this._debugViewState = debugViewState;
143
+ this._bufferState = bufferState;
142
144
  this._debugViewControl = modesGroup.add( debugViewState, 'view', {
143
145
  'Shaded': 'none',
144
146
  'Shader Complexity': 'shaderComplexity',
145
- 'Lighting Complexity': 'lightingComplexity'
147
+ 'Lighting Complexity': 'lightingComplexity',
148
+ 'Quad Overdraw': 'quadOverdraw',
149
+ 'Shader Complexity & Quads': 'shaderComplexityAndQuads',
150
+ 'Buffer Visualization': 'bufferVisualization',
151
+ 'Lighting Only': 'lightingOnly',
152
+ 'Detail Lighting': 'detailLighting',
153
+ 'Draw Call': 'drawCall'
146
154
  } ).name( 'Debug View' ).onChange( ( view ) => {
147
155
 
148
156
  const renderer = this.inspector.getRenderer();
@@ -150,9 +158,30 @@ class Settings extends Parameters {
150
158
  if ( renderer === null || renderer.debug === undefined ) return;
151
159
 
152
160
  renderer.debug.view = view;
161
+ this._syncBufferRow( view );
153
162
  window.dispatchEvent( new Event( 'genesys-debug-view' ) );
154
163
 
155
- } ).info( 'Shaded color, a shader-cost heatmap, or a direct-light count. Overdraw draws on top when both are enabled.' );
164
+ } ).info( 'Shaded color, a cost heatmap, per-pixel overdraw, shader cost times overdraw, one material channel, lighting on a flat gray surface, or one lit color per draw. The Overdraw toggle above draws on top when both are enabled.' );
165
+
166
+ this._bufferControl = modesGroup.add( bufferState, 'buffer', {
167
+ 'Base Color': 'baseColor',
168
+ 'World Normal': 'worldNormal',
169
+ 'Roughness': 'roughness',
170
+ 'Metallic': 'metallic',
171
+ 'Ambient Occlusion': 'ambientOcclusion',
172
+ 'Emissive': 'emissive'
173
+ } ).name( 'Buffer' ).onChange( ( buffer ) => {
174
+
175
+ const renderer = this.inspector.getRenderer();
176
+
177
+ if ( renderer === null || renderer.debug === undefined ) return;
178
+
179
+ renderer.debug.buffer = buffer;
180
+ window.dispatchEvent( new Event( 'genesys-debug-view' ) );
181
+
182
+ } ).info( 'Channel drawn by Buffer Visualization. Base color, world normal, roughness, metallic, ambient occlusion, or emissive.' );
183
+
184
+ this._bufferControl.hide();
156
185
  // !WITH_GENESYS
157
186
 
158
187
  }
@@ -163,7 +192,7 @@ class Settings extends Parameters {
163
192
  const renderer = this.inspector.getRenderer();
164
193
  const view = renderer !== null && renderer.debug !== undefined ? renderer.debug.view : null;
165
194
 
166
- if ( view === 'none' || view === 'shaderComplexity' || view === 'lightingComplexity' ) {
195
+ if ( view === 'none' || view === 'shaderComplexity' || view === 'lightingComplexity' || view === 'quadOverdraw' || view === 'shaderComplexityAndQuads' || view === 'bufferVisualization' || view === 'lightingOnly' || view === 'detailLighting' || view === 'drawCall' ) {
167
196
 
168
197
  if ( this._debugViewState.view !== view ) {
169
198
 
@@ -171,6 +200,17 @@ class Settings extends Parameters {
171
200
 
172
201
  }
173
202
 
203
+ this._syncBufferRow( view );
204
+
205
+ }
206
+
207
+ const buffer = renderer !== null && renderer.debug !== undefined ? renderer.debug.buffer : null;
208
+ const buffers = [ 'baseColor', 'worldNormal', 'roughness', 'metallic', 'ambientOcclusion', 'emissive' ];
209
+
210
+ if ( buffers.includes( buffer ) && this._bufferState.buffer !== buffer ) {
211
+
212
+ this._bufferControl.setValue( buffer );
213
+
174
214
  }
175
215
  // !WITH_GENESYS
176
216
 
@@ -257,6 +297,27 @@ Shares the same state across any page within the current origin.` );
257
297
 
258
298
  }
259
299
 
300
+ // WITH_GENESYS
301
+ /**
302
+ * Shows the buffer channel row only while buffer visualization is the debug view.
303
+ *
304
+ * @param {string} view - `renderer.debug.view`.
305
+ */
306
+ _syncBufferRow( view ) {
307
+
308
+ if ( view === 'bufferVisualization' ) {
309
+
310
+ this._bufferControl.show();
311
+
312
+ } else {
313
+
314
+ this._bufferControl.hide();
315
+
316
+ }
317
+
318
+ }
319
+ // !WITH_GENESYS
320
+
260
321
  async setActiveExtension( name, value ) {
261
322
 
262
323
  const extension = this.extensions[ name ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gnsx/three",
3
- "version": "0.186.4",
3
+ "version": "0.186.6",
4
4
  "description": "JavaScript 3D library",
5
5
  "type": "module",
6
6
  "main": "./build/three.cjs",
@@ -118,6 +118,19 @@ class MeshBasicNodeMaterial extends NodeMaterial {
118
118
 
119
119
  }
120
120
 
121
+ // WITH_GENESYS
122
+ /**
123
+ * Shader-complexity proxy for {@link BasicLightingModel}.
124
+ *
125
+ * @return {number} The base cost, excluding texture samples.
126
+ */
127
+ getShaderComplexity() {
128
+
129
+ return 80;
130
+
131
+ }
132
+ // !WITH_GENESYS
133
+
121
134
  /**
122
135
  * Setups the lighting model.
123
136
  *
@@ -66,6 +66,19 @@ class MeshLambertNodeMaterial extends NodeMaterial {
66
66
 
67
67
  }
68
68
 
69
+ // WITH_GENESYS
70
+ /**
71
+ * Shader-complexity proxy for Lambert. Specular is forced off.
72
+ *
73
+ * @return {number} The base cost, excluding texture samples.
74
+ */
75
+ getShaderComplexity() {
76
+
77
+ return 140;
78
+
79
+ }
80
+ // !WITH_GENESYS
81
+
69
82
  /**
70
83
  * Setups the lighting model.
71
84
  *
@@ -46,6 +46,19 @@ class MeshMatcapNodeMaterial extends NodeMaterial {
46
46
 
47
47
  }
48
48
 
49
+ // WITH_GENESYS
50
+ /**
51
+ * Shader-complexity proxy for matcap UV shading.
52
+ *
53
+ * @return {number} The base cost, excluding texture samples.
54
+ */
55
+ getShaderComplexity() {
56
+
57
+ return 50;
58
+
59
+ }
60
+ // !WITH_GENESYS
61
+
49
62
  /**
50
63
  * Setups the matcap specific node variables.
51
64
  *
@@ -95,6 +95,19 @@ class MeshPhongNodeMaterial extends NodeMaterial {
95
95
 
96
96
  }
97
97
 
98
+ // WITH_GENESYS
99
+ /**
100
+ * Shader-complexity proxy for Blinn-Phong.
101
+ *
102
+ * @return {number} The base cost, excluding texture samples.
103
+ */
104
+ getShaderComplexity() {
105
+
106
+ return 200;
107
+
108
+ }
109
+ // !WITH_GENESYS
110
+
98
111
  /**
99
112
  * Setups the lighting model.
100
113
  *
@@ -383,6 +383,31 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
383
383
 
384
384
  }
385
385
 
386
+ // WITH_GENESYS
387
+ /**
388
+ * GGX base from {@link MeshStandardNodeMaterial}, plus each enabled physical feature.
389
+ *
390
+ * @return {number} The base cost, excluding texture samples.
391
+ */
392
+ getShaderComplexity() {
393
+
394
+ let cost = super.getShaderComplexity();
395
+
396
+ if ( this.useClearcoat === true ) cost += 30;
397
+
398
+ if ( this.useSheen === true ) cost += 30;
399
+
400
+ if ( this.useIridescence === true ) cost += 30;
401
+
402
+ if ( this.useAnisotropy === true ) cost += 30;
403
+
404
+ if ( this.useTransmission === true ) cost += 60;
405
+
406
+ return cost;
407
+
408
+ }
409
+ // !WITH_GENESYS
410
+
386
411
  /**
387
412
  * Setups the lighting model.
388
413
  *
@@ -146,6 +146,21 @@ class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial {
146
146
 
147
147
  }
148
148
 
149
+ // WITH_GENESYS
150
+ /**
151
+ * Physical complexity, plus the subsurface term when it is evaluated.
152
+ *
153
+ * @return {number} The base cost, excluding texture samples.
154
+ */
155
+ getShaderComplexity() {
156
+
157
+ const cost = super.getShaderComplexity();
158
+
159
+ return this.useSSS === true ? cost + 40 : cost;
160
+
161
+ }
162
+ // !WITH_GENESYS
163
+
149
164
  /**
150
165
  * Setups the lighting model.
151
166
  *
@@ -117,6 +117,19 @@ class MeshStandardNodeMaterial extends NodeMaterial {
117
117
 
118
118
  }
119
119
 
120
+ // WITH_GENESYS
121
+ /**
122
+ * Shader-complexity proxy for the Cook-Torrance GGX model.
123
+ *
124
+ * @return {number} The base cost, excluding texture samples.
125
+ */
126
+ getShaderComplexity() {
127
+
128
+ return 240;
129
+
130
+ }
131
+ // !WITH_GENESYS
132
+
120
133
  /**
121
134
  * Setups the lighting model.
122
135
  *
@@ -50,6 +50,19 @@ class MeshToonNodeMaterial extends NodeMaterial {
50
50
 
51
51
  }
52
52
 
53
+ // WITH_GENESYS
54
+ /**
55
+ * Shader-complexity proxy for toon banding.
56
+ *
57
+ * @return {number} The base cost, excluding texture samples.
58
+ */
59
+ getShaderComplexity() {
60
+
61
+ return 170;
62
+
63
+ }
64
+ // !WITH_GENESYS
65
+
53
66
  /**
54
67
  * Setups the lighting model.
55
68
  *
@@ -26,7 +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_SHADER_COMPLEXITY, getShaderComplexityBase, 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';
31
+ import { DEBUG_VIEW_BUFFER, assignBufferDefaults, bufferVisualizationOutput } from '../../nodes/display/BufferDebug.js';
32
+ import { DEBUG_VIEW_DETAIL_LIGHTING, DEBUG_VIEW_LIGHTING_ONLY, applyLightingDebug, lightingOnlyNormal } from '../../nodes/display/LightingDebug.js';
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
+ }
30
53
  // !WITH_GENESYS
31
54
 
32
55
  /**
@@ -527,10 +550,33 @@ class NodeMaterial extends Material {
527
550
 
528
551
  if ( this.fragmentNode === null ) {
529
552
 
553
+ // WITH_GENESYS
554
+ // Fallback for materials that never write the channel. Lit materials overwrite these.
555
+ if ( renderer.debug.view === DEBUG_VIEW_BUFFER && this.isShadowPassMaterial !== true ) {
556
+
557
+ assignBufferDefaults( renderer.debug.buffer );
558
+
559
+ }
560
+ // !WITH_GENESYS
561
+
530
562
  this.setupDiffuseColor( builder );
531
563
  this.setupAmbientOcclusion( builder );
532
564
  this.setupVariants( builder );
533
565
 
566
+ // WITH_GENESYS
567
+ // After the material writes its channels, so roughness and normals already exist
568
+ // for detail lighting and can be replaced for lighting only.
569
+ if ( ( renderer.debug.view === DEBUG_VIEW_LIGHTING_ONLY || renderer.debug.view === DEBUG_VIEW_DETAIL_LIGHTING ) && this.isShadowPassMaterial !== true ) {
570
+
571
+ applyLightingDebug( builder, this, renderer.debug.view );
572
+
573
+ } else if ( renderer.debug.view === DEBUG_VIEW_DRAW_CALL && this.isShadowPassMaterial !== true ) {
574
+
575
+ applyDrawCallDebug( builder, this );
576
+
577
+ }
578
+ // !WITH_GENESYS
579
+
534
580
  const outgoingLightNode = this.setupLighting( builder );
535
581
 
536
582
  if ( clippingNode !== null ) builder.stack.addToStack( clippingNode );
@@ -601,12 +647,32 @@ class NodeMaterial extends Material {
601
647
  }
602
648
 
603
649
  // WITH_GENESYS
604
- // The screen output pass colorizes the accumulated ratio. Wrapping that pass
605
- // would replace the heatmap with this material's own constant cost.
606
- 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 ) {
656
+
657
+ builder.shaderComplexityBase = this.getShaderComplexity();
658
+ resultNode = replaceColorOutput( resultNode, shaderComplexityOutput );
607
659
 
608
- builder.shaderComplexityBase = getShaderComplexityBase( this );
609
- resultNode = shaderComplexityOutput( resultNode );
660
+ } else if ( renderer.debug.view === DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS ) {
661
+
662
+ builder.shaderComplexityBase = this.getShaderComplexity();
663
+ resultNode = replaceColorOutput( resultNode, shaderComplexityAndQuadsOutput );
664
+
665
+ } else {
666
+
667
+ resultNode = replaceColorOutput( resultNode, quadOverdrawOutput );
668
+
669
+ }
670
+
671
+ } else if ( renderer.debug.view === DEBUG_VIEW_BUFFER && this.isShadowPassMaterial !== true && this.fragmentNode === null ) {
672
+
673
+ // The fullscreen output pass sets fragmentNode. Scene materials do not, including
674
+ // when the scene is drawn straight to the canvas.
675
+ resultNode = replaceColorOutput( resultNode, () => bufferVisualizationOutput( renderer.debug.buffer ) );
610
676
 
611
677
  }
612
678
  // !WITH_GENESYS
@@ -621,6 +687,21 @@ class NodeMaterial extends Material {
621
687
 
622
688
  }
623
689
 
690
+ // WITH_GENESYS
691
+ /**
692
+ * Static shader-complexity proxy for this material's lighting model.
693
+ * Fragment texture samples are counted later, while the shader is generated.
694
+ * Derived materials override this instead of registering a type flag.
695
+ *
696
+ * @return {number} The base cost, excluding texture samples.
697
+ */
698
+ getShaderComplexity() {
699
+
700
+ return this.lights === true ? 40 : 20;
701
+
702
+ }
703
+ // !WITH_GENESYS
704
+
624
705
  /**
625
706
  * Setups the clipping node.
626
707
  *
@@ -945,9 +1026,18 @@ class NodeMaterial extends Material {
945
1026
  /**
946
1027
  * Setups the normal node from the material.
947
1028
  *
1029
+ * @param {NodeBuilder} builder - The current node builder.
948
1030
  * @return {Node<vec3>} The normal node.
949
1031
  */
950
- setupNormal() {
1032
+ setupNormal( builder ) {
1033
+
1034
+ // WITH_GENESYS
1035
+ if ( ( builder.renderer.debug.view === DEBUG_VIEW_LIGHTING_ONLY || builder.renderer.debug.view === DEBUG_VIEW_DRAW_CALL ) && this.isShadowPassMaterial !== true && this.fragmentNode === null ) {
1036
+
1037
+ return lightingOnlyNormal();
1038
+
1039
+ }
1040
+ // !WITH_GENESYS
951
1041
 
952
1042
  return this.normalNode ? vec3( this.normalNode ) : materialNormal;
953
1043
 
@@ -1144,6 +1234,16 @@ class NodeMaterial extends Material {
1144
1234
 
1145
1235
  if ( ( emissiveNode && emissiveNode.isNode === true ) || ( material.emissive && material.emissive.isColor === true ) ) {
1146
1236
 
1237
+ // WITH_GENESYS
1238
+ // Lighting only and draw call substitute a plain lit material, so emissive is dropped.
1239
+ // Detail lighting keeps it.
1240
+ if ( ( builder.renderer.debug.view === DEBUG_VIEW_LIGHTING_ONLY || builder.renderer.debug.view === DEBUG_VIEW_DRAW_CALL ) && this.isShadowPassMaterial !== true ) {
1241
+
1242
+ return outgoingLightNode;
1243
+
1244
+ }
1245
+ // !WITH_GENESYS
1246
+
1147
1247
  emissive.assign( vec3( emissiveNode ? emissiveNode : materialEmissive ) );
1148
1248
 
1149
1249
  outgoingLightNode = outgoingLightNode.add( emissive );
@@ -60,6 +60,19 @@ class ShadowNodeMaterial extends NodeMaterial {
60
60
 
61
61
  }
62
62
 
63
+ // WITH_GENESYS
64
+ /**
65
+ * Shader-complexity proxy for the shadow mask.
66
+ *
67
+ * @return {number} The base cost, excluding texture samples.
68
+ */
69
+ getShaderComplexity() {
70
+
71
+ return 110;
72
+
73
+ }
74
+ // !WITH_GENESYS
75
+
63
76
  /**
64
77
  * Setups the lighting model.
65
78
  *
@@ -70,6 +70,19 @@ class VolumeNodeMaterial extends NodeMaterial {
70
70
 
71
71
  }
72
72
 
73
+ // WITH_GENESYS
74
+ /**
75
+ * Shader-complexity proxy for volumetric ray integration.
76
+ *
77
+ * @return {number} The base cost, excluding texture samples.
78
+ */
79
+ getShaderComplexity() {
80
+
81
+ return 280;
82
+
83
+ }
84
+ // !WITH_GENESYS
85
+
73
86
  setupLightingModel() {
74
87
 
75
88
  return new VolumetricLightingModel();
@@ -0,0 +1,143 @@
1
+ // WITH_GENESYS
2
+ // Buffer visualization. Shows one material channel in place of the shaded color.
3
+ // !WITH_GENESYS
4
+
5
+ import { diffuseColor, ambientOcclusion, emissive, metalness, roughness } from '../core/PropertyNode.js';
6
+ import { normalWorld } from '../accessors/Normal.js';
7
+ import { float, vec3, vec4 } from '../tsl/TSLCore.js';
8
+
9
+ /**
10
+ * Buffer visualization. The visible surface wins, and one material channel replaces the shaded color.
11
+ *
12
+ * @type {string}
13
+ */
14
+ export const DEBUG_VIEW_BUFFER = 'bufferVisualization';
15
+
16
+ /**
17
+ * Albedo before lighting, including maps and vertex colors.
18
+ *
19
+ * @type {string}
20
+ */
21
+ export const BUFFER_BASE_COLOR = 'baseColor';
22
+
23
+ /**
24
+ * Shading normal in world space, packed to RGB with `n * 0.5 + 0.5`.
25
+ *
26
+ * @type {string}
27
+ */
28
+ export const BUFFER_WORLD_NORMAL = 'worldNormal';
29
+
30
+ /**
31
+ * Scalar roughness used by the lighting model. Black is smooth.
32
+ *
33
+ * @type {string}
34
+ */
35
+ export const BUFFER_ROUGHNESS = 'roughness';
36
+
37
+ /**
38
+ * Scalar metalness. White is metal. Unreal calls this buffer Metallic.
39
+ *
40
+ * @type {string}
41
+ */
42
+ export const BUFFER_METALLIC = 'metallic';
43
+
44
+ /**
45
+ * Material ambient occlusion. White means no occlusion map.
46
+ *
47
+ * @type {string}
48
+ */
49
+ export const BUFFER_AMBIENT_OCCLUSION = 'ambientOcclusion';
50
+
51
+ /**
52
+ * Emissive color before it is added to the lit result.
53
+ *
54
+ * @type {string}
55
+ */
56
+ export const BUFFER_EMISSIVE = 'emissive';
57
+
58
+ /**
59
+ * Channel drawn when buffer visualization is first enabled.
60
+ *
61
+ * @type {string}
62
+ */
63
+ export const DEFAULT_BUFFER = BUFFER_BASE_COLOR;
64
+
65
+ /**
66
+ * Writes a defined value for channels a material may never assign.
67
+ * Standard and physical materials overwrite roughness and metalness in `setupVariants`,
68
+ * and emissive is overwritten when the material has one.
69
+ *
70
+ * @param {string} buffer - `renderer.debug.buffer`.
71
+ */
72
+ export function assignBufferDefaults( buffer ) {
73
+
74
+ if ( buffer === BUFFER_ROUGHNESS ) {
75
+
76
+ roughness.assign( float( 0 ) );
77
+
78
+ } else if ( buffer === BUFFER_METALLIC ) {
79
+
80
+ metalness.assign( float( 0 ) );
81
+
82
+ } else if ( buffer === BUFFER_EMISSIVE ) {
83
+
84
+ emissive.assign( vec3( 0 ) );
85
+
86
+ }
87
+
88
+ }
89
+
90
+ /**
91
+ * The color for one buffer channel. Scalar channels are copied into RGB.
92
+ *
93
+ * @param {string} buffer - `renderer.debug.buffer`.
94
+ * @return {Node<vec3>} The channel color.
95
+ */
96
+ export function bufferVisualizationColor( buffer ) {
97
+
98
+ if ( buffer === BUFFER_WORLD_NORMAL ) {
99
+
100
+ return normalWorld.mul( 0.5 ).add( 0.5 );
101
+
102
+ }
103
+
104
+ if ( buffer === BUFFER_ROUGHNESS ) {
105
+
106
+ return vec3( roughness );
107
+
108
+ }
109
+
110
+ if ( buffer === BUFFER_METALLIC ) {
111
+
112
+ return vec3( metalness );
113
+
114
+ }
115
+
116
+ if ( buffer === BUFFER_AMBIENT_OCCLUSION ) {
117
+
118
+ return vec3( ambientOcclusion );
119
+
120
+ }
121
+
122
+ if ( buffer === BUFFER_EMISSIVE ) {
123
+
124
+ return emissive;
125
+
126
+ }
127
+
128
+ return diffuseColor.rgb;
129
+
130
+ }
131
+
132
+ /**
133
+ * Replaces the shaded color with the selected buffer. Alpha stays the material's coverage
134
+ * so masked and transparent surfaces keep their shape.
135
+ *
136
+ * @param {string} buffer - `renderer.debug.buffer`.
137
+ * @return {Node<vec4>} The buffer color.
138
+ */
139
+ export function bufferVisualizationOutput( buffer ) {
140
+
141
+ return vec4( bufferVisualizationColor( buffer ), diffuseColor.a );
142
+
143
+ }