matrix-engine-wgpu 1.0.1 → 1.0.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/LICENSE CHANGED
@@ -1,21 +1,26 @@
1
- MIT License
1
+ Copyright 2019 WebGPU Samples Contributors
2
2
 
3
- Copyright (c) 2024 Nikola
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are met:
4
5
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
6
+ 1. Redistributions of source code must retain the above copyright notice,
7
+ this list of conditions and the following disclaimer.
11
8
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
14
12
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
13
+ 3. Neither the name of the copyright holder nor the names of its
14
+ contributors may be used to endorse or promote products derived from this
15
+ software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/REFERENCE.md CHANGED
@@ -1,7 +1,53 @@
1
1
 
2
+ ### Best solution for learning:
2
3
 
4
+ https://webgpufundamentals.org/webgpu/lessons/webgpu-from-webgl.html
3
5
 
4
- Best solution for learning:
5
6
 
6
- https://webgpufundamentals.org/webgpu/lessons/webgpu-from-webgl.html
7
+ ### I got answer from gman at stackoverflow.com :
8
+
9
+ https://stackoverflow.com/questions/78093302/webgpu-i-cant-draw-two-object-in-same-scene/78098135#78098135
10
+
11
+ Interest facts about webGPU tech:
12
+
13
+ ```
14
+ You can have different pipelines if the things you want to draw actually need different pipelines but if possible you could try to have less pipelines than more. In the example above, if you cube had a different pipeline than the sphere you'd call setPipeline with the sphere's pipeline after drawing the cube and before drawing the sphere.
15
+ ```
16
+
17
+ ```
18
+ Let's assume you only have one pipeline and 2 things you want to draw with that pipeline, a cube, and a sphere. In pseudo code you might do something like this
19
+
20
+ at init time
21
+ create pipeline
22
+ create vertex buffers for cube
23
+ create uniform buffers for cube
24
+ create bindGroup for cube
25
+ create vertex buffers for sphere
26
+ create uniform buffers for sphere
27
+ create bindGroup for cube
28
+ at render time
29
+ create command buffer
30
+ begin render pass
31
+ set pipeline
32
+ set vertex buffers for cube
33
+ set bindGroups for cube
34
+ draw cube
35
+ set vertex buffers for sphere
36
+ set bindgroups for sphere
37
+ draw sphere
38
+ end render pass
39
+ finish command buffer
40
+ submit command buffer
41
+
42
+ Things to notice, there is only one command buffer. There is only 1 render pass.
43
+ ```
44
+
45
+
46
+ ```
47
+ For each render pass, you need to set loadOp and storeOp correctly.
48
+ Most examples that have one render pass set loadOp: 'clear' but in the example above, if render pass 2 had loadOp: 'clear' it would erase the results from render pass 1. Instead it would need to be loadOp: 'load'.
49
+ ```
50
+
51
+ YEs this is happening " would erase the results from render pass 1 "
52
+
7
53
 
package/main.js CHANGED
@@ -1,20 +1,26 @@
1
1
  import MatrixEngineWGPU from "./src/meWGPU";
2
2
 
3
- let application = new MatrixEngineWGPU(()=> {
3
+ let application = new MatrixEngineWGPU({ useSingleRenderPass: false }, () => {
4
4
 
5
5
  let c = {
6
- position: { x: -1, y: 3, z: -10},
6
+ position: {x: -3, y: 0, z: -5},
7
+ rotation: {x: 0, y: 45, z: 0},
8
+ rotationSpeed: {x: 0, y: 0, z: 0},
7
9
  texturesPaths: ['./res/textures/rust.jpg']
8
10
  };
9
11
 
10
12
  let o = {
11
- position: { x: 5, y: 2, z: -10},
13
+ position: {x: 3, y: 0, z: -10},
14
+ rotation: {x: 0, y: 45, z: 0},
15
+ rotationSpeed: {x: 0, y: 10, z: 0},
12
16
  texturesPaths: ['./res/textures/rust.jpg']
13
17
  };
14
18
 
15
- application.addCube(c)
19
+
16
20
  application.addBall(o)
17
21
 
22
+ application.addCube(c)
23
+
18
24
 
19
25
  })
20
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matrix-engine-wgpu",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "webGPU powered pwa application.Crazy fast rendering.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/public/app.js CHANGED
@@ -3,25 +3,47 @@
3
3
 
4
4
  var _meWGPU = _interopRequireDefault(require("./src/meWGPU"));
5
5
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
- let application = new _meWGPU.default(() => {
6
+ let application = new _meWGPU.default({
7
+ useSingleRenderPass: false
8
+ }, () => {
7
9
  let c = {
8
10
  position: {
9
- x: -1,
10
- y: 3,
11
- z: -10
11
+ x: -3,
12
+ y: 0,
13
+ z: -5
14
+ },
15
+ rotation: {
16
+ x: 0,
17
+ y: 45,
18
+ z: 0
19
+ },
20
+ rotationSpeed: {
21
+ x: 0,
22
+ y: 0,
23
+ z: 0
12
24
  },
13
25
  texturesPaths: ['./res/textures/rust.jpg']
14
26
  };
15
27
  let o = {
16
28
  position: {
17
- x: 5,
18
- y: 2,
29
+ x: 3,
30
+ y: 0,
19
31
  z: -10
20
32
  },
33
+ rotation: {
34
+ x: 0,
35
+ y: 45,
36
+ z: 0
37
+ },
38
+ rotationSpeed: {
39
+ x: 0,
40
+ y: 10,
41
+ z: 0
42
+ },
21
43
  texturesPaths: ['./res/textures/rust.jpg']
22
44
  };
23
- application.addCube(c);
24
45
  application.addBall(o);
46
+ application.addCube(c);
25
47
  });
26
48
  window.app = application;
27
49
 
@@ -5386,6 +5408,7 @@ class MEBall {
5386
5408
  constructor(canvas, device, context, o) {
5387
5409
  this.context = context;
5388
5410
  this.device = device;
5411
+ this.entityArgPass = o.entityArgPass;
5389
5412
  this.SphereLayout = {
5390
5413
  vertexStride: 8 * 4,
5391
5414
  positionsOffset: 0,
@@ -5397,6 +5420,10 @@ class MEBall {
5397
5420
  this.texturesPaths.push(t);
5398
5421
  });
5399
5422
  this.position = new _matrixClass.Position(o.position.x, o.position.y, o.position.z);
5423
+ this.rotation = new _matrixClass.Rotation(o.rotation.x, o.rotation.y, o.rotation.z);
5424
+ this.rotation.rotationSpeed.x = o.rotationSpeed.x;
5425
+ this.rotation.rotationSpeed.y = o.rotationSpeed.y;
5426
+ this.rotation.rotationSpeed.z = o.rotationSpeed.z;
5400
5427
  this.shaderModule = device.createShaderModule({
5401
5428
  code: _shaders.BALL_SHADER
5402
5429
  });
@@ -5483,26 +5510,23 @@ class MEBall {
5483
5510
  this.renderables = [this.planet];
5484
5511
 
5485
5512
  // this.ensureEnoughAsteroids(asteroids, this.transform);
5486
-
5487
5513
  this.renderPassDescriptor = {
5488
5514
  colorAttachments: [{
5489
5515
  view: undefined,
5490
- // Assigned later
5491
-
5492
5516
  clearValue: {
5493
5517
  r: 0.0,
5494
5518
  g: 0.0,
5495
5519
  b: 0.0,
5496
5520
  a: 1.0
5497
5521
  },
5498
- loadOp: 'clear',
5499
- storeOp: 'store'
5522
+ loadOp: this.entityArgPass.loadOp,
5523
+ storeOp: this.entityArgPass.storeOp
5500
5524
  }],
5501
5525
  depthStencilAttachment: {
5502
5526
  view: this.depthTexture.createView(),
5503
5527
  depthClearValue: 1.0,
5504
- depthLoadOp: 'clear',
5505
- depthStoreOp: 'store'
5528
+ depthLoadOp: this.entityArgPass.depthLoadOp,
5529
+ depthStoreOp: this.entityArgPass.depthStoreOp
5506
5530
  }
5507
5531
  };
5508
5532
  const aspect = canvas.width / canvas.height;
@@ -5614,9 +5638,9 @@ class MEBall {
5614
5638
  const viewMatrix = _wgpuMatrix.mat4.identity();
5615
5639
  _wgpuMatrix.mat4.translate(viewMatrix, _wgpuMatrix.vec3.fromValues(pos.x, pos.y, pos.z), viewMatrix);
5616
5640
  const now = Date.now() / 1000;
5617
- _wgpuMatrix.mat4.rotateZ(viewMatrix, Math.PI * 0.1, viewMatrix);
5618
- _wgpuMatrix.mat4.rotateX(viewMatrix, Math.PI * 0.1, viewMatrix);
5619
- _wgpuMatrix.mat4.rotateY(viewMatrix, now * 0.05, viewMatrix);
5641
+ _wgpuMatrix.mat4.rotateX(viewMatrix, Math.PI * this.rotation.getRotX(), viewMatrix);
5642
+ _wgpuMatrix.mat4.rotateY(viewMatrix, Math.PI * this.rotation.getRotY(), viewMatrix);
5643
+ _wgpuMatrix.mat4.rotateZ(viewMatrix, Math.PI * this.rotation.getRotZ(), viewMatrix);
5620
5644
  _wgpuMatrix.mat4.multiply(this.projectionMatrix, viewMatrix, this.modelViewProjectionMatrix);
5621
5645
  return this.modelViewProjectionMatrix;
5622
5646
  }
@@ -5722,6 +5746,7 @@ class MEBall {
5722
5746
  indices: new Uint16Array(indices)
5723
5747
  };
5724
5748
  }
5749
+
5725
5750
  // Render bundles function as partial, limited render passes, so we can use the
5726
5751
  // same code both to render the scene normally and to build the render bundle.
5727
5752
  renderScene(passEncoder) {
@@ -5778,6 +5803,8 @@ class MECube {
5778
5803
  constructor(canvas, device, context, o) {
5779
5804
  this.device = device;
5780
5805
  this.context = context;
5806
+ this.entityArgPass = o.entityArgPass;
5807
+ console.log('passed args', o.entityArgPass);
5781
5808
  this.shaderModule = device.createShaderModule({
5782
5809
  code: _shaders.BALL_SHADER
5783
5810
  });
@@ -5787,6 +5814,10 @@ class MECube {
5787
5814
  });
5788
5815
  this.presentationFormat = navigator.gpu.getPreferredCanvasFormat();
5789
5816
  this.position = new _matrixClass.Position(o.position.x, o.position.y, o.position.z);
5817
+ this.rotation = new _matrixClass.Rotation(o.rotation.x, o.rotation.y, o.rotation.z);
5818
+ this.rotation.rotationSpeed.x = o.rotationSpeed.x;
5819
+ this.rotation.rotationSpeed.y = o.rotationSpeed.y;
5820
+ this.rotation.rotationSpeed.z = o.rotationSpeed.z;
5790
5821
  this.pipeline = device.createRenderPipeline({
5791
5822
  layout: 'auto',
5792
5823
  vertex: {
@@ -5869,9 +5900,7 @@ class MECube {
5869
5900
  this.planet.bindGroup = this.createSphereBindGroup(this.texture0, this.transform);
5870
5901
  var asteroids = [this.createSphereRenderable(0.2, 8, 6, 0.15), this.createSphereRenderable(0.13, 8, 6, 0.15)];
5871
5902
  this.renderables = [this.planet];
5872
-
5873
5903
  // this.ensureEnoughAsteroids(asteroids, this.transform);
5874
-
5875
5904
  this.renderPassDescriptor = {
5876
5905
  colorAttachments: [{
5877
5906
  view: undefined,
@@ -5881,14 +5910,14 @@ class MECube {
5881
5910
  b: 0.0,
5882
5911
  a: 1.0
5883
5912
  },
5884
- loadOp: 'clear',
5885
- storeOp: 'store'
5913
+ loadOp: this.entityArgPass.loadOp,
5914
+ storeOp: this.entityArgPass.storeOp
5886
5915
  }],
5887
5916
  depthStencilAttachment: {
5888
5917
  view: this.depthTexture.createView(),
5889
5918
  depthClearValue: 1.0,
5890
- depthLoadOp: 'clear',
5891
- depthStoreOp: 'store'
5919
+ depthLoadOp: this.entityArgPass.depthLoadOp,
5920
+ depthStoreOp: this.entityArgPass.depthStoreOp
5892
5921
  }
5893
5922
  };
5894
5923
  const aspect = canvas.width / canvas.height;
@@ -5939,7 +5968,7 @@ class MECube {
5939
5968
  }
5940
5969
  }
5941
5970
  updateRenderBundle() {
5942
- console.log('sss');
5971
+ console.log('[CUBE] updateRenderBundle');
5943
5972
  const renderBundleEncoder = this.device.createRenderBundleEncoder({
5944
5973
  colorFormats: [this.presentationFormat],
5945
5974
  depthStencilFormat: 'depth24plus'
@@ -5997,12 +6026,13 @@ class MECube {
5997
6026
  return bindGroup;
5998
6027
  }
5999
6028
  getTransformationMatrix(pos) {
6029
+ // const now = Date.now() / 1000;
6030
+
6000
6031
  const viewMatrix = _wgpuMatrix.mat4.identity();
6001
6032
  _wgpuMatrix.mat4.translate(viewMatrix, _wgpuMatrix.vec3.fromValues(pos.x, pos.y, pos.z), viewMatrix);
6002
- const now = Date.now() / 1000;
6003
- _wgpuMatrix.mat4.rotateZ(viewMatrix, Math.PI * 0, viewMatrix);
6004
- _wgpuMatrix.mat4.rotateX(viewMatrix, Math.PI * 0, viewMatrix);
6005
- _wgpuMatrix.mat4.rotateY(viewMatrix, -45, viewMatrix);
6033
+ _wgpuMatrix.mat4.rotateX(viewMatrix, Math.PI * this.rotation.getRotX(), viewMatrix);
6034
+ _wgpuMatrix.mat4.rotateY(viewMatrix, Math.PI * this.rotation.getRotY(), viewMatrix);
6035
+ _wgpuMatrix.mat4.rotateZ(viewMatrix, Math.PI * this.rotation.getRotZ(), viewMatrix);
6006
6036
  _wgpuMatrix.mat4.multiply(this.projectionMatrix, viewMatrix, this.modelViewProjectionMatrix);
6007
6037
  return this.modelViewProjectionMatrix;
6008
6038
  }
@@ -6145,7 +6175,7 @@ exports.default = MECube;
6145
6175
  Object.defineProperty(exports, "__esModule", {
6146
6176
  value: true
6147
6177
  });
6148
- exports.Position = void 0;
6178
+ exports.Rotation = exports.Position = void 0;
6149
6179
  // Sub classes for matrix-wgpu
6150
6180
 
6151
6181
  /**
@@ -6296,6 +6326,48 @@ class Position {
6296
6326
  }
6297
6327
  }
6298
6328
  exports.Position = Position;
6329
+ class Rotation {
6330
+ constructor(x, y, z) {
6331
+ // Not in use for nwo this is from matrix-engine project [nameUniq]
6332
+ this.nameUniq = null;
6333
+ if (typeof x == 'undefined') x = 0;
6334
+ if (typeof y == 'undefined') y = 0;
6335
+ if (typeof z == 'undefined') z = 0;
6336
+ this.x = x;
6337
+ this.y = y;
6338
+ this.z = z;
6339
+ this.rotationSpeed = {
6340
+ x: 0,
6341
+ y: 0,
6342
+ z: 0
6343
+ };
6344
+ }
6345
+ getRotX() {
6346
+ if (this.rotationSpeed.x == 0) {
6347
+ return this.x;
6348
+ } else {
6349
+ this.x = this.x + this.rotationSpeed.x * 0.001;
6350
+ return this.x;
6351
+ }
6352
+ }
6353
+ getRotY() {
6354
+ if (this.rotationSpeed.y == 0) {
6355
+ return this.y;
6356
+ } else {
6357
+ this.y = this.y + this.rotationSpeed.y * 0.001;
6358
+ return this.y;
6359
+ }
6360
+ }
6361
+ getRotZ() {
6362
+ if (this.rotationSpeed.z == 0) {
6363
+ return this.z;
6364
+ } else {
6365
+ this.z = this.z + this.rotationSpeed.z * 0.001;
6366
+ return this.z;
6367
+ }
6368
+ }
6369
+ }
6370
+ exports.Rotation = Rotation;
6299
6371
 
6300
6372
  },{}],6:[function(require,module,exports){
6301
6373
  "use strict";
@@ -6307,13 +6379,26 @@ exports.default = void 0;
6307
6379
  var _ball = _interopRequireDefault(require("./engine/ball.js"));
6308
6380
  var _cube = _interopRequireDefault(require("./engine/cube.js"));
6309
6381
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6310
- // import { mat4, vec3 } from 'wgpu-matrix';
6311
- // import { createSphereMesh, SphereLayout } from './src/engine/ballsBuffer.js';
6312
-
6313
6382
  class MatrixEngineWGPU {
6314
6383
  mainRenderBundle = [];
6315
6384
  rbContainer = [];
6316
- constructor(callback) {
6385
+ frame = () => {};
6386
+ entityArgPass = {
6387
+ loadOp: 'clear',
6388
+ storeOp: 'store',
6389
+ depthLoadOp: 'clear',
6390
+ depthStoreOp: 'store'
6391
+ };
6392
+ constructor(options, callback) {
6393
+ console.log('typeof options ', typeof options);
6394
+ console.log('typeof options ', options);
6395
+ if (typeof options == 'undefined' || typeof options == "function") {
6396
+ this.options = {
6397
+ useSingleRenderPass: true
6398
+ };
6399
+ callback = options;
6400
+ }
6401
+ this.options = options;
6317
6402
  var canvas = document.createElement('canvas');
6318
6403
  canvas.width = window.innerWidth;
6319
6404
  canvas.height = window.innerHeight;
@@ -6340,8 +6425,41 @@ class MatrixEngineWGPU {
6340
6425
  format: presentationFormat,
6341
6426
  alphaMode: 'premultiplied'
6342
6427
  });
6428
+ if (this.options.useSingleRenderPass == true) {
6429
+ this.makeDefaultRenderPassDescriptor();
6430
+ this.frame = this.frameSinglePass;
6431
+ } else {
6432
+ // must be
6433
+ this.frame = this.framePassPerObject;
6434
+ }
6343
6435
  this.run(callback);
6344
6436
  };
6437
+ makeDefaultRenderPassDescriptor = () => {
6438
+ this.depthTexture = this.device.createTexture({
6439
+ size: [this.canvas.width, this.canvas.height],
6440
+ format: 'depth24plus',
6441
+ usage: GPUTextureUsage.RENDER_ATTACHMENT
6442
+ });
6443
+ this.renderPassDescriptor = {
6444
+ colorAttachments: [{
6445
+ view: undefined,
6446
+ clearValue: {
6447
+ r: 0.0,
6448
+ g: 0.0,
6449
+ b: 0.0,
6450
+ a: 1.0
6451
+ },
6452
+ loadOp: 'clear',
6453
+ storeOp: 'store'
6454
+ }],
6455
+ depthStencilAttachment: {
6456
+ view: this.depthTexture.createView(),
6457
+ depthClearValue: 1.0,
6458
+ depthLoadOp: 'clear',
6459
+ depthStoreOp: 'store'
6460
+ }
6461
+ };
6462
+ };
6345
6463
  addCube = o => {
6346
6464
  if (typeof o === 'undefined') {
6347
6465
  var o = {
@@ -6350,7 +6468,18 @@ class MatrixEngineWGPU {
6350
6468
  y: 0,
6351
6469
  z: -4
6352
6470
  },
6353
- texturesPaths: ['./res/textures/default.png']
6471
+ texturesPaths: ['./res/textures/default.png'],
6472
+ rotation: {
6473
+ x: 0,
6474
+ y: 0,
6475
+ z: 0
6476
+ },
6477
+ rotationSpeed: {
6478
+ x: 0,
6479
+ y: 0,
6480
+ z: 0
6481
+ },
6482
+ entityArgPass: this.entityArgPass
6354
6483
  };
6355
6484
  } else {
6356
6485
  if (typeof o.position === 'undefined') {
@@ -6360,9 +6489,24 @@ class MatrixEngineWGPU {
6360
6489
  z: -4
6361
6490
  };
6362
6491
  }
6492
+ if (typeof o.rotation === 'undefined') {
6493
+ o.rotation = {
6494
+ x: 0,
6495
+ y: 0,
6496
+ z: 0
6497
+ };
6498
+ }
6499
+ if (typeof o.rotationSpeed === 'undefined') {
6500
+ o.rotationSpeed = {
6501
+ x: 0,
6502
+ y: 0,
6503
+ z: 0
6504
+ };
6505
+ }
6363
6506
  if (typeof o.texturesPaths === 'undefined') {
6364
6507
  o.texturesPaths = ['./res/textures/default.png'];
6365
6508
  }
6509
+ o.entityArgPass = this.entityArgPass;
6366
6510
  }
6367
6511
  let myCube1 = new _cube.default(this.canvas, this.device, this.context, o);
6368
6512
  this.mainRenderBundle.push(myCube1);
@@ -6375,7 +6519,18 @@ class MatrixEngineWGPU {
6375
6519
  y: 0,
6376
6520
  z: -4
6377
6521
  },
6378
- texturesPaths: ['./res/textures/default.png']
6522
+ texturesPaths: ['./res/textures/default.png'],
6523
+ rotation: {
6524
+ x: 0,
6525
+ y: 0,
6526
+ z: 0
6527
+ },
6528
+ rotationSpeed: {
6529
+ x: 0,
6530
+ y: 0,
6531
+ z: 0
6532
+ },
6533
+ entityArgPass: this.entityArgPass
6379
6534
  };
6380
6535
  } else {
6381
6536
  if (typeof o.position === 'undefined') {
@@ -6385,9 +6540,24 @@ class MatrixEngineWGPU {
6385
6540
  z: -4
6386
6541
  };
6387
6542
  }
6543
+ if (typeof o.rotation === 'undefined') {
6544
+ o.rotation = {
6545
+ x: 0,
6546
+ y: 0,
6547
+ z: 0
6548
+ };
6549
+ }
6550
+ if (typeof o.rotationSpeed === 'undefined') {
6551
+ o.rotationSpeed = {
6552
+ x: 0,
6553
+ y: 0,
6554
+ z: 0
6555
+ };
6556
+ }
6388
6557
  if (typeof o.texturesPaths === 'undefined') {
6389
6558
  o.texturesPaths = ['./res/textures/default.png'];
6390
6559
  }
6560
+ o.entityArgPass = this.entityArgPass;
6391
6561
  }
6392
6562
  let myBall1 = new _ball.default(this.canvas, this.device, this.context, o);
6393
6563
  this.mainRenderBundle.push(myBall1);
@@ -6400,22 +6570,38 @@ class MatrixEngineWGPU {
6400
6570
  callback();
6401
6571
  }, 10);
6402
6572
  }
6403
- frame = () => {
6573
+ frameSinglePass = () => {
6574
+ console.log('single');
6404
6575
  let commandEncoder = this.device.createCommandEncoder();
6405
6576
  this.rbContainer = [];
6406
6577
  let passEncoder;
6407
6578
  this.mainRenderBundle.forEach((meItem, index) => {
6408
6579
  meItem.draw();
6409
6580
  this.rbContainer.push(meItem.renderBundle);
6410
- if (index == 0) passEncoder = commandEncoder.beginRenderPass(meItem.renderPassDescriptor);
6581
+ // if(index == 0) passEncoder = commandEncoder.beginRenderPass(meItem.renderPassDescriptor);
6411
6582
  });
6412
-
6413
- // passEncoder.executeBundles([NIK.renderBundle, NIK2.renderBundle]);
6583
+ this.renderPassDescriptor.colorAttachments[0].view = this.context.getCurrentTexture().createView();
6584
+ passEncoder = commandEncoder.beginRenderPass(this.renderPassDescriptor);
6414
6585
  passEncoder.executeBundles(this.rbContainer);
6415
6586
  passEncoder.end();
6416
6587
  this.device.queue.submit([commandEncoder.finish()]);
6417
6588
  requestAnimationFrame(this.frame);
6418
6589
  };
6590
+ framePassPerObject = () => {
6591
+ console.log('framePassPerObject');
6592
+ let commandEncoder = this.device.createCommandEncoder();
6593
+ this.rbContainer = [];
6594
+ let passEncoder;
6595
+ this.mainRenderBundle.forEach((meItem, index) => {
6596
+ meItem.draw();
6597
+ this.rbContainer.push(meItem.renderBundle);
6598
+ passEncoder = commandEncoder.beginRenderPass(meItem.renderPassDescriptor);
6599
+ passEncoder.executeBundles(this.rbContainer);
6600
+ passEncoder.end();
6601
+ });
6602
+ this.device.queue.submit([commandEncoder.finish()]);
6603
+ requestAnimationFrame(this.frame);
6604
+ };
6419
6605
  }
6420
6606
  exports.default = MatrixEngineWGPU;
6421
6607
 
package/readme.md CHANGED
@@ -23,6 +23,9 @@ I publish (this repo) npm package with name `matrix-engine-wgpu`.
23
23
 
24
24
  For now i will use `createRenderBundleEncoder` for multi object scene draws.
25
25
 
26
+
27
+
28
+
26
29
  Main instance script:
27
30
  ```js
28
31
  let application = new MatrixEngineWGPU(()=> {
@@ -69,6 +72,36 @@ frame = () => {
69
72
 
70
73
  ## LICENCE
71
74
 
72
- - MIT LICENCE - Nikola Lukic zlatnaspirala@gmail.com 2024
73
75
  - Structural shema for project and personal learning inspired by:
74
76
  https://webgpu.github.io/webgpu-samples/samples/renderBundles
77
+
78
+ ### BSD 3-Clause
79
+
80
+ https://github.com/webgpu/webgpu-samples/blob/main/LICENSE.txt
81
+
82
+ Copyright 2019 WebGPU Samples Contributors
83
+
84
+ Redistribution and use in source and binary forms, with or without
85
+ modification, are permitted provided that the following conditions are met:
86
+
87
+ 1. Redistributions of source code must retain the above copyright notice,
88
+ this list of conditions and the following disclaimer.
89
+
90
+ 2. Redistributions in binary form must reproduce the above copyright notice,
91
+ this list of conditions and the following disclaimer in the documentation
92
+ and/or other materials provided with the distribution.
93
+
94
+ 3. Neither the name of the copyright holder nor the names of its
95
+ contributors may be used to endorse or promote products derived from this
96
+ software without specific prior written permission.
97
+
98
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
99
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
100
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
101
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
102
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
103
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
104
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
105
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
106
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
107
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,6 +1,6 @@
1
1
  import {BALL_SHADER} from "../shaders/shaders";
2
2
  import {mat4, vec3} from 'wgpu-matrix';
3
- import {Position} from "./matrix-class";
3
+ import {Position, Rotation} from "./matrix-class";
4
4
 
5
5
  export default class MEBall {
6
6
 
@@ -8,6 +8,8 @@ export default class MEBall {
8
8
  this.context = context;
9
9
  this.device = device;
10
10
 
11
+ this.entityArgPass = o.entityArgPass;
12
+
11
13
  this.SphereLayout = {
12
14
  vertexStride: 8 * 4,
13
15
  positionsOffset: 0,
@@ -22,6 +24,11 @@ export default class MEBall {
22
24
  })
23
25
 
24
26
  this.position = new Position(o.position.x, o.position.y, o.position.z)
27
+ this.rotation = new Rotation(o.rotation.x, o.rotation.y, o.rotation.z);
28
+ this.rotation.rotationSpeed.x = o.rotationSpeed.x;
29
+ this.rotation.rotationSpeed.y = o.rotationSpeed.y;
30
+ this.rotation.rotationSpeed.z = o.rotationSpeed.z;
31
+
25
32
  this.shaderModule = device.createShaderModule({code: BALL_SHADER});
26
33
  this.presentationFormat = navigator.gpu.getPreferredCanvasFormat();
27
34
 
@@ -128,23 +135,20 @@ export default class MEBall {
128
135
  this.renderables = [this.planet];
129
136
 
130
137
  // this.ensureEnoughAsteroids(asteroids, this.transform);
131
-
132
138
  this.renderPassDescriptor = {
133
139
  colorAttachments: [
134
140
  {
135
- view: undefined, // Assigned later
136
-
141
+ view: undefined,
137
142
  clearValue: {r: 0.0, g: 0.0, b: 0.0, a: 1.0},
138
- loadOp: 'clear',
139
- storeOp: 'store',
143
+ loadOp: this.entityArgPass.loadOp,
144
+ storeOp: this.entityArgPass.storeOp,
140
145
  },
141
146
  ],
142
147
  depthStencilAttachment: {
143
148
  view: this.depthTexture.createView(),
144
-
145
149
  depthClearValue: 1.0,
146
- depthLoadOp: 'clear',
147
- depthStoreOp: 'store',
150
+ depthLoadOp: this.entityArgPass.depthLoadOp,
151
+ depthStoreOp: this.entityArgPass.depthStoreOp,
148
152
  },
149
153
  };
150
154
 
@@ -281,9 +285,9 @@ export default class MEBall {
281
285
  mat4.translate(viewMatrix, vec3.fromValues(pos.x, pos.y, pos.z), viewMatrix);
282
286
  const now = Date.now() / 1000;
283
287
 
284
- mat4.rotateZ(viewMatrix, Math.PI * 0.1, viewMatrix);
285
- mat4.rotateX(viewMatrix, Math.PI * 0.1, viewMatrix);
286
- mat4.rotateY(viewMatrix, now * 0.05, viewMatrix);
288
+ mat4.rotateX(viewMatrix, Math.PI * this.rotation.getRotX(), viewMatrix);
289
+ mat4.rotateY(viewMatrix, Math.PI * this.rotation.getRotY(), viewMatrix);
290
+ mat4.rotateZ(viewMatrix, Math.PI * this.rotation.getRotZ(), viewMatrix);
287
291
 
288
292
  mat4.multiply(this.projectionMatrix, viewMatrix, this.modelViewProjectionMatrix);
289
293
  return this.modelViewProjectionMatrix;
@@ -402,12 +406,12 @@ export default class MEBall {
402
406
  }
403
407
  }
404
408
 
405
-
406
409
  return {
407
410
  vertices: new Float32Array(vertices),
408
411
  indices: new Uint16Array(indices),
409
412
  };
410
413
  }
414
+
411
415
  // Render bundles function as partial, limited render passes, so we can use the
412
416
  // same code both to render the scene normally and to build the render bundle.
413
417
  renderScene(passEncoder) {
@@ -1,6 +1,6 @@
1
1
  import {BALL_SHADER} from "../shaders/shaders";
2
2
  import {mat4, vec3} from 'wgpu-matrix';
3
- import {Position} from "./matrix-class";
3
+ import {Position, Rotation} from "./matrix-class";
4
4
 
5
5
  var SphereLayout = {
6
6
  vertexStride: 8 * 4,
@@ -15,6 +15,9 @@ export default class MECube {
15
15
  this.device = device;
16
16
  this.context = context;
17
17
 
18
+ this.entityArgPass = o.entityArgPass;
19
+
20
+ console.log('passed args', o.entityArgPass)
18
21
  this.shaderModule = device.createShaderModule({
19
22
  code: BALL_SHADER,
20
23
  });
@@ -26,7 +29,11 @@ export default class MECube {
26
29
  })
27
30
 
28
31
  this.presentationFormat = navigator.gpu.getPreferredCanvasFormat();
29
- this.position = new Position(o.position.x, o.position.y, o.position.z)
32
+ this.position = new Position(o.position.x, o.position.y, o.position.z);
33
+ this.rotation = new Rotation(o.rotation.x, o.rotation.y, o.rotation.z);
34
+ this.rotation.rotationSpeed.x = o.rotationSpeed.x;
35
+ this.rotation.rotationSpeed.y = o.rotationSpeed.y;
36
+ this.rotation.rotationSpeed.z = o.rotationSpeed.z;
30
37
  this.pipeline = device.createRenderPipeline({
31
38
  layout: 'auto',
32
39
  vertex: {
@@ -109,23 +116,21 @@ export default class MECube {
109
116
  ];
110
117
 
111
118
  this.renderables = [this.planet];
112
-
113
119
  // this.ensureEnoughAsteroids(asteroids, this.transform);
114
-
115
120
  this.renderPassDescriptor = {
116
121
  colorAttachments: [
117
122
  {
118
123
  view: undefined,
119
124
  clearValue: {r: 0.0, g: 0.0, b: 0.0, a: 1.0},
120
- loadOp: 'clear',
121
- storeOp: 'store',
125
+ loadOp: this.entityArgPass.loadOp,
126
+ storeOp: this.entityArgPass.storeOp,
122
127
  },
123
128
  ],
124
129
  depthStencilAttachment: {
125
130
  view: this.depthTexture.createView(),
126
131
  depthClearValue: 1.0,
127
- depthLoadOp: 'clear',
128
- depthStoreOp: 'store',
132
+ depthLoadOp: this.entityArgPass.depthLoadOp,
133
+ depthStoreOp: this.entityArgPass.depthStoreOp,
129
134
  },
130
135
  };
131
136
 
@@ -181,7 +186,7 @@ export default class MECube {
181
186
  }
182
187
 
183
188
  updateRenderBundle() {
184
- console.log('sss')
189
+ console.log('[CUBE] updateRenderBundle')
185
190
  const renderBundleEncoder = this.device.createRenderBundleEncoder({
186
191
  colorFormats: [this.presentationFormat],
187
192
  depthStencilFormat: 'depth24plus',
@@ -252,14 +257,19 @@ export default class MECube {
252
257
  }
253
258
 
254
259
  getTransformationMatrix(pos) {
260
+ // const now = Date.now() / 1000;
261
+
255
262
  const viewMatrix = mat4.identity();
263
+
256
264
  mat4.translate(viewMatrix, vec3.fromValues(pos.x, pos.y, pos.z), viewMatrix);
257
- const now = Date.now() / 1000;
258
- mat4.rotateZ(viewMatrix, Math.PI * 0, viewMatrix);
259
- mat4.rotateX(viewMatrix, Math.PI * 0, viewMatrix);
260
- mat4.rotateY(viewMatrix, -45, viewMatrix);
265
+
266
+ mat4.rotateX(viewMatrix, Math.PI * this.rotation.getRotX(), viewMatrix);
267
+ mat4.rotateY(viewMatrix, Math.PI * this.rotation.getRotY(), viewMatrix);
268
+ mat4.rotateZ(viewMatrix, Math.PI * this.rotation.getRotZ(), viewMatrix);
269
+
261
270
  mat4.multiply(this.projectionMatrix, viewMatrix, this.modelViewProjectionMatrix);
262
271
  return this.modelViewProjectionMatrix;
272
+
263
273
  }
264
274
 
265
275
  async loadTex1(device) {
@@ -0,0 +1,8 @@
1
+
2
+
3
+ export class Engine {
4
+
5
+ constructor() {
6
+
7
+ }
8
+ }
@@ -169,3 +169,45 @@ export class Position {
169
169
  }
170
170
  }
171
171
 
172
+ export class Rotation {
173
+
174
+ constructor(x, y, z) {
175
+ // Not in use for nwo this is from matrix-engine project [nameUniq]
176
+ this.nameUniq = null;
177
+ if(typeof x == 'undefined') x = 0;
178
+ if(typeof y == 'undefined') y = 0;
179
+ if(typeof z == 'undefined') z = 0;
180
+ this.x = x;
181
+ this.y = y;
182
+ this.z = z;
183
+ this.rotationSpeed = {x: 0, y: 0, z: 0}
184
+ }
185
+
186
+ getRotX () {
187
+ if (this.rotationSpeed.x == 0) {
188
+ return this.x;
189
+ } else {
190
+ this.x = this.x + this.rotationSpeed.x* 0.001;
191
+ return this.x;
192
+ }
193
+ }
194
+
195
+ getRotY () {
196
+ if (this.rotationSpeed.y == 0) {
197
+ return this.y;
198
+ } else {
199
+ this.y = this.y + this.rotationSpeed.y * 0.001;
200
+ return this.y;
201
+ }
202
+ }
203
+
204
+ getRotZ () {
205
+ if (this.rotationSpeed.z == 0) {
206
+ return this.z;
207
+ } else {
208
+ this.z = this.z + this.rotationSpeed.z* 0.001;
209
+ return this.z;
210
+ }
211
+ }
212
+
213
+ }
package/src/meWGPU.js CHANGED
@@ -1,19 +1,35 @@
1
1
  import MEBall from "./engine/ball.js";
2
2
  import MECube from './engine/cube.js';
3
- // import { mat4, vec3 } from 'wgpu-matrix';
4
- // import { createSphereMesh, SphereLayout } from './src/engine/ballsBuffer.js';
5
3
 
6
4
  export default class MatrixEngineWGPU {
7
5
 
8
6
  mainRenderBundle = [];
9
7
  rbContainer = [];
8
+ frame = () => {};
9
+
10
+ entityArgPass = {
11
+ loadOp: 'clear',
12
+ storeOp: 'store',
13
+ depthLoadOp: 'clear',
14
+ depthStoreOp: 'store'
15
+ }
16
+
17
+ constructor(options, callback) {
18
+ console.log('typeof options ', typeof options )
19
+ console.log('typeof options ', options )
20
+ if (typeof options == 'undefined' || typeof options == "function") {
21
+ this.options = {
22
+ useSingleRenderPass: true
23
+ }
24
+ callback = options;
25
+ }
26
+
27
+ this.options = options;
10
28
 
11
- constructor(callback) {
12
29
  var canvas = document.createElement('canvas')
13
30
  canvas.width = window.innerWidth;
14
31
  canvas.height = window.innerHeight;
15
32
  document.body.append(canvas)
16
-
17
33
  this.init({canvas, callback})
18
34
  }
19
35
 
@@ -34,18 +50,58 @@ export default class MatrixEngineWGPU {
34
50
  alphaMode: 'premultiplied',
35
51
  });
36
52
 
53
+ if(this.options.useSingleRenderPass == true) {
54
+ this.makeDefaultRenderPassDescriptor()
55
+ this.frame = this.frameSinglePass;
56
+ } else {
57
+ // must be
58
+ this.frame = this.framePassPerObject;
59
+ }
60
+
37
61
  this.run(callback)
38
62
  };
39
63
 
64
+ makeDefaultRenderPassDescriptor = () => {
65
+
66
+ this.depthTexture = this.device.createTexture({
67
+ size: [this.canvas.width, this.canvas.height],
68
+ format: 'depth24plus',
69
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
70
+ });
71
+
72
+ this.renderPassDescriptor = {
73
+ colorAttachments: [
74
+ {
75
+ view: undefined,
76
+ clearValue: {r: 0.0, g: 0.0, b: 0.0, a: 1.0},
77
+ loadOp: 'clear',
78
+ storeOp: 'store',
79
+ },
80
+ ],
81
+ depthStencilAttachment: {
82
+ view: this.depthTexture.createView(),
83
+ depthClearValue: 1.0,
84
+ depthLoadOp: 'clear',
85
+ depthStoreOp: 'store',
86
+ },
87
+ };
88
+ }
89
+
40
90
  addCube = (o) => {
41
91
  if(typeof o === 'undefined') {
42
92
  var o = {
43
93
  position: {x: 0, y: 0, z: -4},
44
- texturesPaths: ['./res/textures/default.png']
94
+ texturesPaths: ['./res/textures/default.png'],
95
+ rotation: {x: 0, y: 0, z: 0},
96
+ rotationSpeed: {x: 0, y: 0, z: 0},
97
+ entityArgPass: this.entityArgPass
45
98
  }
46
99
  } else {
47
100
  if(typeof o.position === 'undefined') {o.position = {x: 0, y: 0, z: -4}}
101
+ if(typeof o.rotation === 'undefined') {o.rotation = {x: 0, y: 0, z: 0}}
102
+ if(typeof o.rotationSpeed === 'undefined') {o.rotationSpeed = {x: 0, y: 0, z: 0}}
48
103
  if(typeof o.texturesPaths === 'undefined') {o.texturesPaths = ['./res/textures/default.png']}
104
+ o.entityArgPass = this.entityArgPass;
49
105
  }
50
106
  let myCube1 = new MECube(this.canvas, this.device, this.context, o)
51
107
  this.mainRenderBundle.push(myCube1);
@@ -55,11 +111,17 @@ export default class MatrixEngineWGPU {
55
111
  if(typeof o === 'undefined') {
56
112
  var o = {
57
113
  position: {x: 0, y: 0, z: -4},
58
- texturesPaths: ['./res/textures/default.png']
114
+ texturesPaths: ['./res/textures/default.png'],
115
+ rotation: {x: 0, y: 0, z: 0},
116
+ rotationSpeed: {x: 0, y: 0, z: 0},
117
+ entityArgPass: this.entityArgPass
59
118
  }
60
119
  } else {
61
120
  if(typeof o.position === 'undefined') {o.position = {x: 0, y: 0, z: -4}}
121
+ if(typeof o.rotation === 'undefined') {o.rotation = {x: 0, y: 0, z: 0}}
122
+ if(typeof o.rotationSpeed === 'undefined') {o.rotationSpeed = {x: 0, y: 0, z: 0}}
62
123
  if(typeof o.texturesPaths === 'undefined') {o.texturesPaths = ['./res/textures/default.png']}
124
+ o.entityArgPass = this.entityArgPass;
63
125
  }
64
126
  let myBall1 = new MEBall(this.canvas, this.device, this.context, o)
65
127
  this.mainRenderBundle.push(myBall1);
@@ -70,23 +132,42 @@ export default class MatrixEngineWGPU {
70
132
  setTimeout(() => {callback()}, 10)
71
133
  }
72
134
 
73
- frame = () => {
135
+ frameSinglePass = () => {
136
+ console.log('single')
74
137
  let commandEncoder = this.device.createCommandEncoder();
75
138
  this.rbContainer = [];
76
-
77
139
  let passEncoder;
78
140
 
79
141
  this.mainRenderBundle.forEach((meItem, index) => {
80
142
  meItem.draw();
81
143
  this.rbContainer.push(meItem.renderBundle)
82
- if(index == 0) passEncoder = commandEncoder.beginRenderPass(meItem.renderPassDescriptor);
144
+ // if(index == 0) passEncoder = commandEncoder.beginRenderPass(meItem.renderPassDescriptor);
83
145
  })
84
146
 
85
- // passEncoder.executeBundles([NIK.renderBundle, NIK2.renderBundle]);
147
+ this.renderPassDescriptor.colorAttachments[0].view = this.context
148
+ .getCurrentTexture()
149
+ .createView();
150
+
151
+ passEncoder = commandEncoder.beginRenderPass(this.renderPassDescriptor);
86
152
  passEncoder.executeBundles(this.rbContainer);
87
153
  passEncoder.end();
88
154
  this.device.queue.submit([commandEncoder.finish()]);
155
+ requestAnimationFrame(this.frame);
156
+ }
89
157
 
158
+ framePassPerObject = () => {
159
+ console.log('framePassPerObject')
160
+ let commandEncoder = this.device.createCommandEncoder();
161
+ this.rbContainer = [];
162
+ let passEncoder;
163
+ this.mainRenderBundle.forEach((meItem, index) => {
164
+ meItem.draw();
165
+ this.rbContainer.push(meItem.renderBundle)
166
+ passEncoder = commandEncoder.beginRenderPass(meItem.renderPassDescriptor);
167
+ passEncoder.executeBundles(this.rbContainer);
168
+ passEncoder.end();
169
+ })
170
+ this.device.queue.submit([commandEncoder.finish()]);
90
171
  requestAnimationFrame(this.frame);
91
172
  }
92
173
  }