Skip to content

Commit 6b2b479

Browse files
authored
LightProbeHelper: Add WebGPU version. (#29301)
* LightProbeHelper: Add WebGPU version. * LightProbeHelperGPU: Clean up.
1 parent f464589 commit 6b2b479

File tree

5 files changed

+93
-29
lines changed

5 files changed

+93
-29
lines changed

examples/jsm/helpers/LightProbeHelper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66

77
class LightProbeHelper extends Mesh {
88

9-
constructor( lightProbe, size ) {
9+
constructor( lightProbe, size = 1 ) {
1010

1111
const material = new ShaderMaterial( {
1212

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import {
2+
Mesh,
3+
NodeMaterial,
4+
SphereGeometry
5+
} from 'three';
6+
import { float, Fn, getShIrradianceAt, normalWorld, uniformArray, uniform, vec4 } from 'three/tsl';
7+
8+
class LightProbeHelper extends Mesh {
9+
10+
constructor( lightProbe, size = 1 ) {
11+
12+
const sh = uniformArray( lightProbe.sh.coefficients );
13+
const intensity = uniform( lightProbe.intensity );
14+
15+
const RECIPROCAL_PI = float( 1 / Math.PI );
16+
17+
const fragmentNode = Fn( () => {
18+
19+
const irradiance = getShIrradianceAt( normalWorld, sh );
20+
21+
const outgoingLight = RECIPROCAL_PI.mul( irradiance ).mul( intensity );
22+
23+
return vec4( outgoingLight, 1.0 );
24+
25+
} )();
26+
27+
const material = new NodeMaterial();
28+
material.fragmentNode = fragmentNode;
29+
30+
const geometry = new SphereGeometry( 1, 32, 16 );
31+
32+
super( geometry, material );
33+
34+
this.lightProbe = lightProbe;
35+
this.size = size;
36+
this.type = 'LightProbeHelper';
37+
38+
this._intensity = intensity;
39+
40+
this.onBeforeRender();
41+
42+
}
43+
44+
dispose() {
45+
46+
this.geometry.dispose();
47+
this.material.dispose();
48+
49+
}
50+
51+
onBeforeRender() {
52+
53+
this.position.copy( this.lightProbe.position );
54+
55+
this.scale.set( 1, 1, 1 ).multiplyScalar( this.size );
56+
57+
}
58+
59+
}
60+
61+
export { LightProbeHelper };

src/nodes/TSL.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,4 @@ export * from './lighting/LightUtils.js';
171171

172172
export { default as getGeometryRoughness } from './functions/material/getGeometryRoughness.js';
173173
export { default as getRoughness } from './functions/material/getRoughness.js';
174+
export { default as getShIrradianceAt } from './functions/material/getShIrradianceAt.js';
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Fn, mul } from '../../tsl/TSLBase.js';
2+
3+
const getShIrradianceAt = /*@__PURE__*/ Fn( ( [ normal, shCoefficients ] ) => {
4+
5+
// normal is assumed to have unit length
6+
7+
const x = normal.x, y = normal.y, z = normal.z;
8+
9+
// band 0
10+
let result = shCoefficients.element( 0 ).mul( 0.886227 );
11+
12+
// band 1
13+
result = result.add( shCoefficients.element( 1 ).mul( 2.0 * 0.511664 ).mul( y ) );
14+
result = result.add( shCoefficients.element( 2 ).mul( 2.0 * 0.511664 ).mul( z ) );
15+
result = result.add( shCoefficients.element( 3 ).mul( 2.0 * 0.511664 ).mul( x ) );
16+
17+
// band 2
18+
result = result.add( shCoefficients.element( 4 ).mul( 2.0 * 0.429043 ).mul( x ).mul( y ) );
19+
result = result.add( shCoefficients.element( 5 ).mul( 2.0 * 0.429043 ).mul( y ).mul( z ) );
20+
result = result.add( shCoefficients.element( 6 ).mul( z.mul( z ).mul( 0.743125 ).sub( 0.247708 ) ) );
21+
result = result.add( shCoefficients.element( 7 ).mul( 2.0 * 0.429043 ).mul( x ).mul( z ) );
22+
result = result.add( shCoefficients.element( 8 ).mul( 0.429043 ).mul( mul( x, x ).sub( mul( y, y ) ) ) );
23+
24+
return result;
25+
26+
} );
27+
28+
export default getShIrradianceAt;

src/nodes/lighting/LightProbeNode.js

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import AnalyticLightNode from './AnalyticLightNode.js';
22
import { normalWorld } from '../accessors/Normal.js';
33
import { uniformArray } from '../accessors/UniformArrayNode.js';
4-
import { Fn } from '../tsl/TSLBase.js';
5-
import { mul } from '../math/OperatorNode.js';
64
import { Vector3 } from '../../math/Vector3.js';
5+
import getShIrradianceAt from '../functions/material/getShIrradianceAt.js';
76

87
class LightProbeNode extends AnalyticLightNode {
98

@@ -43,7 +42,7 @@ class LightProbeNode extends AnalyticLightNode {
4342

4443
setup( builder ) {
4544

46-
const irradiance = shGetIrradianceAt( normalWorld, this.lightProbe );
45+
const irradiance = getShIrradianceAt( normalWorld, this.lightProbe );
4746

4847
builder.context.irradiance.addAssign( irradiance );
4948

@@ -52,28 +51,3 @@ class LightProbeNode extends AnalyticLightNode {
5251
}
5352

5453
export default LightProbeNode;
55-
56-
const shGetIrradianceAt = /*@__PURE__*/ Fn( ( [ normal, shCoefficients ] ) => {
57-
58-
// normal is assumed to have unit length
59-
60-
const x = normal.x, y = normal.y, z = normal.z;
61-
62-
// band 0
63-
const result = shCoefficients.element( 0 ).mul( 0.886227 );
64-
65-
// band 1
66-
result.addAssign( shCoefficients.element( 1 ).mul( 2.0 * 0.511664 ).mul( y ) );
67-
result.addAssign( shCoefficients.element( 2 ).mul( 2.0 * 0.511664 ).mul( z ) );
68-
result.addAssign( shCoefficients.element( 3 ).mul( 2.0 * 0.511664 ).mul( x ) );
69-
70-
// band 2
71-
result.addAssign( shCoefficients.element( 4 ).mul( 2.0 * 0.429043 ).mul( x ).mul( y ) );
72-
result.addAssign( shCoefficients.element( 5 ).mul( 2.0 * 0.429043 ).mul( y ).mul( z ) );
73-
result.addAssign( shCoefficients.element( 6 ).mul( z.mul( z ).mul( 0.743125 ).sub( 0.247708 ) ) );
74-
result.addAssign( shCoefficients.element( 7 ).mul( 2.0 * 0.429043 ).mul( x ).mul( z ) );
75-
result.addAssign( shCoefficients.element( 8 ).mul( 0.429043 ).mul( mul( x, x ).sub( mul( y, y ) ) ) );
76-
77-
return result;
78-
79-
} );

0 commit comments

Comments
 (0)