Skip to content

Commit 2c13adc

Browse files
authored
WebGPURenderer: Build - three.webgpu.js (#28650)
* webgpu build * revision * cleanup * Restore USDZLoader * update * puppeteer: added `three.webgpu` build support * update IESSpotLight * move to src and revision * cleanup * fix test-circular-deps test * fix lint * revision * cleanup lint * update build * update package * update builds * update - fixing conflicts * cleanup * WebGPUBackend: add srcRegion to copyTextureToTexture() * fix examples * fix warnOnce * update path * update build * Update package.json * importmap: added alias * move materials to THREE * update import to three/tsl
1 parent 6e66343 commit 2c13adc

File tree

373 files changed

+75320
-1710
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

373 files changed

+75320
-1710
lines changed

build/three.webgpu.js

Lines changed: 73550 additions & 0 deletions
Large diffs are not rendered by default.

build/three.webgpu.min.js

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/jsm/lights/RectAreaLightTexturesLib.js

Lines changed: 91 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/jsm/lights/RectAreaLightUniformsLib.js

Lines changed: 8 additions & 63 deletions
Large diffs are not rendered by default.

examples/jsm/lines/webgpu/Line2.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { LineSegments2 } from './LineSegments2.js';
2+
import { LineGeometry } from '../LineGeometry.js';
3+
4+
import { Line2NodeMaterial } from 'three';
5+
6+
class Line2 extends LineSegments2 {
7+
8+
constructor( geometry = new LineGeometry(), material = new Line2NodeMaterial( { color: Math.random() * 0xffffff } ) ) {
9+
10+
super( geometry, material );
11+
12+
this.isLine2 = true;
13+
14+
this.type = 'Line2';
15+
16+
}
17+
18+
}
19+
20+
export { Line2 };
Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
import {
2+
Box3,
3+
InstancedInterleavedBuffer,
4+
InterleavedBufferAttribute,
5+
Line3,
6+
MathUtils,
7+
Matrix4,
8+
Mesh,
9+
Sphere,
10+
Vector3,
11+
Vector4,
12+
Line2NodeMaterial
13+
} from 'three';
14+
import { LineSegmentsGeometry } from '../../lines/LineSegmentsGeometry.js';
15+
16+
const _viewport = new Vector4();
17+
18+
const _start = new Vector3();
19+
const _end = new Vector3();
20+
21+
const _start4 = new Vector4();
22+
const _end4 = new Vector4();
23+
24+
const _ssOrigin = new Vector4();
25+
const _ssOrigin3 = new Vector3();
26+
const _mvMatrix = new Matrix4();
27+
const _line = new Line3();
28+
const _closestPoint = new Vector3();
29+
30+
const _box = new Box3();
31+
const _sphere = new Sphere();
32+
const _clipToWorldVector = new Vector4();
33+
34+
let _ray, _lineWidth;
35+
36+
// Returns the margin required to expand by in world space given the distance from the camera,
37+
// line width, resolution, and camera projection
38+
function getWorldSpaceHalfWidth( camera, distance, resolution ) {
39+
40+
// transform into clip space, adjust the x and y values by the pixel width offset, then
41+
// transform back into world space to get world offset. Note clip space is [-1, 1] so full
42+
// width does not need to be halved.
43+
_clipToWorldVector.set( 0, 0, - distance, 1.0 ).applyMatrix4( camera.projectionMatrix );
44+
_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
45+
_clipToWorldVector.x = _lineWidth / resolution.width;
46+
_clipToWorldVector.y = _lineWidth / resolution.height;
47+
_clipToWorldVector.applyMatrix4( camera.projectionMatrixInverse );
48+
_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
49+
50+
return Math.abs( Math.max( _clipToWorldVector.x, _clipToWorldVector.y ) );
51+
52+
}
53+
54+
function raycastWorldUnits( lineSegments, intersects ) {
55+
56+
const matrixWorld = lineSegments.matrixWorld;
57+
const geometry = lineSegments.geometry;
58+
const instanceStart = geometry.attributes.instanceStart;
59+
const instanceEnd = geometry.attributes.instanceEnd;
60+
const segmentCount = Math.min( geometry.instanceCount, instanceStart.count );
61+
62+
for ( let i = 0, l = segmentCount; i < l; i ++ ) {
63+
64+
_line.start.fromBufferAttribute( instanceStart, i );
65+
_line.end.fromBufferAttribute( instanceEnd, i );
66+
67+
_line.applyMatrix4( matrixWorld );
68+
69+
const pointOnLine = new Vector3();
70+
const point = new Vector3();
71+
72+
_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
73+
const isInside = point.distanceTo( pointOnLine ) < _lineWidth * 0.5;
74+
75+
if ( isInside ) {
76+
77+
intersects.push( {
78+
point,
79+
pointOnLine,
80+
distance: _ray.origin.distanceTo( point ),
81+
object: lineSegments,
82+
face: null,
83+
faceIndex: i,
84+
uv: null,
85+
uv1: null,
86+
} );
87+
88+
}
89+
90+
}
91+
92+
}
93+
94+
function raycastScreenSpace( lineSegments, camera, intersects ) {
95+
96+
const projectionMatrix = camera.projectionMatrix;
97+
const material = lineSegments.material;
98+
const resolution = material.resolution;
99+
const matrixWorld = lineSegments.matrixWorld;
100+
101+
const geometry = lineSegments.geometry;
102+
const instanceStart = geometry.attributes.instanceStart;
103+
const instanceEnd = geometry.attributes.instanceEnd;
104+
const segmentCount = Math.min( geometry.instanceCount, instanceStart.count );
105+
106+
const near = - camera.near;
107+
108+
//
109+
110+
// pick a point 1 unit out along the ray to avoid the ray origin
111+
// sitting at the camera origin which will cause "w" to be 0 when
112+
// applying the projection matrix.
113+
_ray.at( 1, _ssOrigin );
114+
115+
// ndc space [ - 1.0, 1.0 ]
116+
_ssOrigin.w = 1;
117+
_ssOrigin.applyMatrix4( camera.matrixWorldInverse );
118+
_ssOrigin.applyMatrix4( projectionMatrix );
119+
_ssOrigin.multiplyScalar( 1 / _ssOrigin.w );
120+
121+
// screen space
122+
_ssOrigin.x *= resolution.x / 2;
123+
_ssOrigin.y *= resolution.y / 2;
124+
_ssOrigin.z = 0;
125+
126+
_ssOrigin3.copy( _ssOrigin );
127+
128+
_mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld );
129+
130+
for ( let i = 0, l = segmentCount; i < l; i ++ ) {
131+
132+
_start4.fromBufferAttribute( instanceStart, i );
133+
_end4.fromBufferAttribute( instanceEnd, i );
134+
135+
_start4.w = 1;
136+
_end4.w = 1;
137+
138+
// camera space
139+
_start4.applyMatrix4( _mvMatrix );
140+
_end4.applyMatrix4( _mvMatrix );
141+
142+
// skip the segment if it's entirely behind the camera
143+
const isBehindCameraNear = _start4.z > near && _end4.z > near;
144+
if ( isBehindCameraNear ) {
145+
146+
continue;
147+
148+
}
149+
150+
// trim the segment if it extends behind camera near
151+
if ( _start4.z > near ) {
152+
153+
const deltaDist = _start4.z - _end4.z;
154+
const t = ( _start4.z - near ) / deltaDist;
155+
_start4.lerp( _end4, t );
156+
157+
} else if ( _end4.z > near ) {
158+
159+
const deltaDist = _end4.z - _start4.z;
160+
const t = ( _end4.z - near ) / deltaDist;
161+
_end4.lerp( _start4, t );
162+
163+
}
164+
165+
// clip space
166+
_start4.applyMatrix4( projectionMatrix );
167+
_end4.applyMatrix4( projectionMatrix );
168+
169+
// ndc space [ - 1.0, 1.0 ]
170+
_start4.multiplyScalar( 1 / _start4.w );
171+
_end4.multiplyScalar( 1 / _end4.w );
172+
173+
// screen space
174+
_start4.x *= resolution.x / 2;
175+
_start4.y *= resolution.y / 2;
176+
177+
_end4.x *= resolution.x / 2;
178+
_end4.y *= resolution.y / 2;
179+
180+
// create 2d segment
181+
_line.start.copy( _start4 );
182+
_line.start.z = 0;
183+
184+
_line.end.copy( _end4 );
185+
_line.end.z = 0;
186+
187+
// get closest point on ray to segment
188+
const param = _line.closestPointToPointParameter( _ssOrigin3, true );
189+
_line.at( param, _closestPoint );
190+
191+
// check if the intersection point is within clip space
192+
const zPos = MathUtils.lerp( _start4.z, _end4.z, param );
193+
const isInClipSpace = zPos >= - 1 && zPos <= 1;
194+
195+
const isInside = _ssOrigin3.distanceTo( _closestPoint ) < _lineWidth * 0.5;
196+
197+
if ( isInClipSpace && isInside ) {
198+
199+
_line.start.fromBufferAttribute( instanceStart, i );
200+
_line.end.fromBufferAttribute( instanceEnd, i );
201+
202+
_line.start.applyMatrix4( matrixWorld );
203+
_line.end.applyMatrix4( matrixWorld );
204+
205+
const pointOnLine = new Vector3();
206+
const point = new Vector3();
207+
208+
_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
209+
210+
intersects.push( {
211+
point: point,
212+
pointOnLine: pointOnLine,
213+
distance: _ray.origin.distanceTo( point ),
214+
object: lineSegments,
215+
face: null,
216+
faceIndex: i,
217+
uv: null,
218+
uv1: null,
219+
} );
220+
221+
}
222+
223+
}
224+
225+
}
226+
227+
class LineSegments2 extends Mesh {
228+
229+
constructor( geometry = new LineSegmentsGeometry(), material = new Line2NodeMaterial( { color: Math.random() * 0xffffff } ) ) {
230+
231+
super( geometry, material );
232+
233+
this.isLineSegments2 = true;
234+
235+
this.type = 'LineSegments2';
236+
237+
}
238+
239+
// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
240+
241+
computeLineDistances() {
242+
243+
const geometry = this.geometry;
244+
245+
const instanceStart = geometry.attributes.instanceStart;
246+
const instanceEnd = geometry.attributes.instanceEnd;
247+
const lineDistances = new Float32Array( 2 * instanceStart.count );
248+
249+
for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) {
250+
251+
_start.fromBufferAttribute( instanceStart, i );
252+
_end.fromBufferAttribute( instanceEnd, i );
253+
254+
lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ];
255+
lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end );
256+
257+
}
258+
259+
const instanceDistanceBuffer = new InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1
260+
261+
geometry.setAttribute( 'instanceDistanceStart', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0
262+
geometry.setAttribute( 'instanceDistanceEnd', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1
263+
264+
return this;
265+
266+
}
267+
268+
raycast( raycaster, intersects ) {
269+
270+
const worldUnits = this.material.worldUnits;
271+
const camera = raycaster.camera;
272+
273+
if ( camera === null && ! worldUnits ) {
274+
275+
console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.' );
276+
277+
}
278+
279+
const threshold = ( raycaster.params.Line2 !== undefined ) ? raycaster.params.Line2.threshold || 0 : 0;
280+
281+
_ray = raycaster.ray;
282+
283+
const matrixWorld = this.matrixWorld;
284+
const geometry = this.geometry;
285+
const material = this.material;
286+
287+
_lineWidth = material.linewidth + threshold;
288+
289+
// check if we intersect the sphere bounds
290+
if ( geometry.boundingSphere === null ) {
291+
292+
geometry.computeBoundingSphere();
293+
294+
}
295+
296+
_sphere.copy( geometry.boundingSphere ).applyMatrix4( matrixWorld );
297+
298+
// increase the sphere bounds by the worst case line screen space width
299+
let sphereMargin;
300+
if ( worldUnits ) {
301+
302+
sphereMargin = _lineWidth * 0.5;
303+
304+
} else {
305+
306+
const distanceToSphere = Math.max( camera.near, _sphere.distanceToPoint( _ray.origin ) );
307+
sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere, material.resolution );
308+
309+
}
310+
311+
_sphere.radius += sphereMargin;
312+
313+
if ( _ray.intersectsSphere( _sphere ) === false ) {
314+
315+
return;
316+
317+
}
318+
319+
// check if we intersect the box bounds
320+
if ( geometry.boundingBox === null ) {
321+
322+
geometry.computeBoundingBox();
323+
324+
}
325+
326+
_box.copy( geometry.boundingBox ).applyMatrix4( matrixWorld );
327+
328+
// increase the box bounds by the worst case line width
329+
let boxMargin;
330+
if ( worldUnits ) {
331+
332+
boxMargin = _lineWidth * 0.5;
333+
334+
} else {
335+
336+
const distanceToBox = Math.max( camera.near, _box.distanceToPoint( _ray.origin ) );
337+
boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox, material.resolution );
338+
339+
}
340+
341+
_box.expandByScalar( boxMargin );
342+
343+
if ( _ray.intersectsBox( _box ) === false ) {
344+
345+
return;
346+
347+
}
348+
349+
if ( worldUnits ) {
350+
351+
raycastWorldUnits( this, intersects );
352+
353+
} else {
354+
355+
raycastScreenSpace( this, camera, intersects );
356+
357+
}
358+
359+
}
360+
361+
onBeforeRender( renderer ) {
362+
363+
const uniforms = this.material.uniforms;
364+
365+
if ( uniforms && uniforms.resolution ) {
366+
367+
renderer.getViewport( _viewport );
368+
this.material.uniforms.resolution.value.set( _viewport.z, _viewport.w );
369+
370+
}
371+
372+
}
373+
374+
}
375+
376+
export { LineSegments2 };

0 commit comments

Comments
 (0)