@gnsx/three 0.184.8 → 0.184.10
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.tsl.js +5 -1
- package/build/three.tsl.min.js +1 -1
- package/build/three.webgpu.js +480 -8
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +480 -8
- package/build/three.webgpu.nodes.min.js +1 -1
- package/examples/jsm/helpers/LightProbeGridCubeMapHelper.js +222 -0
- package/examples/jsm/helpers/LightProbeGridHelper.js +223 -99
- package/examples/jsm/inspector/tabs/Settings.js +1 -1
- package/examples/jsm/lighting/LightProbeGrid.js +628 -84
- package/examples/jsm/tsl/lighting/DynamicLightsNode.js +19 -1
- package/package.json +1 -1
- package/src/Three.TSL.js +4 -0
- package/src/nodes/Nodes.js +3 -0
- package/src/nodes/TSL.js +4 -0
- package/src/nodes/accessors/CubeTextureNode.js +7 -1
- package/src/nodes/accessors/TextureNode.js +21 -1
- package/src/nodes/functions/material/getLightProbeGridIrradiance.js +68 -0
- package/src/nodes/lighting/LightProbeGridNode.js +137 -0
- package/src/nodes/lighting/LightsNode.js +98 -1
- package/src/renderers/common/Background.js +33 -0
- package/src/renderers/common/RenderList.js +28 -0
- package/src/renderers/common/RenderObjects.js +47 -0
- package/src/renderers/common/Renderer.js +32 -2
- package/src/renderers/common/nodes/NodeManager.js +24 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BoxGeometry,
|
|
3
|
+
Mesh,
|
|
4
|
+
Object3D,
|
|
5
|
+
ShaderMaterial,
|
|
6
|
+
Vector3
|
|
7
|
+
} from 'three';
|
|
8
|
+
import { NodeMaterial } from 'three/webgpu';
|
|
9
|
+
import {
|
|
10
|
+
cubeTexture,
|
|
11
|
+
Fn,
|
|
12
|
+
normalWorld,
|
|
13
|
+
vec4
|
|
14
|
+
} from 'three/tsl';
|
|
15
|
+
|
|
16
|
+
function createNodeMaterial( texture ) {
|
|
17
|
+
|
|
18
|
+
const fragmentNode = Fn( () => {
|
|
19
|
+
|
|
20
|
+
return vec4( cubeTexture( texture, normalWorld ).rgb, 1.0 );
|
|
21
|
+
|
|
22
|
+
} )();
|
|
23
|
+
|
|
24
|
+
const material = new NodeMaterial();
|
|
25
|
+
material.fragmentNode = fragmentNode;
|
|
26
|
+
|
|
27
|
+
return material;
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function createShaderMaterial( texture ) {
|
|
32
|
+
|
|
33
|
+
return new ShaderMaterial( {
|
|
34
|
+
|
|
35
|
+
uniforms: {
|
|
36
|
+
|
|
37
|
+
cubeTexture: { value: texture }
|
|
38
|
+
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
vertexShader: /* glsl */`
|
|
42
|
+
|
|
43
|
+
varying vec3 vWorldNormal;
|
|
44
|
+
|
|
45
|
+
void main() {
|
|
46
|
+
|
|
47
|
+
vWorldNormal = normalize( mat3( modelMatrix ) * normal );
|
|
48
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
`,
|
|
53
|
+
|
|
54
|
+
fragmentShader: /* glsl */`
|
|
55
|
+
|
|
56
|
+
precision highp float;
|
|
57
|
+
|
|
58
|
+
uniform samplerCube cubeTexture;
|
|
59
|
+
|
|
60
|
+
varying vec3 vWorldNormal;
|
|
61
|
+
|
|
62
|
+
void main() {
|
|
63
|
+
|
|
64
|
+
vec3 direction = normalize( vWorldNormal );
|
|
65
|
+
vec3 color = textureCube( cubeTexture, direction ).rgb;
|
|
66
|
+
|
|
67
|
+
gl_FragColor = vec4( color, 1.0 );
|
|
68
|
+
|
|
69
|
+
#include <tonemapping_fragment>
|
|
70
|
+
#include <colorspace_fragment>
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
`
|
|
75
|
+
|
|
76
|
+
} );
|
|
77
|
+
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Visualizes an {@link LightProbeGrid} by rendering a cube at each
|
|
82
|
+
* probe position, displaying the captured cube map on each face.
|
|
83
|
+
*
|
|
84
|
+
* Requires the probe grid to be baked with `retainCubemaps: true` option.
|
|
85
|
+
*
|
|
86
|
+
* ```js
|
|
87
|
+
* // First bake with retainCubemaps option
|
|
88
|
+
* await probeGrid.bake( renderer, scene, { retainCubemaps: true } );
|
|
89
|
+
*
|
|
90
|
+
* // Then create the helper
|
|
91
|
+
* const helper = new LightProbeGridCubeMapHelper( probeGrid );
|
|
92
|
+
* scene.add( helper );
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @augments Object3D
|
|
96
|
+
* @three_import import { LightProbeGridCubeMapHelper } from 'three/addons/helpers/LightProbeGridCubeMapHelper.js';
|
|
97
|
+
*/
|
|
98
|
+
class LightProbeGridCubeMapHelper extends Object3D {
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Constructs a new light probe grid cube map helper.
|
|
102
|
+
*
|
|
103
|
+
* @param {LightProbeGrid} probes - The probe grid to visualize.
|
|
104
|
+
* @param {number} [cubeSize=0.15] - The size of each probe cube.
|
|
105
|
+
* @param {Object} [options] - The helper options.
|
|
106
|
+
* @param {boolean} [options.webgpu=false] - Whether to use a WebGPU-compatible node material.
|
|
107
|
+
*/
|
|
108
|
+
constructor( probes, cubeSize = 0.15, options = {} ) {
|
|
109
|
+
|
|
110
|
+
super();
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The probe grid to visualize.
|
|
114
|
+
*
|
|
115
|
+
* @type {LightProbeGrid}
|
|
116
|
+
*/
|
|
117
|
+
this.probes = probes;
|
|
118
|
+
|
|
119
|
+
this.type = 'LightProbeGridCubeMapHelper';
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The size of each probe cube.
|
|
123
|
+
*
|
|
124
|
+
* @type {number}
|
|
125
|
+
*/
|
|
126
|
+
this.cubeSize = cubeSize;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Whether to use WebGPU node materials.
|
|
130
|
+
*
|
|
131
|
+
* @private
|
|
132
|
+
* @type {boolean}
|
|
133
|
+
*/
|
|
134
|
+
this._webgpu = options.webgpu === true;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Shared cube geometry.
|
|
138
|
+
*
|
|
139
|
+
* @private
|
|
140
|
+
* @type {BoxGeometry}
|
|
141
|
+
*/
|
|
142
|
+
this._geometry = new BoxGeometry( cubeSize, cubeSize, cubeSize );
|
|
143
|
+
|
|
144
|
+
this.update();
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Rebuilds cube meshes from the current probe grid.
|
|
150
|
+
* Call this after changing `probes` or after re-baking with `retainCubemaps: true`.
|
|
151
|
+
*/
|
|
152
|
+
update() {
|
|
153
|
+
|
|
154
|
+
this._clearCubes();
|
|
155
|
+
|
|
156
|
+
const probes = this.probes;
|
|
157
|
+
const res = probes.resolution;
|
|
158
|
+
const cubeTextures = probes.cubeTextures || [];
|
|
159
|
+
const probePos = new Vector3();
|
|
160
|
+
|
|
161
|
+
let i = 0;
|
|
162
|
+
|
|
163
|
+
for ( let iz = 0; iz < res.z; iz ++ ) {
|
|
164
|
+
|
|
165
|
+
for ( let iy = 0; iy < res.y; iy ++ ) {
|
|
166
|
+
|
|
167
|
+
for ( let ix = 0; ix < res.x; ix ++ ) {
|
|
168
|
+
|
|
169
|
+
const texture = cubeTextures[ i ];
|
|
170
|
+
|
|
171
|
+
if ( texture !== undefined ) {
|
|
172
|
+
|
|
173
|
+
const material = this._webgpu === true ? createNodeMaterial( texture ) : createShaderMaterial( texture );
|
|
174
|
+
const cube = new Mesh( this._geometry, material );
|
|
175
|
+
|
|
176
|
+
probes.getProbePosition( ix, iy, iz, probePos );
|
|
177
|
+
cube.position.copy( probePos );
|
|
178
|
+
this.add( cube );
|
|
179
|
+
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
i ++;
|
|
183
|
+
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Frees the GPU-related resources allocated by this instance. Call this
|
|
194
|
+
* method whenever this instance is no longer used in your app.
|
|
195
|
+
*/
|
|
196
|
+
dispose() {
|
|
197
|
+
|
|
198
|
+
this._clearCubes();
|
|
199
|
+
this._geometry.dispose();
|
|
200
|
+
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Removes all cube children and disposes their materials.
|
|
205
|
+
*
|
|
206
|
+
* @private
|
|
207
|
+
*/
|
|
208
|
+
_clearCubes() {
|
|
209
|
+
|
|
210
|
+
for ( const child of this.children ) {
|
|
211
|
+
|
|
212
|
+
child.material.dispose();
|
|
213
|
+
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.clear();
|
|
217
|
+
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export { LightProbeGridCubeMapHelper };
|
|
@@ -1,136 +1,195 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Data3DTexture,
|
|
3
|
+
FloatType,
|
|
2
4
|
InstancedBufferAttribute,
|
|
3
5
|
InstancedMesh,
|
|
6
|
+
LinearFilter,
|
|
4
7
|
Matrix4,
|
|
8
|
+
RGBAFormat,
|
|
5
9
|
ShaderMaterial,
|
|
6
10
|
SphereGeometry,
|
|
7
11
|
Vector3
|
|
8
12
|
} from 'three';
|
|
13
|
+
// WITH_GENESYS
|
|
14
|
+
import { NodeMaterial } from 'three/webgpu';
|
|
15
|
+
import {
|
|
16
|
+
attribute,
|
|
17
|
+
Fn,
|
|
18
|
+
getLightProbeGridIrradianceAtUV,
|
|
19
|
+
normalWorld,
|
|
20
|
+
texture3D,
|
|
21
|
+
uniform,
|
|
22
|
+
vec4
|
|
23
|
+
} from 'three/tsl';
|
|
24
|
+
// !WITH_GENESYS
|
|
25
|
+
|
|
26
|
+
// WITH_GENESYS
|
|
27
|
+
const _emptyTexture = /*@__PURE__*/ new Data3DTexture( new Float32Array( 1 * 1 * 28 * 4 ), 1, 1, 28 );
|
|
28
|
+
|
|
29
|
+
_emptyTexture.format = RGBAFormat;
|
|
30
|
+
_emptyTexture.type = FloatType;
|
|
31
|
+
_emptyTexture.minFilter = LinearFilter;
|
|
32
|
+
_emptyTexture.magFilter = LinearFilter;
|
|
33
|
+
_emptyTexture.needsUpdate = true;
|
|
34
|
+
|
|
35
|
+
function createNodeMaterial( probes ) {
|
|
36
|
+
|
|
37
|
+
const probesSH = texture3D( probes.texture || _emptyTexture );
|
|
38
|
+
const probesResolution = uniform( new Vector3( 1, 1, 1 ) );
|
|
39
|
+
const instanceUVW = attribute( 'instanceUVW', 'vec3' );
|
|
40
|
+
|
|
41
|
+
const fragmentNode = Fn( () => {
|
|
42
|
+
|
|
43
|
+
const irradiance = getLightProbeGridIrradianceAtUV( {
|
|
44
|
+
probesSH,
|
|
45
|
+
probesResolution,
|
|
46
|
+
gridUVW: instanceUVW,
|
|
47
|
+
worldNormal: normalWorld
|
|
48
|
+
} );
|
|
9
49
|
|
|
10
|
-
|
|
11
|
-
* Visualizes an {@link LightProbeGrid} by rendering a sphere at each
|
|
12
|
-
* probe position, shaded with the probe's L1 spherical harmonics.
|
|
13
|
-
*
|
|
14
|
-
* Uses a single `InstancedMesh` draw call for all probes.
|
|
15
|
-
*
|
|
16
|
-
* ```js
|
|
17
|
-
* const helper = new LightProbeGridHelper( probes );
|
|
18
|
-
* scene.add( helper );
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* @augments InstancedMesh
|
|
22
|
-
* @three_import import { LightProbeGridHelper } from 'three/addons/helpers/LightProbeGridHelper.js';
|
|
23
|
-
*/
|
|
24
|
-
class LightProbeGridHelper extends InstancedMesh {
|
|
50
|
+
return vec4( irradiance, 1.0 );
|
|
25
51
|
|
|
26
|
-
|
|
27
|
-
* Constructs a new irradiance probe grid helper.
|
|
28
|
-
*
|
|
29
|
-
* @param {LightProbeGrid} probes - The probe grid to visualize.
|
|
30
|
-
* @param {number} [sphereSize=0.12] - The radius of each probe sphere.
|
|
31
|
-
*/
|
|
32
|
-
constructor( probes, sphereSize = 0.12 ) {
|
|
52
|
+
} )();
|
|
33
53
|
|
|
34
|
-
|
|
54
|
+
const material = new NodeMaterial();
|
|
55
|
+
material.fragmentNode = fragmentNode;
|
|
35
56
|
|
|
36
|
-
|
|
57
|
+
return { material, probesSH, probesResolution };
|
|
37
58
|
|
|
38
|
-
|
|
59
|
+
}
|
|
60
|
+
// !WITH_GENESYS
|
|
39
61
|
|
|
40
|
-
|
|
41
|
-
probesResolution: { value: new Vector3() },
|
|
62
|
+
function createShaderMaterial() {
|
|
42
63
|
|
|
43
|
-
|
|
64
|
+
return new ShaderMaterial( {
|
|
44
65
|
|
|
45
|
-
|
|
66
|
+
uniforms: {
|
|
46
67
|
|
|
47
|
-
|
|
68
|
+
probesSH: { value: null },
|
|
69
|
+
probesResolution: { value: new Vector3() },
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
varying vec3 vUVW;
|
|
71
|
+
},
|
|
51
72
|
|
|
52
|
-
|
|
73
|
+
vertexShader: /* glsl */`
|
|
53
74
|
|
|
54
|
-
|
|
55
|
-
vWorldNormal = normalize( mat3( modelMatrix ) * normal );
|
|
56
|
-
gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4( position, 1.0 );
|
|
75
|
+
attribute vec3 instanceUVW;
|
|
57
76
|
|
|
58
|
-
|
|
77
|
+
varying vec3 vWorldNormal;
|
|
78
|
+
varying vec3 vUVW;
|
|
79
|
+
|
|
80
|
+
void main() {
|
|
59
81
|
|
|
60
|
-
|
|
82
|
+
vUVW = instanceUVW;
|
|
83
|
+
vWorldNormal = normalize( mat3( modelMatrix ) * normal );
|
|
84
|
+
gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4( position, 1.0 );
|
|
61
85
|
|
|
62
|
-
|
|
86
|
+
}
|
|
63
87
|
|
|
64
|
-
|
|
88
|
+
`,
|
|
65
89
|
|
|
66
|
-
|
|
67
|
-
uniform vec3 probesResolution;
|
|
90
|
+
fragmentShader: /* glsl */`
|
|
68
91
|
|
|
69
|
-
|
|
70
|
-
varying vec3 vUVW;
|
|
92
|
+
precision highp sampler3D;
|
|
71
93
|
|
|
72
|
-
|
|
94
|
+
uniform sampler3D probesSH;
|
|
95
|
+
uniform vec3 probesResolution;
|
|
73
96
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
float paddedSlices = nz + 2.0;
|
|
77
|
-
float atlasDepth = 7.0 * paddedSlices;
|
|
78
|
-
float uvZBase = vUVW.z * nz + 1.0;
|
|
97
|
+
varying vec3 vWorldNormal;
|
|
98
|
+
varying vec3 vUVW;
|
|
79
99
|
|
|
80
|
-
|
|
81
|
-
vec4 s1 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + paddedSlices ) / atlasDepth ) );
|
|
82
|
-
vec4 s2 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) );
|
|
83
|
-
vec4 s3 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) );
|
|
84
|
-
vec4 s4 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) );
|
|
85
|
-
vec4 s5 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) );
|
|
86
|
-
vec4 s6 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) );
|
|
100
|
+
void main() {
|
|
87
101
|
|
|
88
|
-
|
|
102
|
+
// Atlas UV mapping — must match lightprobes_pars_fragment.glsl.js
|
|
103
|
+
float nz = probesResolution.z;
|
|
104
|
+
float paddedSlices = nz + 2.0;
|
|
105
|
+
float atlasDepth = 7.0 * paddedSlices;
|
|
106
|
+
float uvZBase = vUVW.z * nz + 1.0;
|
|
89
107
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
vec3 c7 = s5.yzw;
|
|
98
|
-
vec3 c8 = s6.xyz;
|
|
108
|
+
vec4 s0 = texture( probesSH, vec3( vUVW.xy, ( uvZBase ) / atlasDepth ) );
|
|
109
|
+
vec4 s1 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + paddedSlices ) / atlasDepth ) );
|
|
110
|
+
vec4 s2 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) );
|
|
111
|
+
vec4 s3 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) );
|
|
112
|
+
vec4 s4 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) );
|
|
113
|
+
vec4 s5 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) );
|
|
114
|
+
vec4 s6 = texture( probesSH, vec3( vUVW.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) );
|
|
99
115
|
|
|
100
|
-
|
|
116
|
+
// Unpack 9 vec3 SH L2 coefficients
|
|
101
117
|
|
|
102
|
-
|
|
118
|
+
vec3 c0 = s0.xyz;
|
|
119
|
+
vec3 c1 = vec3( s0.w, s1.xy );
|
|
120
|
+
vec3 c2 = vec3( s1.zw, s2.x );
|
|
121
|
+
vec3 c3 = s2.yzw;
|
|
122
|
+
vec3 c4 = s3.xyz;
|
|
123
|
+
vec3 c5 = vec3( s3.w, s4.xy );
|
|
124
|
+
vec3 c6 = vec3( s4.zw, s5.x );
|
|
125
|
+
vec3 c7 = s5.yzw;
|
|
126
|
+
vec3 c8 = s6.xyz;
|
|
103
127
|
|
|
104
|
-
|
|
105
|
-
vec3 result = c0 * 0.886227;
|
|
128
|
+
vec3 n = normalize( vWorldNormal );
|
|
106
129
|
|
|
107
|
-
|
|
108
|
-
result += c1 * 2.0 * 0.511664 * y;
|
|
109
|
-
result += c2 * 2.0 * 0.511664 * z;
|
|
110
|
-
result += c3 * 2.0 * 0.511664 * x;
|
|
130
|
+
float x = n.x, y = n.y, z = n.z;
|
|
111
131
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
result += c5 * 2.0 * 0.429043 * y * z;
|
|
115
|
-
result += c6 * ( 0.743125 * z * z - 0.247708 );
|
|
116
|
-
result += c7 * 2.0 * 0.429043 * x * z;
|
|
117
|
-
result += c8 * 0.429043 * ( x * x - y * y );
|
|
132
|
+
// band 0
|
|
133
|
+
vec3 result = c0 * 0.886227;
|
|
118
134
|
|
|
119
|
-
|
|
135
|
+
// band 1,
|
|
136
|
+
result += c1 * 2.0 * 0.511664 * y;
|
|
137
|
+
result += c2 * 2.0 * 0.511664 * z;
|
|
138
|
+
result += c3 * 2.0 * 0.511664 * x;
|
|
120
139
|
|
|
121
|
-
|
|
122
|
-
|
|
140
|
+
// band 2,
|
|
141
|
+
result += c4 * 2.0 * 0.429043 * x * y;
|
|
142
|
+
result += c5 * 2.0 * 0.429043 * y * z;
|
|
143
|
+
result += c6 * ( 0.743125 * z * z - 0.247708 );
|
|
144
|
+
result += c7 * 2.0 * 0.429043 * x * z;
|
|
145
|
+
result += c8 * 0.429043 * ( x * x - y * y );
|
|
123
146
|
|
|
124
|
-
|
|
147
|
+
gl_FragColor = vec4( max( result, vec3( 0.0 ) ), 1.0 );
|
|
125
148
|
|
|
126
|
-
|
|
149
|
+
#include <tonemapping_fragment>
|
|
150
|
+
#include <colorspace_fragment>
|
|
127
151
|
|
|
128
|
-
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
`
|
|
155
|
+
|
|
156
|
+
} );
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Visualizes an {@link LightProbeGrid} by rendering a sphere at each
|
|
162
|
+
* probe position, shaded with the probe's L1 spherical harmonics.
|
|
163
|
+
*
|
|
164
|
+
* Uses a single `InstancedMesh` draw call for all probes.
|
|
165
|
+
*
|
|
166
|
+
* ```js
|
|
167
|
+
* const helper = new LightProbeGridHelper( probes );
|
|
168
|
+
* scene.add( helper );
|
|
169
|
+
* ```
|
|
170
|
+
*
|
|
171
|
+
* @augments InstancedMesh
|
|
172
|
+
* @three_import import { LightProbeGridHelper } from 'three/addons/helpers/LightProbeGridHelper.js';
|
|
173
|
+
*/
|
|
174
|
+
class LightProbeGridHelper extends InstancedMesh {
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Constructs a new irradiance probe grid helper.
|
|
178
|
+
*
|
|
179
|
+
* @param {LightProbeGrid} probes - The probe grid to visualize.
|
|
180
|
+
* @param {number} [sphereSize=0.12] - The radius of each probe sphere.
|
|
181
|
+
* @param {Object} [options] - The helper options.
|
|
182
|
+
* @param {boolean} [options.webgpu=false] - Whether to use a WebGPU-compatible node material.
|
|
183
|
+
*/
|
|
184
|
+
constructor( probes, sphereSize = 0.12, options = {} ) {
|
|
185
|
+
|
|
186
|
+
const geometry = new SphereGeometry( sphereSize, 16, 16 );
|
|
187
|
+
const materialState = options.webgpu === true ? createNodeMaterial( probes ) : { material: createShaderMaterial() };
|
|
129
188
|
|
|
130
189
|
const res = probes.resolution;
|
|
131
190
|
const count = res.x * res.y * res.z;
|
|
132
191
|
|
|
133
|
-
super( geometry, material, count );
|
|
192
|
+
super( geometry, materialState.material, count );
|
|
134
193
|
|
|
135
194
|
/**
|
|
136
195
|
* The probe grid to visualize.
|
|
@@ -141,6 +200,11 @@ class LightProbeGridHelper extends InstancedMesh {
|
|
|
141
200
|
|
|
142
201
|
this.type = 'LightProbeGridHelper';
|
|
143
202
|
|
|
203
|
+
// WITH_GENESYS
|
|
204
|
+
this._probesSH = materialState.probesSH || null;
|
|
205
|
+
this._probesResolution = materialState.probesResolution || null;
|
|
206
|
+
// !WITH_GENESYS
|
|
207
|
+
|
|
144
208
|
this.update();
|
|
145
209
|
|
|
146
210
|
}
|
|
@@ -155,17 +219,17 @@ class LightProbeGridHelper extends InstancedMesh {
|
|
|
155
219
|
const res = probes.resolution;
|
|
156
220
|
const count = res.x * res.y * res.z;
|
|
157
221
|
|
|
158
|
-
// Resize instance matrix buffer if needed
|
|
159
|
-
|
|
160
222
|
if ( this.instanceMatrix.count !== count ) {
|
|
161
223
|
|
|
224
|
+
// WITH_GENESYS
|
|
225
|
+
this.instanceMatrix.dispose();
|
|
226
|
+
// !WITH_GENESYS
|
|
162
227
|
this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
|
|
163
228
|
|
|
164
229
|
}
|
|
165
230
|
|
|
166
231
|
this.count = count;
|
|
167
232
|
|
|
168
|
-
const uvwArray = new Float32Array( count * 3 );
|
|
169
233
|
const matrix = new Matrix4();
|
|
170
234
|
const probePos = new Vector3();
|
|
171
235
|
|
|
@@ -177,11 +241,6 @@ class LightProbeGridHelper extends InstancedMesh {
|
|
|
177
241
|
|
|
178
242
|
for ( let ix = 0; ix < res.x; ix ++ ) {
|
|
179
243
|
|
|
180
|
-
// Remap to texel centers (must match lightprobes_pars_fragment.glsl.js)
|
|
181
|
-
uvwArray[ i * 3 ] = ( ix + 0.5 ) / res.x;
|
|
182
|
-
uvwArray[ i * 3 + 1 ] = ( iy + 0.5 ) / res.y;
|
|
183
|
-
uvwArray[ i * 3 + 2 ] = ( iz + 0.5 ) / res.z;
|
|
184
|
-
|
|
185
244
|
probes.getProbePosition( ix, iy, iz, probePos );
|
|
186
245
|
matrix.makeTranslation( probePos.x, probePos.y, probePos.z );
|
|
187
246
|
this.setMatrixAt( i, matrix );
|
|
@@ -196,12 +255,65 @@ class LightProbeGridHelper extends InstancedMesh {
|
|
|
196
255
|
|
|
197
256
|
this.instanceMatrix.needsUpdate = true;
|
|
198
257
|
|
|
199
|
-
this.geometry.
|
|
258
|
+
let instanceUVW = this.geometry.getAttribute( 'instanceUVW' );
|
|
259
|
+
|
|
260
|
+
if ( instanceUVW === undefined || instanceUVW.count !== count ) {
|
|
261
|
+
|
|
262
|
+
// WITH_GENESYS
|
|
263
|
+
if ( instanceUVW !== undefined ) {
|
|
264
|
+
|
|
265
|
+
instanceUVW.dispose();
|
|
266
|
+
|
|
267
|
+
}
|
|
268
|
+
// !WITH_GENESYS
|
|
269
|
+
|
|
270
|
+
const uvwArray = new Float32Array( count * 3 );
|
|
271
|
+
|
|
272
|
+
i = 0;
|
|
273
|
+
|
|
274
|
+
for ( let iz = 0; iz < res.z; iz ++ ) {
|
|
275
|
+
|
|
276
|
+
for ( let iy = 0; iy < res.y; iy ++ ) {
|
|
277
|
+
|
|
278
|
+
for ( let ix = 0; ix < res.x; ix ++ ) {
|
|
279
|
+
|
|
280
|
+
// Remap to texel centers (must match lightprobes_pars_fragment.glsl.js)
|
|
281
|
+
uvwArray[ i * 3 ] = ( ix + 0.5 ) / res.x;
|
|
282
|
+
uvwArray[ i * 3 + 1 ] = ( iy + 0.5 ) / res.y;
|
|
283
|
+
uvwArray[ i * 3 + 2 ] = ( iz + 0.5 ) / res.z;
|
|
284
|
+
|
|
285
|
+
i ++;
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
instanceUVW = new InstancedBufferAttribute( uvwArray, 3 );
|
|
294
|
+
this.geometry.setAttribute( 'instanceUVW', instanceUVW );
|
|
295
|
+
|
|
296
|
+
}
|
|
200
297
|
|
|
201
298
|
// Update texture uniforms
|
|
202
299
|
|
|
203
|
-
|
|
204
|
-
this.
|
|
300
|
+
// WITH_GENESYS
|
|
301
|
+
if ( this._probesSH !== null && this._probesResolution !== null ) {
|
|
302
|
+
|
|
303
|
+
this._probesSH.value = probes.texture || _emptyTexture;
|
|
304
|
+
this._probesResolution.value.copy( probes.resolution );
|
|
305
|
+
|
|
306
|
+
} else {
|
|
307
|
+
|
|
308
|
+
// !WITH_GENESYS
|
|
309
|
+
|
|
310
|
+
this.material.uniforms.probesSH.value = probes.texture;
|
|
311
|
+
this.material.uniforms.probesResolution.value.copy( probes.resolution );
|
|
312
|
+
|
|
313
|
+
// WITH_GENESYS
|
|
314
|
+
|
|
315
|
+
}
|
|
316
|
+
// !WITH_GENESYS
|
|
205
317
|
|
|
206
318
|
}
|
|
207
319
|
|
|
@@ -211,6 +323,18 @@ class LightProbeGridHelper extends InstancedMesh {
|
|
|
211
323
|
*/
|
|
212
324
|
dispose() {
|
|
213
325
|
|
|
326
|
+
// WITH_GENESYS
|
|
327
|
+
this.instanceMatrix.dispose();
|
|
328
|
+
|
|
329
|
+
const instanceUVW = this.geometry.getAttribute( 'instanceUVW' );
|
|
330
|
+
|
|
331
|
+
if ( instanceUVW !== undefined ) {
|
|
332
|
+
|
|
333
|
+
instanceUVW.dispose();
|
|
334
|
+
|
|
335
|
+
}
|
|
336
|
+
// !WITH_GENESYS
|
|
337
|
+
|
|
214
338
|
this.geometry.dispose();
|
|
215
339
|
this.material.dispose();
|
|
216
340
|
|
|
@@ -233,7 +233,7 @@ class Settings extends Parameters {
|
|
|
233
233
|
const extUrl = new URL( extension.url, new URL( _EXTENSIONS_PATH, import.meta.url ) ).href;
|
|
234
234
|
|
|
235
235
|
// WITH_GENESYS
|
|
236
|
-
const module = await import( /* webpackIgnore: true */ extUrl );
|
|
236
|
+
const module = await import( /* @vite-ignore */ /* webpackIgnore: true */ extUrl );
|
|
237
237
|
// !WITH_GENESYS
|
|
238
238
|
|
|
239
239
|
const keys = Object.keys( module );
|