matrix-engine-wgpu 1.4.0 → 1.4.2

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/src/world.js CHANGED
@@ -20,12 +20,10 @@ import {SpotLight} from "./engine/lights.js";
20
20
  * @github zlatnaspirala
21
21
  */
22
22
  export default class MatrixEngineWGPU {
23
- lightContainer
24
23
 
25
24
  mainRenderBundle = [];
26
25
  lightContainer = [];
27
26
  frame = () => {};
28
-
29
27
  entityHolder = [];
30
28
 
31
29
  entityArgPass = {
@@ -68,7 +66,7 @@ export default class MatrixEngineWGPU {
68
66
  this.mainCameraParams = options.mainCameraParams;
69
67
 
70
68
  const target = this.options.appendTo || document.body;
71
- var canvas = document.createElement('canvas')
69
+ var canvas = document.createElement('canvas');
72
70
  canvas.id = this.options.canvasId;
73
71
  if(this.options.canvasSize == 'fullscreen') {
74
72
  canvas.width = window.innerWidth;
@@ -81,11 +79,10 @@ export default class MatrixEngineWGPU {
81
79
 
82
80
  // The camera types
83
81
  const initialCameraPosition = vec3.create(0, 0, 0);
84
- // console.log('passed : o.mainCameraParams.responseCoef ', o.mainCameraParams.responseCoef)
85
82
  this.mainCameraParams = {
86
83
  type: this.options.mainCameraParams.type,
87
84
  responseCoef: this.options.mainCameraParams.responseCoef
88
- }
85
+ };
89
86
 
90
87
  this.cameras = {
91
88
  arcball: new ArcballCamera({position: initialCameraPosition}),
@@ -139,9 +136,86 @@ export default class MatrixEngineWGPU {
139
136
  createGlobalStuff() {
140
137
  this.spotlightUniformBuffer = this.device.createBuffer({
141
138
  label: 'spotlightUniformBufferGLOBAL',
142
- size: this.MAX_SPOTLIGHTS * 80,
139
+ size: this.MAX_SPOTLIGHTS * 144,
143
140
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
144
141
  });
142
+
143
+ this.SHADOW_RES = 1024;
144
+ this.createTexArrayForShadows()
145
+
146
+ this.mainDepthTexture = this.device.createTexture({
147
+ size: [this.canvas.width, this.canvas.height],
148
+ format: 'depth24plus',
149
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
150
+ });
151
+
152
+ this.mainDepthView = this.mainDepthTexture.createView();
153
+
154
+ this.mainRenderPassDesc = {
155
+ label: 'mainRenderPassDesc',
156
+ colorAttachments: [{
157
+ view: undefined, // set each frame
158
+ loadOp: 'clear',
159
+ storeOp: 'store',
160
+ clearValue: [0.02, 0.02, 0.02, 1],
161
+ }],
162
+ depthStencilAttachment: {
163
+ view: this.mainDepthView, // fixed
164
+ depthLoadOp: 'clear',
165
+ depthStoreOp: 'store',
166
+ depthClearValue: 1.0,
167
+ },
168
+ };
169
+ }
170
+ createTexArrayForShadows() {
171
+ let numberOfLights = this.lightContainer.length;
172
+ if(this.lightContainer.length == 0) {
173
+ // console.warn('Wait for init light instance')
174
+ setTimeout(() => {
175
+ // console.info('Test light again...')
176
+ this.createMe();
177
+ }, 800);
178
+ }
179
+
180
+ this.createMe = () => {
181
+ Math.max(1, this.lightContainer.length);
182
+ if(this.lightContainer.length == 0) {
183
+ setTimeout(() => {
184
+ console.warn('Create now test...')
185
+ this.createMe();
186
+ }, 800);
187
+ return;
188
+ }
189
+
190
+ console.warn('Create this.shadowTextureArray...')
191
+ this.shadowTextureArray = this.device.createTexture({
192
+ label: `shadowTextureArray[GLOBAL] num of light ${numberOfLights}`,
193
+ size: {
194
+ width: 1024,
195
+ height: 1024,
196
+ depthOrArrayLayers: numberOfLights, // at least 1
197
+ },
198
+ dimension: '2d',
199
+ format: 'depth32float',
200
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
201
+ });
202
+
203
+ this.shadowArrayView = this.shadowTextureArray.createView({
204
+ dimension: '2d-array'
205
+ });
206
+
207
+ this.shadowVideoTexture = this.device.createTexture({
208
+ size: [1024, 1024],
209
+ format: "depth32float",
210
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
211
+ });
212
+
213
+ this.shadowVideoView = this.shadowVideoTexture.createView({
214
+ dimension: "2d",
215
+ });
216
+ }
217
+
218
+ this.createMe();
145
219
  }
146
220
 
147
221
  getSceneObjectByName(name) {
@@ -250,9 +324,9 @@ export default class MatrixEngineWGPU {
250
324
 
251
325
  addLight(o) {
252
326
  const camera = this.cameras[this.mainCameraParams.type];
253
- let newLight = new SpotLight(camera, this.inputHandler);
254
- newLight.prepareBuffer(this.device);
327
+ let newLight = new SpotLight(camera, this.inputHandler, this.device);
255
328
  this.lightContainer.push(newLight);
329
+ this.createTexArrayForShadows();
256
330
  console.log(`%cAdd light: ${newLight}`, LOG_FUNNY_SMALL);
257
331
  }
258
332
 
@@ -300,14 +374,13 @@ export default class MatrixEngineWGPU {
300
374
  // scale for all second option!
301
375
  o.objAnim.scaleAll = function(s) {
302
376
  for(var k in this.meshList) {
303
- console.log('SCALE');
377
+ console.log('SCALE meshList');
304
378
  this.meshList[k].setScale(s);
305
379
  }
306
380
  }
307
381
  }
308
- let myMesh1 = new MEMeshObj(this.canvas, this.device, this.context, o);
382
+ let myMesh1 = new MEMeshObj(this.canvas, this.device, this.context, o, this.inputHandler);
309
383
  myMesh1.spotlightUniformBuffer = this.spotlightUniformBuffer;
310
- myMesh1.inputHandler = this.inputHandler;
311
384
  myMesh1.clearColor = clearColor;
312
385
  if(o.physics.enabled == true) {
313
386
  this.matrixAmmo.addPhysics(myMesh1, o.physics)
@@ -325,38 +398,19 @@ export default class MatrixEngineWGPU {
325
398
  this.canvas.remove();
326
399
  }
327
400
 
328
- test = () => {
329
- const now = Date.now();
330
- // First frame safety
331
- let dt = (now - this.lastFrameMS) / this.mainCameraParams.responseCoef;
332
- if(!this.lastFrameMS) {dt = 16;}
333
- this.lastFrameMS = now;
334
- const camera = this.cameras[this.mainCameraParams.type];
335
- camera.update(dt, this.inputHandler());
336
- const camVP = mat4.multiply(camera.projectionMatrix, camera.view); // P * V
337
-
338
- for(const mesh of this.mainRenderBundle) {
339
- // scene buffer layout = 0..63 lightVP, 64..127 camVP, 128..143 lightPos(+pad)
340
- this.device.queue.writeBuffer(
341
- mesh.sceneUniformBuffer,
342
- 64, // cameraViewProjMatrix offset
343
- camVP.buffer,
344
- camVP.byteOffset,
345
- camVP.byteLength
346
- );
347
- }
348
- }
349
-
350
401
  updateLights() {
351
- // Update buffer every frame
352
- const data = new Float32Array(this.MAX_SPOTLIGHTS * 20);
402
+ const floatsPerLight = 36; // not 20 anymore
403
+ const data = new Float32Array(this.MAX_SPOTLIGHTS * floatsPerLight);
404
+
353
405
  for(let i = 0;i < this.MAX_SPOTLIGHTS;i++) {
354
406
  if(i < this.lightContainer.length) {
355
- data.set(this.lightContainer[i].getLightDataBuffer(), i * 20);
407
+ const buf = this.lightContainer[i].getLightDataBuffer();
408
+ data.set(buf, i * floatsPerLight);
356
409
  } else {
357
- data.set(new Float32Array(20), i * 20);
410
+ data.set(new Float32Array(floatsPerLight), i * floatsPerLight);
358
411
  }
359
412
  }
413
+
360
414
  this.device.queue.writeBuffer(this.spotlightUniformBuffer, 0, data.buffer);
361
415
  }
362
416
 
@@ -365,60 +419,110 @@ export default class MatrixEngineWGPU {
365
419
  setTimeout(() => {requestAnimationFrame(this.frame)}, 200);
366
420
  return;
367
421
  }
422
+
423
+ let noPass = false;
424
+
425
+ this.mainRenderBundle.forEach((meItem, index) => {
426
+ if(meItem.isVideo == true) {
427
+ if(!meItem.externalTexture || meItem.video.readyState < 2) {
428
+ console.log('no rendere for video not ready')
429
+ // this.externalTexture = this.device.importExternalTexture({source: this.video});
430
+ noPass = true;
431
+ setTimeout(() => requestAnimationFrame(this.frame), 1500)
432
+ return;
433
+ }
434
+ }
435
+ })
436
+
437
+ if(noPass == true) {
438
+ console.log('no rendere for video not ready !!!!')
439
+ return;
440
+ }
441
+
442
+ // let pass;
443
+ // let commandEncoder;
368
444
  try {
369
- let shadowPass = null;
370
- let renderPass;
371
445
  let commandEncoder = this.device.createCommandEncoder();
372
-
373
446
  this.updateLights()
374
- this.test()
375
-
376
447
  // 1️⃣ Update light data (position, direction, uniforms)
377
448
  for(const light of this.lightContainer) {
449
+ light.update()
450
+ // light.updateSceneUniforms(this.mainRenderBundle, this.cameras.WASD);
378
451
  this.mainRenderBundle.forEach((meItem, index) => {
379
-
380
- light.updateSceneUniforms(this.mainRenderBundle, this.cameras.WASD);
452
+ meItem.position.update()
453
+ meItem.updateModelUniformBuffer()
454
+ // if(meItem.isVideo != true) {
455
+ meItem.getTransformationMatrix(this.mainRenderBundle, light)
456
+ // }
381
457
  })
382
458
  }
383
-
384
- this.mainRenderBundle.forEach((meItem, index) => {meItem.position.update()})
385
459
  if(this.matrixAmmo) this.matrixAmmo.updatePhysics();
386
- const firstItem = this.mainRenderBundle[0];
387
- shadowPass = commandEncoder.beginRenderPass(firstItem.shadowPassDescriptor);
388
- shadowPass.setPipeline(firstItem.shadowPipeline);
389
- for(const meItem of this.mainRenderBundle) {
390
- meItem.drawShadows(shadowPass);
460
+
461
+ for(let i = 0;i < this.lightContainer.length;i++) {
462
+ const light = this.lightContainer[i];
463
+
464
+ let ViewPerLightRenderShadowPass = this.shadowTextureArray.createView({
465
+ dimension: '2d',
466
+ baseArrayLayer: i,
467
+ arrayLayerCount: 1, // must be > 0
468
+ baseMipLevel: 0,
469
+ mipLevelCount: 1,
470
+ });
471
+
472
+ const shadowPass = commandEncoder.beginRenderPass({
473
+ label: "shadowPass",
474
+ colorAttachments: [],
475
+ depthStencilAttachment: {
476
+ view: ViewPerLightRenderShadowPass,
477
+ depthLoadOp: 'clear',
478
+ depthStoreOp: 'store',
479
+ depthClearValue: 1.0,
480
+ }
481
+ });
482
+
483
+ shadowPass.setPipeline(light.shadowPipeline);
484
+ for(const [meshIndex, mesh] of this.mainRenderBundle.entries()) {
485
+ if(mesh.videoIsReady == 'NONE') {
486
+ shadowPass.setBindGroup(0, light.getShadowBindGroup(mesh, meshIndex));
487
+ shadowPass.setBindGroup(1, mesh.modelBindGroup);
488
+ mesh.drawShadows(shadowPass, light);
489
+ }
490
+ }
491
+ shadowPass.end();
391
492
  }
392
- shadowPass.end();
393
-
394
- this.mainRenderBundle.forEach((meItem, index) => {
395
- if(index == 0) {
396
- meItem.draw(commandEncoder);
397
- meItem.renderPassDescriptor.colorAttachments[0].view =
398
- this.context.getCurrentTexture().createView();
399
- renderPass = commandEncoder.beginRenderPass(meItem.renderPassDescriptor);
400
- renderPass.setPipeline(meItem.pipeline);
401
- } else {
402
- meItem.draw(commandEncoder);
493
+ const currentTextureView = this.context.getCurrentTexture().createView();
494
+ this.mainRenderPassDesc.colorAttachments[0].view = currentTextureView;
495
+ let pass = commandEncoder.beginRenderPass(this.mainRenderPassDesc);
496
+ // Loop over each mesh
497
+ for(const mesh of this.mainRenderBundle) {
498
+ pass.setPipeline(mesh.pipeline);
499
+ if(!mesh.sceneBindGroupForRender || (mesh.FINISH_VIDIO_INIT == false && mesh.isVideo == true)) {
500
+ for(const m of this.mainRenderBundle) {
501
+ if(m.isVideo == true) {
502
+ console.log('✅shadowVideoView', this.shadowVideoView)
503
+ m.shadowDepthTextureView = this.shadowVideoView;
504
+ m.FINISH_VIDIO_INIT = true;
505
+ m.setupPipeline();
506
+ } else {
507
+ m.shadowDepthTextureView = this.shadowArrayView;
508
+ m.setupPipeline();
509
+ }
510
+ }
403
511
  }
404
- })
405
-
406
- this.mainRenderBundle.forEach((meItem, index) => {
407
- meItem.drawElements(renderPass);
408
- })
409
- if(renderPass) renderPass.end();
410
-
512
+ mesh.drawElements(pass, this.lightContainer);
513
+ }
514
+ pass.end();
411
515
  this.device.queue.submit([commandEncoder.finish()]);
412
516
  requestAnimationFrame(this.frame);
413
517
  } catch(err) {
414
- console.log('%cLoop (err):' + err, LOG_WARN)
518
+ console.log('%cLoop(err):' + err, LOG_WARN)
415
519
  requestAnimationFrame(this.frame);
416
520
  }
417
521
  }
418
522
 
419
523
  framePassPerObject = () => {
420
524
  let commandEncoder = this.device.createCommandEncoder();
421
- this.matrixAmmo.updatePhysics();
525
+ if(this.matrixAmmo.rigidBodies.length > 0) this.matrixAmmo.updatePhysics();
422
526
  this.mainRenderBundle.forEach((meItem, index) => {
423
527
  if(index === 0) {
424
528
  if(meItem.renderPassDescriptor) meItem.renderPassDescriptor.colorAttachments[0].loadOp = 'clear';