@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.
- package/build/three.webgpu.js +1563 -761
- package/build/three.webgpu.nodes.js +1563 -761
- package/examples/jsm/inspector/tabs/Settings.js +64 -3
- package/package.json +1 -1
- package/src/materials/nodes/MeshBasicNodeMaterial.js +13 -0
- package/src/materials/nodes/MeshLambertNodeMaterial.js +13 -0
- package/src/materials/nodes/MeshMatcapNodeMaterial.js +13 -0
- package/src/materials/nodes/MeshPhongNodeMaterial.js +13 -0
- package/src/materials/nodes/MeshPhysicalNodeMaterial.js +25 -0
- package/src/materials/nodes/MeshSSSNodeMaterial.js +15 -0
- package/src/materials/nodes/MeshStandardNodeMaterial.js +13 -0
- package/src/materials/nodes/MeshToonNodeMaterial.js +13 -0
- package/src/materials/nodes/NodeMaterial.js +107 -7
- package/src/materials/nodes/ShadowNodeMaterial.js +13 -0
- package/src/materials/nodes/VolumeNodeMaterial.js +13 -0
- package/src/nodes/display/BufferDebug.js +143 -0
- package/src/nodes/display/ComplexityDebug.js +188 -34
- package/src/nodes/display/DrawCallDebug.js +119 -0
- package/src/nodes/display/LightingDebug.js +109 -0
- package/src/renderers/common/Background.js +5 -2
- package/src/renderers/common/RenderObject.js +1 -1
- package/src/renderers/common/RenderPipeline.js +34 -5
- package/src/renderers/common/Renderer.js +11 -9
- package/src/renderers/common/nodes/NodeManager.js +13 -3
- package/src/renderers/webgl-fallback/WebGLBackend.js +4 -1
- package/src/renderers/webgl-fallback/utils/WebGLState.js +6 -2
- package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +4 -1
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import Node from '../core/Node.js';
|
|
6
6
|
import { float, vec3, vec4, If, Fn } from '../tsl/TSLCore.js';
|
|
7
|
-
import { fract, min, mix } from '../math/MathNode.js';
|
|
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.
|
|
@@ -27,30 +28,57 @@ export const DEBUG_VIEW_SHADER_COMPLEXITY = 'shaderComplexity';
|
|
|
27
28
|
*/
|
|
28
29
|
export const DEBUG_VIEW_LIGHTING_COMPLEXITY = 'lightingComplexity';
|
|
29
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Per-pixel overdraw heatmap. Each fragment that passes the depth test adds one.
|
|
33
|
+
* This is the portable stand-in for Unreal's 2×2 quad-coverage count.
|
|
34
|
+
*
|
|
35
|
+
* @type {string}
|
|
36
|
+
*/
|
|
37
|
+
export const DEBUG_VIEW_QUAD_OVERDRAW = 'quadOverdraw';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Shader cost multiplied by the number of fragments that shaded the pixel, then the shader-complexity ramp.
|
|
41
|
+
* One opaque surface matches {@link DEBUG_VIEW_SHADER_COMPLEXITY}. Each extra overlapping fragment scales the summed cost.
|
|
42
|
+
* WebGPU cannot count wasted lanes in a 2×2 quad, so the count is fragments that pass the depth test.
|
|
43
|
+
*
|
|
44
|
+
* @type {string}
|
|
45
|
+
*/
|
|
46
|
+
export const DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS = 'shaderComplexityAndQuads';
|
|
47
|
+
|
|
30
48
|
/**
|
|
31
49
|
* Proxy budget that fills the shader-complexity ramp.
|
|
32
|
-
*
|
|
33
|
-
* texture samples climbs toward
|
|
50
|
+
* Unlit and basic stay green. Phong and standard move through yellow into red.
|
|
51
|
+
* Transmission plus several texture samples climbs toward white.
|
|
34
52
|
*
|
|
35
53
|
* @type {number}
|
|
36
54
|
*/
|
|
37
55
|
export const DEFAULT_SHADER_COMPLEXITY_BUDGET = 800;
|
|
38
56
|
|
|
39
|
-
/**
|
|
40
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Overlapping fragments that fill the quad-overdraw ramp.
|
|
59
|
+
* Unreal's stair reaches white at ten layers (`1 / 16` stored, then scaled by 1.6).
|
|
60
|
+
*
|
|
61
|
+
* @type {number}
|
|
62
|
+
*/
|
|
63
|
+
export const DEFAULT_QUAD_OVERDRAW_BUDGET = 10;
|
|
41
64
|
|
|
42
|
-
/**
|
|
43
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Storage scale for the overdraw count in {@link DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS}.
|
|
67
|
+
* Each fragment adds `1 / scale`, so an 8-bit target can hold this many layers.
|
|
68
|
+
* The output pass multiplies that channel back to a count. Half-float targets hold the same count exactly.
|
|
69
|
+
*
|
|
70
|
+
* @type {number}
|
|
71
|
+
*/
|
|
72
|
+
export const SHADER_COMPLEXITY_QUAD_COUNT_SCALE = 16;
|
|
44
73
|
|
|
45
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Added for each fragment texture sample. Lighting-model costs are returned
|
|
76
|
+
* directly by {@link NodeMaterial#getShaderComplexity}.
|
|
77
|
+
*
|
|
78
|
+
* @type {number}
|
|
79
|
+
*/
|
|
46
80
|
export const SHADER_COMPLEXITY_TEXTURE_COST = 16;
|
|
47
81
|
|
|
48
|
-
/** @type {number} */
|
|
49
|
-
export const SHADER_COMPLEXITY_FEATURE_COST = 30;
|
|
50
|
-
|
|
51
|
-
/** @type {number} */
|
|
52
|
-
export const SHADER_COMPLEXITY_TRANSMISSION_COST = 60;
|
|
53
|
-
|
|
54
82
|
/**
|
|
55
83
|
* Attenuation above this counts as a light that shades the pixel.
|
|
56
84
|
*
|
|
@@ -83,6 +111,26 @@ const SHADER_COMPLEXITY_COLORS = [
|
|
|
83
111
|
[ 1.0, 0.9, 0.9 ]
|
|
84
112
|
];
|
|
85
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Unreal `QuadComplexityColors` from `BaseEngine.ini`.
|
|
116
|
+
* Sampled as a stair: one overlapping fragment is one stop.
|
|
117
|
+
*
|
|
118
|
+
* @type {Array<Array<number>>}
|
|
119
|
+
*/
|
|
120
|
+
const QUAD_COMPLEXITY_COLORS = [
|
|
121
|
+
[ 0.0, 0.0, 0.0 ],
|
|
122
|
+
[ 0.0, 0.0, 0.4 ],
|
|
123
|
+
[ 0.0, 0.3, 1.0 ],
|
|
124
|
+
[ 0.0, 0.7, 0.4 ],
|
|
125
|
+
[ 0.0, 1.0, 0.0 ],
|
|
126
|
+
[ 0.8, 0.8, 0.0 ],
|
|
127
|
+
[ 1.0, 0.3, 0.0 ],
|
|
128
|
+
[ 0.7, 0.0, 0.0 ],
|
|
129
|
+
[ 0.5, 0.0, 0.5 ],
|
|
130
|
+
[ 0.7, 0.3, 0.7 ],
|
|
131
|
+
[ 1.0, 0.9, 0.9 ]
|
|
132
|
+
];
|
|
133
|
+
|
|
86
134
|
/**
|
|
87
135
|
* Unreal `LightComplexityColors` from `BaseEngine.ini`.
|
|
88
136
|
*
|
|
@@ -141,6 +189,73 @@ const colorizeLinear = ( cost, colors ) => {
|
|
|
141
189
|
*/
|
|
142
190
|
export const colorizeLightComplexity = ( cost ) => colorizeLinear( cost, LIGHT_COMPLEXITY_COLORS );
|
|
143
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Unreal's stair sample for quad overdraw (`CS_STAIR`).
|
|
194
|
+
* `cost` is the accumulated fragment count divided by the budget.
|
|
195
|
+
*
|
|
196
|
+
* @param {Node<float>} cost - Overdraw count divided by the budget.
|
|
197
|
+
* @return {Node<vec3>} The ramp color.
|
|
198
|
+
*/
|
|
199
|
+
export const colorizeQuadOverdraw = ( cost ) => {
|
|
200
|
+
|
|
201
|
+
const steps = QUAD_COMPLEXITY_COLORS.length - 1;
|
|
202
|
+
const index = round( cost.clamp( 0, 1 ).mul( steps ) );
|
|
203
|
+
|
|
204
|
+
let color = rgb( QUAD_COMPLEXITY_COLORS, 0 );
|
|
205
|
+
|
|
206
|
+
for ( let i = 0; i <= steps; i ++ ) {
|
|
207
|
+
|
|
208
|
+
color = index.equal( float( i ) ).select( rgb( QUAD_COMPLEXITY_COLORS, i ), color );
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return color;
|
|
213
|
+
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Views that add a scalar per fragment, then colorize that sum in the output pass.
|
|
218
|
+
*
|
|
219
|
+
* @param {string} view - `renderer.debug.view`.
|
|
220
|
+
* @return {boolean} `true` when the view accumulates.
|
|
221
|
+
*/
|
|
222
|
+
export function debugViewAccumulates( view ) {
|
|
223
|
+
|
|
224
|
+
return view === DEBUG_VIEW_SHADER_COMPLEXITY || view === DEBUG_VIEW_QUAD_OVERDRAW || view === DEBUG_VIEW_SHADER_COMPLEXITY_AND_QUADS;
|
|
225
|
+
|
|
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
|
+
|
|
144
259
|
/**
|
|
145
260
|
* Unreal's nonlinear shader-complexity ramp (`ColorizeComplexity`).
|
|
146
261
|
* The first third of the normalized cost spreads across the first seven stops.
|
|
@@ -234,44 +349,83 @@ class ShaderComplexityRatioNode extends Node {
|
|
|
234
349
|
}
|
|
235
350
|
|
|
236
351
|
/**
|
|
237
|
-
*
|
|
352
|
+
* Replaces the shaded color with `vec4(cost / budget, 0, 0, 1)`.
|
|
353
|
+
* The real graph is still generated so texture samples are counted first.
|
|
238
354
|
*
|
|
239
|
-
* @param {
|
|
240
|
-
* @return {
|
|
355
|
+
* @param {Node} resultNode - The material's shaded output.
|
|
356
|
+
* @return {Node<vec4>} The complexity ratio in the red channel.
|
|
241
357
|
*/
|
|
242
|
-
export function
|
|
358
|
+
export function shaderComplexityOutput( resultNode ) {
|
|
243
359
|
|
|
244
|
-
|
|
360
|
+
// Generate the shaded graph first so texture samples are counted, then
|
|
361
|
+
// replace the color. A bypass of a value node emits a bare expression
|
|
362
|
+
// statement, which WGSL rejects.
|
|
363
|
+
const shaded = vec4( resultNode ).toVar();
|
|
245
364
|
|
|
246
|
-
|
|
365
|
+
const ratio = new ShaderComplexityRatioNode();
|
|
247
366
|
|
|
248
|
-
|
|
367
|
+
return vec4( ratio, 0, 0, 1 ).add( shaded.mul( 0 ) );
|
|
249
368
|
|
|
250
|
-
|
|
369
|
+
}
|
|
251
370
|
|
|
252
|
-
|
|
371
|
+
/**
|
|
372
|
+
* Same cost as {@link shaderComplexityOutput}, plus one overdraw step in green.
|
|
373
|
+
* The output pass multiplies red by the accumulated green count.
|
|
374
|
+
*
|
|
375
|
+
* @param {Node} resultNode - The material's shaded output.
|
|
376
|
+
* @return {Node<vec4>} Cost ratio in red, one scaled fragment in green.
|
|
377
|
+
*/
|
|
378
|
+
export function shaderComplexityAndQuadsOutput( resultNode ) {
|
|
253
379
|
|
|
254
|
-
|
|
380
|
+
const shaded = vec4( resultNode ).toVar();
|
|
381
|
+
const ratio = new ShaderComplexityRatioNode();
|
|
382
|
+
const step = float( 1 / SHADER_COMPLEXITY_QUAD_COUNT_SCALE );
|
|
255
383
|
|
|
256
|
-
return
|
|
384
|
+
return vec4( ratio, step, 0, 1 ).add( shaded.mul( 0 ) );
|
|
257
385
|
|
|
258
386
|
}
|
|
259
387
|
|
|
260
388
|
/**
|
|
261
|
-
*
|
|
262
|
-
*
|
|
389
|
+
* Reads `1 / quadOverdrawBudget` at code-generation time.
|
|
390
|
+
*
|
|
391
|
+
* @augments Node
|
|
392
|
+
*/
|
|
393
|
+
class QuadOverdrawRatioNode extends Node {
|
|
394
|
+
|
|
395
|
+
static get type() {
|
|
396
|
+
|
|
397
|
+
return 'QuadOverdrawRatioNode';
|
|
398
|
+
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
constructor() {
|
|
402
|
+
|
|
403
|
+
super( 'float' );
|
|
404
|
+
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
generate( builder ) {
|
|
408
|
+
|
|
409
|
+
const budget = builder.renderer.debug.quadOverdrawBudget;
|
|
410
|
+
const safeBudget = ( typeof budget === 'number' && budget > 0 ) ? budget : 1;
|
|
411
|
+
|
|
412
|
+
return ( 1 / safeBudget ).toFixed( 6 );
|
|
413
|
+
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Replaces the shaded color with `vec4(1 / budget, 0, 0, 1)`.
|
|
420
|
+
* The real graph is still generated so clipped fragments are not counted.
|
|
263
421
|
*
|
|
264
422
|
* @param {Node} resultNode - The material's shaded output.
|
|
265
|
-
* @return {Node<vec4>}
|
|
423
|
+
* @return {Node<vec4>} One overdraw step in the red channel.
|
|
266
424
|
*/
|
|
267
|
-
export function
|
|
425
|
+
export function quadOverdrawOutput( resultNode ) {
|
|
268
426
|
|
|
269
|
-
// Generate the shaded graph first so texture samples are counted, then
|
|
270
|
-
// replace the color. A bypass of a value node emits a bare expression
|
|
271
|
-
// statement, which WGSL rejects.
|
|
272
427
|
const shaded = vec4( resultNode ).toVar();
|
|
273
|
-
|
|
274
|
-
const ratio = new ShaderComplexityRatioNode();
|
|
428
|
+
const ratio = new QuadOverdrawRatioNode();
|
|
275
429
|
|
|
276
430
|
return vec4( ratio, 0, 0, 1 ).add( shaded.mul( 0 ) );
|
|
277
431
|
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// WITH_GENESYS
|
|
2
|
+
// Draw call coloration. One stable diffuse color per submitted draw, then lit.
|
|
3
|
+
// !WITH_GENESYS
|
|
4
|
+
|
|
5
|
+
import { Color } from '../../math/Color.js';
|
|
6
|
+
import { diffuseColor, diffuseContribution, metalness, roughness, specularColor, specularColorBlended, specularF90, clearcoat, sheen, iridescence, anisotropy, transmission, retroreflectivity } from '../core/PropertyNode.js';
|
|
7
|
+
import { uniform } from '../core/UniformNode.js';
|
|
8
|
+
import { float, vec3 } from '../tsl/TSLCore.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Draw call coloration. Each submitted draw gets one diffuse color. An instanced mesh is one draw.
|
|
12
|
+
* The color is lit, so lights and shadows still show. Unlit materials stay flat.
|
|
13
|
+
*
|
|
14
|
+
* @type {string}
|
|
15
|
+
*/
|
|
16
|
+
export const DEBUG_VIEW_DRAW_CALL = 'drawCall';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Golden-ratio step. Sequential object ids land on opposite sides of the hue wheel.
|
|
20
|
+
*
|
|
21
|
+
* @type {number}
|
|
22
|
+
*/
|
|
23
|
+
const DRAW_CALL_HUE_STEP = 0.618033988749895;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Saturation of a draw color. High enough that neighboring hues stay apart after lighting.
|
|
27
|
+
*
|
|
28
|
+
* @type {number}
|
|
29
|
+
*/
|
|
30
|
+
const DRAW_CALL_SATURATION = 0.85;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Value of a draw color. Lighting and shadows darken it from here.
|
|
34
|
+
*
|
|
35
|
+
* @type {number}
|
|
36
|
+
*/
|
|
37
|
+
const DRAW_CALL_VALUE = 0.92;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Writes a saturated color for this draw into `color`.
|
|
41
|
+
* Hue walks the wheel by the golden ratio, so consecutive objects do not share a tint.
|
|
42
|
+
* Instances of one mesh share the object id, so they share the color.
|
|
43
|
+
*
|
|
44
|
+
* @param {Color} color - The uniform color, updated in place.
|
|
45
|
+
* @param {Object3D} object - The drawn object.
|
|
46
|
+
* @param {Material} material - The drawn material. A multi-material group is its own draw.
|
|
47
|
+
* @return {Color} `color`.
|
|
48
|
+
*/
|
|
49
|
+
function writeDrawCallColor( color, object, material ) {
|
|
50
|
+
|
|
51
|
+
const hue = ( ( object.id + material.id * 64 ) * DRAW_CALL_HUE_STEP ) % 1;
|
|
52
|
+
const s = DRAW_CALL_SATURATION;
|
|
53
|
+
const v = DRAW_CALL_VALUE;
|
|
54
|
+
const sector = hue * 6;
|
|
55
|
+
const i = Math.floor( sector );
|
|
56
|
+
const f = sector - i;
|
|
57
|
+
const p = v * ( 1 - s );
|
|
58
|
+
const q = v * ( 1 - f * s );
|
|
59
|
+
const t = v * ( 1 - ( 1 - f ) * s );
|
|
60
|
+
|
|
61
|
+
switch ( i % 6 ) {
|
|
62
|
+
|
|
63
|
+
case 0: return color.setRGB( v, t, p );
|
|
64
|
+
case 1: return color.setRGB( q, v, p );
|
|
65
|
+
case 2: return color.setRGB( p, v, t );
|
|
66
|
+
case 3: return color.setRGB( p, q, v );
|
|
67
|
+
case 4: return color.setRGB( t, p, v );
|
|
68
|
+
default: return color.setRGB( v, p, q );
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Replaces albedo with the draw color after the material has written its channels.
|
|
76
|
+
* Lit materials become a matte dielectric in that color. Unlit materials become flat.
|
|
77
|
+
* The color is an object uniform, so meshes that share a material still differ.
|
|
78
|
+
*
|
|
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`.
|
|
82
|
+
*/
|
|
83
|
+
export function applyDrawCallDebug( builder, material ) {
|
|
84
|
+
|
|
85
|
+
const colorNode = uniform( new Color() ).onObjectUpdate( ( { object, material: drawnMaterial }, self ) => {
|
|
86
|
+
|
|
87
|
+
if ( object === null || drawnMaterial === null ) return;
|
|
88
|
+
|
|
89
|
+
return writeDrawCallColor( self.value, object, drawnMaterial );
|
|
90
|
+
|
|
91
|
+
} );
|
|
92
|
+
|
|
93
|
+
diffuseColor.rgb.assign( colorNode );
|
|
94
|
+
|
|
95
|
+
if ( material.lights !== true ) return;
|
|
96
|
+
|
|
97
|
+
metalness.assign( float( 0 ) );
|
|
98
|
+
diffuseContribution.assign( colorNode );
|
|
99
|
+
roughness.assign( float( 1 ) );
|
|
100
|
+
specularColor.assign( vec3( 0 ) );
|
|
101
|
+
specularColorBlended.assign( vec3( 0 ) );
|
|
102
|
+
specularF90.assign( float( 0 ) );
|
|
103
|
+
|
|
104
|
+
// Ambient occlusion belonged to the original material.
|
|
105
|
+
builder.context.ambientOcclusion = null;
|
|
106
|
+
|
|
107
|
+
if ( material.useClearcoat === true ) clearcoat.assign( float( 0 ) );
|
|
108
|
+
|
|
109
|
+
if ( material.useSheen === true ) sheen.assign( vec3( 0 ) );
|
|
110
|
+
|
|
111
|
+
if ( material.useIridescence === true ) iridescence.assign( float( 0 ) );
|
|
112
|
+
|
|
113
|
+
if ( material.useAnisotropy === true ) anisotropy.assign( float( 0 ) );
|
|
114
|
+
|
|
115
|
+
if ( material.useTransmission === true ) transmission.assign( float( 0 ) );
|
|
116
|
+
|
|
117
|
+
if ( material.useRetroreflection === true ) retroreflectivity.assign( float( 0 ) );
|
|
118
|
+
|
|
119
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// WITH_GENESYS
|
|
2
|
+
// Lighting only and detail lighting. Both replace the shaded albedo with a flat gray.
|
|
3
|
+
// !WITH_GENESYS
|
|
4
|
+
|
|
5
|
+
import { diffuseColor, diffuseContribution, metalness, roughness, specularColor, specularColorBlended, specularF90, clearcoat, sheen, iridescence, anisotropy, transmission, retroreflectivity } from '../core/PropertyNode.js';
|
|
6
|
+
import { normalViewGeometry } from '../accessors/Normal.js';
|
|
7
|
+
import { negateOnBackSide } from './FrontFacingNode.js';
|
|
8
|
+
import { float, vec3, Fn } from '../tsl/TSLCore.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Lighting only. Flat gray, no specular, geometry normals. Material detail is dropped.
|
|
12
|
+
*
|
|
13
|
+
* @type {string}
|
|
14
|
+
*/
|
|
15
|
+
export const DEBUG_VIEW_LIGHTING_ONLY = 'lightingOnly';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Detail lighting. Flat gray and a constant specular, with normal maps and roughness kept.
|
|
19
|
+
*
|
|
20
|
+
* @type {string}
|
|
21
|
+
*/
|
|
22
|
+
export const DEBUG_VIEW_DETAIL_LIGHTING = 'detailLighting';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Neutral albedo shared by both views. Matches Unreal's `LightingOnlyBrightness`.
|
|
26
|
+
*
|
|
27
|
+
* @type {number}
|
|
28
|
+
*/
|
|
29
|
+
const LIGHTING_ONLY_BRIGHTNESS = 0.3;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Specular color used by detail lighting. Unreal writes `0.1` into the specular override.
|
|
33
|
+
*
|
|
34
|
+
* @type {number}
|
|
35
|
+
*/
|
|
36
|
+
const DETAIL_LIGHTING_SPECULAR = 0.1;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Geometry normal for lighting only, so normal maps and `normalNode` do not shade the surface.
|
|
40
|
+
*
|
|
41
|
+
* @type {Node<vec3>}
|
|
42
|
+
*/
|
|
43
|
+
export const lightingOnlyNormal = /*@__PURE__*/ Fn( ( builder ) => {
|
|
44
|
+
|
|
45
|
+
let node = normalViewGeometry;
|
|
46
|
+
|
|
47
|
+
if ( builder.isFlatShading() !== true ) {
|
|
48
|
+
|
|
49
|
+
node = negateOnBackSide( node );
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return node;
|
|
54
|
+
|
|
55
|
+
}, 'vec3' );
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Replaces albedo and specular after the material has written its channels.
|
|
59
|
+
* Lit materials become a dielectric gray. Unlit materials become flat gray.
|
|
60
|
+
*
|
|
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`.
|
|
64
|
+
* @param {string} view - `renderer.debug.view`.
|
|
65
|
+
*/
|
|
66
|
+
export function applyLightingDebug( builder, material, view ) {
|
|
67
|
+
|
|
68
|
+
const gray = vec3( LIGHTING_ONLY_BRIGHTNESS );
|
|
69
|
+
|
|
70
|
+
diffuseColor.rgb.assign( gray );
|
|
71
|
+
|
|
72
|
+
if ( material.lights !== true ) return;
|
|
73
|
+
|
|
74
|
+
metalness.assign( float( 0 ) );
|
|
75
|
+
diffuseContribution.assign( gray );
|
|
76
|
+
|
|
77
|
+
if ( view === DEBUG_VIEW_LIGHTING_ONLY ) {
|
|
78
|
+
|
|
79
|
+
roughness.assign( float( 1 ) );
|
|
80
|
+
specularColor.assign( vec3( 0 ) );
|
|
81
|
+
specularColorBlended.assign( vec3( 0 ) );
|
|
82
|
+
specularF90.assign( float( 0 ) );
|
|
83
|
+
|
|
84
|
+
// Ambient occlusion was stored for the lighting model. Lighting only has no material.
|
|
85
|
+
builder.context.ambientOcclusion = null;
|
|
86
|
+
|
|
87
|
+
if ( material.useClearcoat === true ) clearcoat.assign( float( 0 ) );
|
|
88
|
+
|
|
89
|
+
if ( material.useSheen === true ) sheen.assign( vec3( 0 ) );
|
|
90
|
+
|
|
91
|
+
if ( material.useIridescence === true ) iridescence.assign( float( 0 ) );
|
|
92
|
+
|
|
93
|
+
if ( material.useAnisotropy === true ) anisotropy.assign( float( 0 ) );
|
|
94
|
+
|
|
95
|
+
if ( material.useTransmission === true ) transmission.assign( float( 0 ) );
|
|
96
|
+
|
|
97
|
+
if ( material.useRetroreflection === true ) retroreflectivity.assign( float( 0 ) );
|
|
98
|
+
|
|
99
|
+
} else {
|
|
100
|
+
|
|
101
|
+
const specular = vec3( DETAIL_LIGHTING_SPECULAR );
|
|
102
|
+
|
|
103
|
+
specularColor.assign( specular );
|
|
104
|
+
specularColorBlended.assign( specular );
|
|
105
|
+
specularF90.assign( float( 1 ) );
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
}
|
|
@@ -7,6 +7,9 @@ import { Mesh } from '../../objects/Mesh.js';
|
|
|
7
7
|
import { SphereGeometry } from '../../geometries/SphereGeometry.js';
|
|
8
8
|
import { BackSide } from '../../constants.js';
|
|
9
9
|
import { error } from '../../utils.js';
|
|
10
|
+
// WITH_GENESYS
|
|
11
|
+
import { debugViewAccumulates } from '../../nodes/display/ComplexityDebug.js';
|
|
12
|
+
// !WITH_GENESYS
|
|
10
13
|
|
|
11
14
|
const _clearColor = /*@__PURE__*/ new Color4();
|
|
12
15
|
|
|
@@ -193,7 +196,7 @@ class Background extends DataMap {
|
|
|
193
196
|
|
|
194
197
|
// WITH_GENESYS
|
|
195
198
|
// The background is depth-tested off, so additive shader complexity would add it to every pixel.
|
|
196
|
-
if ( renderer.debug.view !==
|
|
199
|
+
if ( debugViewAccumulates( renderer.debug.view ) !== true ) {
|
|
197
200
|
|
|
198
201
|
renderList.unshift( backgroundMesh, backgroundMesh.geometry, backgroundMesh.material, 0, 0, null, null );
|
|
199
202
|
|
|
@@ -224,7 +227,7 @@ class Background extends DataMap {
|
|
|
224
227
|
//
|
|
225
228
|
|
|
226
229
|
// WITH_GENESYS
|
|
227
|
-
if ( renderer.debug.view
|
|
230
|
+
if ( debugViewAccumulates( renderer.debug.view ) ) {
|
|
228
231
|
|
|
229
232
|
_clearColor.set( 0, 0, 0, 1 );
|
|
230
233
|
|
|
@@ -952,7 +952,7 @@ class RenderObject {
|
|
|
952
952
|
|
|
953
953
|
// WITH_GENESYS
|
|
954
954
|
// hash() xors each argument as a number, so a view name has to be hashed first.
|
|
955
|
-
cacheKey = hash( cacheKey, hashString( this.renderer.debug.view ), this.renderer.debug.shaderComplexityBudget );
|
|
955
|
+
cacheKey = hash( cacheKey, hashString( this.renderer.debug.view ), hashString( this.renderer.debug.buffer ), this.renderer.debug.shaderComplexityBudget, this.renderer.debug.quadOverdrawBudget );
|
|
956
956
|
// !WITH_GENESYS
|
|
957
957
|
|
|
958
958
|
return cacheKey;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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 =
|
|
235
|
+
this._toneMapping = toneMapping;
|
|
221
236
|
this.needsUpdate = true;
|
|
222
237
|
|
|
223
238
|
}
|
|
224
239
|
|
|
225
|
-
if ( this._outputColorSpace !==
|
|
240
|
+
if ( this._outputColorSpace !== outputColorSpace ) {
|
|
226
241
|
|
|
227
|
-
this._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,7 +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 {
|
|
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';
|
|
41
42
|
// !WITH_GENESYS
|
|
42
43
|
import { reference } from '../../nodes/accessors/ReferenceNode.js';
|
|
43
44
|
import { highpModelNormalViewMatrix, highpModelViewMatrix } from '../../nodes/accessors/ModelNode.js';
|
|
@@ -744,8 +745,10 @@ class Renderer {
|
|
|
744
745
|
* @property {?Function} onNodeBuilderCreated - A callback function that is executed after a node builder has been created and before it is built.
|
|
745
746
|
* @property {?Function} onShaderError - A callback function that is executed when a shader error happens. Only supported with WebGL 2 right now.
|
|
746
747
|
* @property {Function} getShaderAsync - Allows the get the raw shader code for the given scene, camera and 3D object.
|
|
747
|
-
* @property {string} view - Debug view. `shaderComplexity` and `
|
|
748
|
+
* @property {string} view - Debug view. `shaderComplexity`, `lightingComplexity`, `quadOverdraw`, and `shaderComplexityAndQuads` replace the shaded color with a heatmap. `shaderComplexityAndQuads` multiplies the shader cost by the overdraw count. `bufferVisualization` shows one material channel. `lightingOnly` and `detailLighting` light a flat gray surface. `drawCall` lights each submitted draw with its own diffuse color.
|
|
749
|
+
* @property {string} buffer - Channel drawn by `bufferVisualization`: `baseColor`, `worldNormal`, `roughness`, `metallic`, `ambientOcclusion`, or `emissive`.
|
|
748
750
|
* @property {number} shaderComplexityBudget - Proxy budget that fills the shader-complexity ramp.
|
|
751
|
+
* @property {number} quadOverdrawBudget - Overlapping fragments that fill the quad-overdraw ramp.
|
|
749
752
|
*/
|
|
750
753
|
|
|
751
754
|
/**
|
|
@@ -762,7 +765,9 @@ class Renderer {
|
|
|
762
765
|
onShaderError: null,
|
|
763
766
|
// WITH_GENESYS
|
|
764
767
|
view: DEBUG_VIEW_NONE,
|
|
768
|
+
buffer: DEFAULT_BUFFER,
|
|
765
769
|
shaderComplexityBudget: DEFAULT_SHADER_COMPLEXITY_BUDGET,
|
|
770
|
+
quadOverdrawBudget: DEFAULT_QUAD_OVERDRAW_BUDGET,
|
|
766
771
|
// !WITH_GENESYS
|
|
767
772
|
getShaderAsync: async ( scene, camera, object ) => {
|
|
768
773
|
|
|
@@ -2699,10 +2704,9 @@ class Renderer {
|
|
|
2699
2704
|
const useColorSpace = this.currentColorSpace !== ColorManagement.workingColorSpace;
|
|
2700
2705
|
|
|
2701
2706
|
// WITH_GENESYS
|
|
2702
|
-
//
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
return useToneMapping || useColorSpace || shaderComplexity;
|
|
2707
|
+
// Accumulating views write a scalar into an intermediate target, then the output pass colorizes it.
|
|
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 );
|
|
2706
2710
|
// !WITH_GENESYS
|
|
2707
2711
|
// return useToneMapping || useColorSpace;
|
|
2708
2712
|
|
|
@@ -2756,9 +2760,7 @@ class Renderer {
|
|
|
2756
2760
|
get currentToneMapping() {
|
|
2757
2761
|
|
|
2758
2762
|
// WITH_GENESYS
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
if ( view === DEBUG_VIEW_SHADER_COMPLEXITY || view === DEBUG_VIEW_LIGHTING_COMPLEXITY ) {
|
|
2763
|
+
if ( debugViewSkipsToneMapping( this.debug.view ) ) {
|
|
2762
2764
|
|
|
2763
2765
|
return NoToneMapping;
|
|
2764
2766
|
|