matrix-engine-wgpu 1.3.13 → 1.3.17

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.
@@ -1,476 +0,0 @@
1
- // Note: The code in this file does not use the 'dst' output parameter of functions in the
2
- // 'wgpu-matrix' library, so produces many temporary vectors and matrices.
3
- // This is intentional, as this sample prefers readability over performance.
4
- import { mat4, vec3 } from 'wgpu-matrix';
5
- import {LOG_INFO} from './utils';
6
- // import Input from './input';
7
-
8
- // // Common interface for camera implementations
9
- // export default interface Camera {
10
- // // update updates the camera using the user-input and returns the view matrix.
11
- // update(delta_time: number, input: Input): Mat4;
12
-
13
- // // The camera matrix.
14
- // // This is the inverse of the view matrix.
15
- // matrix: Mat4;
16
- // // Alias to column vector 0 of the camera matrix.
17
- // right: Vec4;
18
- // // Alias to column vector 1 of the camera matrix.
19
- // up: Vec4;
20
- // // Alias to column vector 2 of the camera matrix.
21
- // back: Vec4;
22
- // // Alias to column vector 3 of the camera matrix.
23
- // position: Vec4;
24
- // }
25
-
26
- // The common functionality between camera implementations
27
- class CameraBase {
28
- // The camera matrix
29
- matrix_ = new Float32Array([
30
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
31
- ]);
32
-
33
- // The calculated view matrix readonly
34
- view_ = mat4.create();
35
-
36
- // Aliases to column vectors of the matrix
37
- right_ = new Float32Array(this.matrix_.buffer, 4 * 0, 4);
38
- up_ = new Float32Array(this.matrix_.buffer, 4 * 4, 4);
39
- back_ = new Float32Array(this.matrix_.buffer, 4 * 8, 4);
40
- position_ = new Float32Array(this.matrix_.buffer, 4 * 12, 4);
41
-
42
- // Returns the camera matrix
43
- get matrix() {
44
- return this.matrix_;
45
- }
46
- // Assigns `mat` to the camera matrix
47
- set matrix(mat) {
48
- mat4.copy(mat, this.matrix_);
49
- }
50
-
51
- setProjection(fov = (2 * Math.PI) / 5, aspect = 1, near = 1, far = 1000) {
52
- this.projectionMatrix = mat4.perspective(fov, aspect, near, far);
53
- }
54
-
55
- // Returns the camera view matrix
56
- get view() {
57
- return this.view_;
58
- }
59
- // Assigns `mat` to the camera view
60
- set view(mat) {
61
- mat4.copy(mat, this.view_);
62
- }
63
-
64
- // Returns column vector 0 of the camera matrix
65
- get right() {
66
- return this.right_;
67
- }
68
-
69
- // Assigns `vec` to the first 3 elements of column vector 0 of the camera matrix
70
- set right(vec) {
71
- vec3.copy(vec, this.right_);
72
- }
73
-
74
- // Returns column vector 1 of the camera matrix
75
- get up() {
76
- return this.up_;
77
- }
78
-
79
- // Assigns `vec` to the first 3 elements of column vector 1 of the camera matrix \ Vec3
80
- set up(vec) {
81
- vec3.copy(vec, this.up_);
82
- }
83
-
84
- // Returns column vector 2 of the camera matrix
85
- get back() {
86
- return this.back_;
87
- }
88
-
89
- // Assigns `vec` to the first 3 elements of column vector 2 of the camera matrix
90
- set back(vec) {
91
- vec3.copy(vec, this.back_);
92
- }
93
-
94
- // Returns column vector 3 of the camera matrix
95
- get position() {
96
- return this.position_;
97
- }
98
-
99
- // Assigns `vec` to the first 3 elements of column vector 3 of the camera matrix
100
- set position(vec) {
101
- vec3.copy(vec, this.position_);
102
- }
103
- }
104
-
105
- // WASDCamera is a camera implementation that behaves similar to first-person-shooter PC games.
106
- export class WASDCamera extends CameraBase {
107
- // The camera absolute pitch angle
108
- pitch = 0;
109
- // The camera absolute yaw angle
110
- yaw = 0;
111
-
112
- // The movement veloicty readonly
113
- velocity_ = vec3.create();
114
-
115
- // Speed multiplier for camera movement
116
- movementSpeed = 10;
117
-
118
- // Speed multiplier for camera rotation
119
- rotationSpeed = 1;
120
-
121
- // Movement velocity drag coeffient [0 .. 1]
122
- // 0: Continues forever
123
- // 1: Instantly stops moving
124
- frictionCoefficient = 0.99;
125
-
126
- // Returns velocity vector
127
- get velocity() {
128
- return this.velocity_;
129
- }
130
- // Assigns `vec` to the velocity vector
131
- set velocity(vec) {
132
- vec3.copy(vec, this.velocity_);
133
- }
134
-
135
- constructor(options) {
136
- super();
137
- if (options && (options.position || options.target)) {
138
- const position = options.position ?? vec3.create(0, 0, 0);
139
- const target = options.target ?? vec3.create(0, 0, 0);
140
- const forward = vec3.normalize(vec3.sub(target, position));
141
- this.recalculateAngles(forward);
142
- this.position = position;
143
-
144
- this.setProjection()
145
- console.log(`%cCamera constructor : ${position}`, LOG_INFO);
146
- }
147
- }
148
-
149
- // Returns the camera matrix
150
- get matrix() {
151
- return super.matrix;
152
- }
153
-
154
- // Assigns `mat` to the camera matrix, and recalcuates the camera angles
155
- set matrix(mat) {
156
- super.matrix = mat;
157
- this.recalculateAngles(this.back);
158
- }
159
-
160
- update(deltaTime, input) {
161
- const sign = (positive, negative) =>
162
- (positive ? 1 : 0) - (negative ? 1 : 0);
163
-
164
- // Apply the delta rotation to the pitch and yaw angles
165
- this.yaw -= input.analog.x * deltaTime * this.rotationSpeed;
166
- this.pitch -= input.analog.y * deltaTime * this.rotationSpeed;
167
-
168
- // Wrap yaw between [0° .. 360°], just to prevent large accumulation.
169
- this.yaw = mod(this.yaw, Math.PI * 2);
170
- // Clamp pitch between [-90° .. +90°] to prevent somersaults.
171
- this.pitch = clamp(this.pitch, -Math.PI / 2, Math.PI / 2);
172
-
173
- // Save the current position, as we're about to rebuild the camera matrix.
174
- const position = vec3.copy(this.position);
175
-
176
- // Reconstruct the camera's rotation, and store into the camera matrix.
177
- super.matrix = mat4.rotateX(mat4.rotationY(this.yaw), this.pitch);
178
- // super.matrix = mat4.rotateX(mat4.rotationY(this.yaw), -this.pitch);
179
- // super.matrix = mat4.rotateY(mat4.rotateX(this.pitch), this.yaw);
180
-
181
- // Calculate the new target velocity
182
- const digital = input.digital;
183
- const deltaRight = sign(digital.right, digital.left);
184
- const deltaUp = sign(digital.up, digital.down);
185
- const targetVelocity = vec3.create();
186
- const deltaBack = sign(digital.backward, digital.forward);
187
- vec3.addScaled(targetVelocity, this.right, deltaRight, targetVelocity);
188
- vec3.addScaled(targetVelocity, this.up, deltaUp, targetVelocity);
189
- vec3.addScaled(targetVelocity, this.back, deltaBack, targetVelocity);
190
- vec3.normalize(targetVelocity, targetVelocity);
191
- vec3.mulScalar(targetVelocity, this.movementSpeed, targetVelocity);
192
-
193
- // Mix new target velocity
194
- this.velocity = lerp(
195
- targetVelocity,
196
- this.velocity,
197
- Math.pow(1 - this.frictionCoefficient, deltaTime)
198
- );
199
-
200
- // Integrate velocity to calculate new position
201
- this.position = vec3.addScaled(position, this.velocity, deltaTime);
202
-
203
- // Invert the camera matrix to build the view matrix
204
- this.view = mat4.invert(this.matrix);
205
- return this.view;
206
- }
207
-
208
- // Recalculates the yaw and pitch values from a directional vector
209
- recalculateAngles(dir) {
210
- this.yaw = Math.atan2(dir[0], dir[2]);
211
- this.pitch = -Math.asin(dir[1]);
212
- }
213
- }
214
-
215
- // ArcballCamera implements a basic orbiting camera around the world origin
216
- export class ArcballCamera extends CameraBase {
217
- // The camera distance from the target
218
- distance = 0;
219
-
220
- // The current angular velocity
221
- angularVelocity = 0;
222
-
223
- // The current rotation axis
224
- axis_ = vec3.create();
225
-
226
- // Returns the rotation axis
227
- get axis() {
228
- return this.axis_;
229
- }
230
- // Assigns `vec` to the rotation axis
231
- set axis(vec) {
232
- vec3.copy(vec, this.axis_);
233
- }
234
-
235
- // Speed multiplier for camera rotation
236
- rotationSpeed = 1;
237
-
238
- // Speed multiplier for camera zoom
239
- zoomSpeed = 0.1;
240
-
241
- // Rotation velocity drag coeffient [0 .. 1]
242
- // 0: Spins forever
243
- // 1: Instantly stops spinning
244
- frictionCoefficient = 0.999;
245
-
246
- // Construtor
247
- constructor(options) {
248
- super();
249
- if (options && options.position) {
250
- this.position = options.position;
251
- this.distance = vec3.len(this.position);
252
- this.back = vec3.normalize(this.position);
253
- this.recalcuateRight();
254
- this.recalcuateUp();
255
- }
256
- }
257
-
258
- // Returns the camera matrix
259
- get matrix() {
260
- return super.matrix;
261
- }
262
-
263
- // Assigns `mat` to the camera matrix, and recalcuates the distance
264
- set matrix(mat) {
265
- super.matrix = mat;
266
- this.distance = vec3.len(this.position);
267
- }
268
-
269
- update(deltaTime, input) {
270
- const epsilon = 0.0000001;
271
-
272
- if (input.analog.touching) {
273
- // Currently being dragged.
274
- this.angularVelocity = 0;
275
- } else {
276
- // Dampen any existing angular velocity
277
- this.angularVelocity *= Math.pow(1 - this.frictionCoefficient, deltaTime);
278
- }
279
-
280
- // Calculate the movement vector
281
- const movement = vec3.create();
282
- vec3.addScaled(movement, this.right, input.analog.x, movement);
283
- vec3.addScaled(movement, this.up, -input.analog.y, movement);
284
-
285
- // Cross the movement vector with the view direction to calculate the rotation axis x magnitude
286
- const crossProduct = vec3.cross(movement, this.back);
287
-
288
- // Calculate the magnitude of the drag
289
- const magnitude = vec3.len(crossProduct);
290
-
291
- if (magnitude > epsilon) {
292
- // Normalize the crossProduct to get the rotation axis
293
- this.axis = vec3.scale(crossProduct, 1 / magnitude);
294
-
295
- // Remember the current angular velocity. This is used when the touch is released for a fling.
296
- this.angularVelocity = magnitude * this.rotationSpeed;
297
- }
298
-
299
- // The rotation around this.axis to apply to the camera matrix this update
300
- const rotationAngle = this.angularVelocity * deltaTime;
301
- if (rotationAngle > epsilon) {
302
- // Rotate the matrix around axis
303
- // Note: The rotation is not done as a matrix-matrix multiply as the repeated multiplications
304
- // will quickly introduce substantial error into the matrix.
305
- this.back = vec3.normalize(rotate(this.back, this.axis, rotationAngle));
306
- this.recalcuateRight();
307
- this.recalcuateUp();
308
- }
309
-
310
- // recalculate `this.position` from `this.back` considering zoom
311
- if (input.analog.zoom !== 0) {
312
- this.distance *= 1 + input.analog.zoom * this.zoomSpeed;
313
- }
314
- this.position = vec3.scale(this.back, this.distance);
315
-
316
- // Invert the camera matrix to build the view matrix
317
- this.view = mat4.invert(this.matrix);
318
- return this.view;
319
- }
320
-
321
- // Assigns `this.right` with the cross product of `this.up` and `this.back`
322
- recalcuateRight() {
323
- this.right = vec3.normalize(vec3.cross(this.up, this.back));
324
- }
325
-
326
- // Assigns `this.up` with the cross product of `this.back` and `this.right`
327
- recalcuateUp() {
328
- this.up = vec3.normalize(vec3.cross(this.back, this.right));
329
- }
330
- }
331
-
332
- // Returns `x` clamped between [`min` .. `max`]
333
- function clamp(x, min, max) {
334
- return Math.min(Math.max(x, min), max);
335
- }
336
-
337
- // Returns `x` float-modulo `div`
338
- function mod(x, div) {
339
- return x - Math.floor(Math.abs(x) / div) * div * Math.sign(x);
340
- }
341
-
342
- // Returns `vec` rotated `angle` radians around `axis`
343
- function rotate(vec, axis, angle) {
344
- return vec3.transformMat4Upper3x3(vec, mat4.rotation(axis, angle));
345
- }
346
-
347
- // Returns the linear interpolation between 'a' and 'b' using 's'
348
- function lerp(a, b, s) {
349
- return vec3.addScaled(a, vec3.sub(b, a), s);
350
- }
351
-
352
- // Input holds as snapshot of input state
353
- // export default interface Input {
354
- // // Digital input (e.g keyboard state)
355
- // readonly digital: {
356
- // readonly forward: boolean;
357
- // readonly backward: boolean;
358
- // readonly left: boolean;
359
- // readonly right: boolean;
360
- // readonly up: boolean;
361
- // readonly down: boolean;
362
- // };
363
- // // Analog input (e.g mouse, touchscreen)
364
- // readonly analog: {
365
- // readonly x: number;
366
- // readonly y: number;
367
- // readonly zoom: number;
368
- // readonly touching: boolean;
369
- // };
370
- // }
371
- // InputHandler is a function that when called, returns the current Input state.
372
- // export type InputHandler = () => Input;
373
- // createInputHandler returns an InputHandler by attaching event handlers to the window and canvas.
374
- export function createInputHandler(window, canvas) {
375
- let digital = {
376
- forward: false,
377
- backward: false,
378
- left: false,
379
- right: false,
380
- up: false,
381
- down: false,
382
- };
383
- let analog = {
384
- x: 0,
385
- y: 0,
386
- zoom: 0,
387
- };
388
- let mouseDown = false;
389
-
390
- const setDigital = (e, value) => {
391
- switch (e.code) {
392
- case 'KeyW':
393
- digital.forward = value;
394
- e.preventDefault();
395
- e.stopPropagation();
396
- break;
397
- case 'KeyS':
398
- digital.backward = value;
399
- e.preventDefault();
400
- e.stopPropagation();
401
- break;
402
- case 'KeyA':
403
- digital.left = value;
404
- e.preventDefault();
405
- e.stopPropagation();
406
- break;
407
- case 'KeyD':
408
- digital.right = value;
409
- e.preventDefault();
410
- e.stopPropagation();
411
- break;
412
- case 'Space':
413
- digital.up = value;
414
- e.preventDefault();
415
- e.stopPropagation();
416
- break;
417
- case 'ShiftLeft':
418
- case 'ControlLeft':
419
- case 'KeyC':
420
- digital.down = value;
421
- e.preventDefault();
422
- e.stopPropagation();
423
- break;
424
- }
425
- };
426
-
427
- window.addEventListener('keydown', (e) => setDigital(e, true));
428
- window.addEventListener('keyup', (e) => setDigital(e, false));
429
-
430
- canvas.style.touchAction = 'pinch-zoom';
431
- canvas.addEventListener('pointerdown', () => {
432
- mouseDown = true;
433
- });
434
- canvas.addEventListener('pointerup', () => {
435
- mouseDown = false;
436
- });
437
- canvas.addEventListener('pointermove', (e) => {
438
- mouseDown = e.pointerType == 'mouse' ? (e.buttons & 1) !== 0 : true;
439
- if (mouseDown) {
440
- // console.log('TEST ', analog)
441
- analog.x += e.movementX / 10;
442
- analog.y += e.movementY / 10;
443
- }
444
- });
445
- canvas.addEventListener(
446
- 'wheel',
447
- (e) => {
448
- mouseDown = (e.buttons & 1) !== 0;
449
- if (mouseDown) {
450
- // The scroll value varies substantially between user agents / browsers.
451
- // Just use the sign.
452
- analog.zoom += Math.sign(e.deltaY);
453
- e.preventDefault();
454
- e.stopPropagation();
455
- }
456
- },
457
- { passive: false }
458
- );
459
-
460
- return () => {
461
- const out = {
462
- digital,
463
- analog: {
464
- x: analog.x,
465
- y: analog.y,
466
- zoom: analog.zoom,
467
- touching: mouseDown,
468
- },
469
- };
470
- // Clear the analog values, as these accumulate.
471
- analog.x = 0;
472
- analog.y = 0;
473
- analog.zoom = 0;
474
- return out;
475
- };
476
- }
@@ -1,53 +0,0 @@
1
- import {computeSurfaceNormals, computeProjectedPlaneUVs} from './utils2.js';
2
-
3
- export function adaptJSON1(dragonRawData) {
4
-
5
- let mesh = {
6
- positions: dragonRawData.positions,
7
- triangles: dragonRawData.cells,
8
- normals: [],
9
- uvs: []
10
- };
11
-
12
- // Compute surface normals
13
- mesh.normals = computeSurfaceNormals(mesh.positions, mesh.triangles);
14
-
15
- // Compute some easy uvs for testing
16
- mesh.uvs = computeProjectedPlaneUVs(mesh.positions, 'xy');
17
-
18
- return mesh;
19
- }
20
-
21
- export function addVerticesNormalUvs(mesh) {
22
-
23
- var meshAdapted = {
24
- positions: [],
25
- cells: [],
26
- uvs: mesh.textures,
27
- vertices: mesh.vertices
28
- // normals: mesh.vertexNormals
29
- };
30
- // force syntese
31
- for (var x = 0; x < mesh.vertices.length; x=x+3) {
32
- var sub = [];
33
- sub.push(mesh.vertices[x])
34
- sub.push(mesh.vertices[x+1])
35
- sub.push(mesh.vertices[x+2])
36
- meshAdapted.positions.push(sub)
37
- sub = [];
38
- sub.push(mesh.indices[x])
39
- sub.push(mesh.indices[x+1])
40
- sub.push(mesh.indices[x+2])
41
- meshAdapted.cells.push(sub)
42
- }
43
-
44
- // Compute surface normals
45
- meshAdapted.normals = computeSurfaceNormals(meshAdapted.positions, meshAdapted.cells);
46
- // Compute some easy uvs for testing
47
- meshAdapted.uvs = computeProjectedPlaneUVs(meshAdapted.positions, 'xy');
48
-
49
- meshAdapted.triangles = meshAdapted.cells
50
- return meshAdapted;
51
- }
52
-
53
-
@@ -1,63 +0,0 @@
1
- import { vec3 } from 'wgpu-matrix';
2
-
3
- export function computeSurfaceNormals(positions,triangles){
4
- const normals = positions.map(() => {
5
- // Initialize to zero.
6
- return [0, 0, 0];
7
- });
8
- triangles.forEach(([i0, i1, i2]) => {
9
- const p0 = positions[i0];
10
- const p1 = positions[i1];
11
- const p2 = positions[i2];
12
-
13
- const v0 = vec3.subtract(p1, p0);
14
- const v1 = vec3.subtract(p2, p0);
15
-
16
- vec3.normalize(v0, v0);
17
- vec3.normalize(v1, v1);
18
- const norm = vec3.cross(v0, v1);
19
-
20
- // Accumulate the normals.
21
- vec3.add(normals[i0], norm, normals[i0]);
22
- vec3.add(normals[i1], norm, normals[i1]);
23
- vec3.add(normals[i2], norm, normals[i2]);
24
- });
25
- normals.forEach((n) => {
26
- // Normalize accumulated normals.
27
- vec3.normalize(n, n);
28
- });
29
-
30
- return normals;
31
- }
32
-
33
- // type ProjectedPlane = 'xy' | 'xz' | 'yz';
34
- const projectedPlane2Ids = {
35
- xy: [0, 1],
36
- xz: [0, 2],
37
- yz: [1, 2],
38
- };
39
-
40
- export function computeProjectedPlaneUVs(positions, projectedPlane) {
41
- const idxs = projectedPlane2Ids[projectedPlane];
42
- const uvs = positions.map(() => {
43
- // Initialize to zero.
44
- return [0, 0];
45
- });
46
- const extentMin = [Infinity, Infinity];
47
- const extentMax = [-Infinity, -Infinity];
48
- positions.forEach((pos, i) => {
49
- // Simply project to the selected plane
50
- uvs[i][0] = pos[idxs[0]];
51
- uvs[i][1] = pos[idxs[1]];
52
-
53
- extentMin[0] = Math.min(pos[idxs[0]], extentMin[0]);
54
- extentMin[1] = Math.min(pos[idxs[1]], extentMin[1]);
55
- extentMax[0] = Math.max(pos[idxs[0]], extentMax[0]);
56
- extentMax[1] = Math.max(pos[idxs[1]], extentMax[1]);
57
- });
58
- uvs.forEach((uv) => {
59
- uv[0] = (uv[0] - extentMin[0]) / (extentMax[0] - extentMin[0]);
60
- uv[1] = (uv[1] - extentMin[1]) / (extentMax[1] - extentMin[1]);
61
- });
62
- return uvs;
63
- }
@@ -1,126 +0,0 @@
1
- import {mat4, vec3} from 'wgpu-matrix';
2
-
3
- export class SpotLight {
4
- position;
5
- target;
6
- up;
7
- direction;
8
-
9
- viewMatrix;
10
- projectionMatrix;
11
- viewProjMatrix;
12
-
13
- fov;
14
- aspect;
15
- near;
16
- far;
17
-
18
- innerCutoff;
19
- outerCutoff;
20
-
21
- spotlightUniformBuffer;
22
-
23
- constructor(
24
- position = vec3.create(0, 5, 10),
25
- target = vec3.create(0, 0, 0),
26
- fov = 45,
27
- aspect = 1.0,
28
- near = 0.1,
29
- far = 100
30
- ) {
31
- this.position = position;
32
- this.target = target;
33
- this.up = vec3.create(0, 1, 0);
34
- this.direction = vec3.normalize(vec3.subtract(target, position));
35
-
36
- this.viewMatrix = mat4.lookAt(position, target, this.up);
37
- this.projectionMatrix = mat4.perspective(
38
- (fov * Math.PI) / 180,
39
- aspect,
40
- near,
41
- far
42
- );
43
- this.viewProjMatrix = mat4.multiply(this.projectionMatrix, this.viewMatrix);
44
-
45
- this.fov = fov;
46
- this.aspect = aspect;
47
- this.near = near;
48
- this.far = far;
49
-
50
- this.innerCutoff = Math.cos((Math.PI / 180) * 12.5);
51
- this.outerCutoff = Math.cos((Math.PI / 180) * 17.5);
52
- }
53
-
54
- update() {
55
- this.direction = vec3.normalize(vec3.subtract(this.target, this.position));
56
- this.viewMatrix = mat4.lookAt(this.position, this.target, this.up);
57
- this.viewProjMatrix = mat4.multiply(this.projectionMatrix, this.viewMatrix);
58
- console.log('test light update this.position : ', this.position)
59
- }
60
-
61
- updateSceneUniforms = (sceneUniformBuffer, camera, inputHandler) => {
62
-
63
- console.log('test camera.view ', camera.view)
64
- // Update spotlight matrices
65
- this.update();
66
-
67
- const now = Date.now();
68
-
69
- // Get camera matrices
70
- camera.update(now, inputHandler()); // Your camera class should also update view/projection
71
- const camVP = mat4.multiply(camera.projectionMatrix, camera.view);
72
-
73
- // Prepare float data
74
- const sceneData = new Float32Array(16 + 16 + 4); // 2 matrices + vec3
75
-
76
- // Light view-proj matrix
77
- sceneData.set(this.viewProjMatrix, 0);
78
-
79
- // Camera view-proj matrix
80
- sceneData.set(camVP, 16);
81
-
82
- // Light position (vec3f + padding)
83
- sceneData.set(this.position, 32);
84
-
85
- // Write to GPU
86
- this.device.queue.writeBuffer(
87
- sceneUniformBuffer,
88
- 0,
89
- sceneData.buffer,
90
- sceneData.byteOffset,
91
- sceneData.byteLength
92
- );
93
-
94
- console.log('light.viewProj[0..3]', this.viewProjMatrix.slice(0, 4));
95
- console.log('camera.vp[0..3]', camVP.slice(0, 4));
96
- }
97
-
98
- prepareBuffer(device) {
99
- this.device = device;
100
- this.spotlightUniformBuffer = device.createBuffer({
101
- size: 16 * 4, // 64 bytes
102
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
103
- });
104
-
105
- const spotlightData = this.getLightDataBuffer();
106
-
107
- device.queue.writeBuffer(
108
- this.spotlightUniformBuffer,
109
- 0,
110
- spotlightData.buffer,
111
- spotlightData.byteOffset,
112
- spotlightData.byteLength
113
- );
114
- }
115
-
116
- getLightDataBuffer() {
117
- return new Float32Array([
118
- ...this.position, 0.0,
119
- ...this.direction, 0.0,
120
- this.innerCutoff,
121
- this.outerCutoff,
122
- 0.0,
123
- 0.0,
124
- ]);
125
- }
126
- }