matrix-engine-wgpu 1.0.1 → 1.0.4

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.
Files changed (46) hide show
  1. package/LICENSE +22 -17
  2. package/REFERENCE.md +48 -2
  3. package/app-worker.js +45 -0
  4. package/empty.js +12 -0
  5. package/examples/load-obj-file.js +48 -0
  6. package/examples/unlit-textures.js +27 -0
  7. package/examples.js +7 -0
  8. package/index.js +18 -5
  9. package/main.js +29 -12
  10. package/package.json +11 -2
  11. package/public/app-worker.js +47 -0
  12. package/public/app.js +2833 -279
  13. package/public/css/style.css +1 -2
  14. package/public/empty.html +25 -0
  15. package/public/empty.js +9107 -0
  16. package/public/examples.html +25 -0
  17. package/public/examples.js +9180 -0
  18. package/public/res/meshes/blender/piramyd.blend +0 -0
  19. package/public/res/meshes/blender/piramyd.blend1 +0 -0
  20. package/public/res/meshes/blender/piramyd.js +42 -0
  21. package/public/res/meshes/blender/piramyd.mtl +10 -0
  22. package/public/res/meshes/blender/piramyd.obj +18696 -0
  23. package/public/res/meshes/blender/piramyd1.js +42 -0
  24. package/public/res/meshes/blender/welcomeTextblend.blend +0 -0
  25. package/public/res/meshes/dragon/stanfordDragonData.js +5 -0
  26. package/public/res/meshes/obj/armor.obj +319 -0
  27. package/public/res/meshes/obj/armor.png +0 -0
  28. package/public/worker.html +25 -0
  29. package/readme.md +77 -36
  30. package/src/engine/ball.js +43 -23
  31. package/src/engine/cube.js +112 -87
  32. package/src/engine/engine.js +470 -0
  33. package/src/engine/final/adaptJSON1.js +53 -0
  34. package/src/engine/final/utils2.js +63 -0
  35. package/src/engine/loader-obj.js +469 -0
  36. package/src/engine/matrix-class.js +44 -1
  37. package/src/engine/matrix-mesh.js +49 -0
  38. package/src/engine/mesh-obj.js +526 -0
  39. package/src/engine/mesh.js +477 -0
  40. package/src/engine/utils.js +2 -0
  41. package/src/shaders/fragment.wgsl.js +48 -0
  42. package/src/shaders/shaders.js +4 -124
  43. package/src/shaders/vertex.wgsl.js +49 -0
  44. package/src/shaders/vertexShadow.wgsl.js +20 -0
  45. package/src/world.js +263 -0
  46. package/src/meWGPU.js +0 -92
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/app-worker.js ADDED
@@ -0,0 +1,45 @@
1
+
2
+ var canvas = document.createElement('canvas')
3
+ canvas.width = window.innerWidth;
4
+ canvas.height = window.innerHeight;
5
+ document.body.append(canvas)
6
+
7
+ // The web worker is created by passing a path to the worker's source file, which will then be
8
+ // executed on a separate thread.
9
+ const worker = new Worker('app.js');
10
+
11
+ // The primary way to communicate with the worker is to send and receive messages.
12
+ worker.addEventListener('message', (ev) => {
13
+ // The format of the message can be whatever you'd like, but it's helpful to decide on a
14
+ // consistent convention so that you can tell the message types apart as your apps grow in
15
+ // complexity. Here we establish a convention that all messages to and from the worker will
16
+ // have a `type` field that we can use to determine the content of the message.
17
+ switch (ev.data.type) {
18
+ default: {
19
+ console.error(`Unknown Message Type: ${ev.data.type}`);
20
+ }
21
+ }
22
+ });
23
+
24
+ try {
25
+ // In order for the worker to display anything on the page, an OffscreenCanvas must be used.
26
+ // Here we can create one from our normal canvas by calling transferControlToOffscreen().
27
+ // Anything drawn to the OffscreenCanvas that call returns will automatically be displayed on
28
+ // the source canvas on the page.
29
+ const offscreenCanvas = canvas.transferControlToOffscreen();
30
+ const devicePixelRatio = window.devicePixelRatio;
31
+ offscreenCanvas.width = canvas.clientWidth * devicePixelRatio;
32
+ offscreenCanvas.height = canvas.clientHeight * devicePixelRatio;
33
+
34
+ // Send a message to the worker telling it to initialize WebGPU with the OffscreenCanvas. The
35
+ // array passed as the second argument here indicates that the OffscreenCanvas is to be
36
+ // transferred to the worker, meaning this main thread will lose access to it and it will be
37
+ // fully owned by the worker.
38
+ worker.postMessage({ type: 'init', offscreenCanvas, devicePixelRatio: devicePixelRatio }, [offscreenCanvas]);
39
+ } catch (err) {
40
+ // TODO: This catch is added here because React will call init twice with the same canvas, and
41
+ // the second time will fail the transferControlToOffscreen() because it's already been
42
+ // transferred. I'd love to know how to get around that.
43
+ console.warn(err.message);
44
+ worker.terminate();
45
+ }
package/empty.js ADDED
@@ -0,0 +1,12 @@
1
+ import MatrixEngineWGPU from "./src/world.js";
2
+ import {downloadMeshes} from './src/engine/loader-obj.js';
3
+
4
+ export let application = new MatrixEngineWGPU({
5
+ useSingleRenderPass: false,
6
+ canvasSize: 'fullscreen'
7
+ }, () => {
8
+ window.app = application
9
+ // for now
10
+ window.downloadMeshes = downloadMeshes;
11
+ console.log("matrix-engine-wgpu is loaded with text/javascript.")
12
+ })
@@ -0,0 +1,48 @@
1
+ import MatrixEngineWGPU from "../src/world.js";
2
+ import {downloadMeshes} from '../src/engine/loader-obj.js';
3
+
4
+ export let application = new MatrixEngineWGPU({
5
+ useSingleRenderPass: false,
6
+ canvasSize: 'fullscreen'
7
+ }, () => {
8
+
9
+ let c = {
10
+ scale: 1,
11
+ position: {x: -2, y: 2, z: -10},
12
+ rotation: {x: 0, y: 0, z: 0},
13
+ rotationSpeed: {x: 0, y: 0, z: 0},
14
+ texturesPaths: ['./res/textures/rust.jpg']
15
+ };
16
+
17
+ let o = {
18
+ scale: 2,
19
+ position: {x: 2, y: 0, z: -10},
20
+ rotation: {x: 0, y: 45, z: 0},
21
+ rotationSpeed: {x: 0, y: 0, z: 0},
22
+ texturesPaths: ['./res/textures/rust.jpg']
23
+ };
24
+
25
+ // let mesh = adaptJSON1(stanfordDragonData)
26
+ // application.addBall(o)
27
+ // application.addCube(c)
28
+ application.addCube(o)
29
+
30
+ function onLoadObj(m) {
31
+ console.log('Loaded obj:', m.armor);
32
+ // console.log('APP2 ', jsonPiramyd);
33
+ // jsonPiramyd.vertexNormals = jsonPiramyd.normals;
34
+ // jsonPiramyd.indices = jsonPiramyd.faces;
35
+ // jsonPiramyd.textures = jsonPiramyd.uvs;
36
+ application.addMeshObj({
37
+ position: {x: 0, y: 0, z: -5},
38
+ texturesPaths: ['./res/meshes/obj/armor.png'],
39
+ name: 'Armor',
40
+ mesh: m.armor
41
+ })
42
+ }
43
+
44
+ // downloadMeshes({armor: "./res/meshes/obj/armor.obj"}, onLoadObj)
45
+ downloadMeshes({armor: "./res/meshes/blender/piramyd.obj"}, onLoadObj)
46
+ })
47
+
48
+ window.app = application
@@ -0,0 +1,27 @@
1
+ import MatrixEngineWGPU from "../src/meWGPU";
2
+
3
+ export let application = new MatrixEngineWGPU({
4
+ useSingleRenderPass: false,
5
+ canvasSize: 'fullscreen'
6
+ }, () => {
7
+
8
+ let c = {
9
+ scale: 2,
10
+ position: {x: -3, y: 0, z: -10},
11
+ rotation: {x: 0, y: 0, z: 0},
12
+ rotationSpeed: {x: 10, y: 0, z: 0},
13
+ texturesPaths: ['./res/textures/rust.jpg']
14
+ };
15
+
16
+ let o = {
17
+ scale: 2,
18
+ position: {x: 3, y: 0, z: -10},
19
+ rotation: {x: 0, y: 45, z: 0},
20
+ rotationSpeed: {x: 0, y: 10, z: 0},
21
+ texturesPaths: ['./res/textures/rust.jpg']
22
+ };
23
+ application.addBall(c)
24
+ application.addCube(o)
25
+ })
26
+
27
+ window.app = application
package/examples.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @examples
3
+ * Just import curent example/demo
4
+ */
5
+ import { application } from "./examples/load-obj-file.js";
6
+
7
+ window.app = application
package/index.js CHANGED
@@ -1,11 +1,24 @@
1
-
1
+ /**
2
+ * This file created by:
3
+ * Nikola Lukic zlatnaspirala@gmail.com mart 2024
4
+ * npm import/export
5
+ */
6
+ import {degToRad} from "wgpu-matrix/dist/2.x/utils.js";
7
+ import {downloadMeshes} from "./src/engine/loader-obj.js";
2
8
  import MatrixEngineWGPU from "./src/meWGPU.js";
3
9
 
4
- var testNpm = () => {
5
- console.log("Hi npm")
10
+ var about = () => {
11
+ console.log("Hi npm. matrix-engine for webgpu is ready...")
12
+ console.log("--------------------------------------------")
13
+ console.log("List of features : ")
14
+ console.log(" - Loading obj files with uvs")
15
+ console.log(" - Scene oriented draws")
16
+ console.log(" - position, rotation - same like matrix-engine")
6
17
  }
7
18
 
8
19
  export {
9
20
  MatrixEngineWGPU,
10
- testNpm
11
- }
21
+ downloadMeshes,
22
+ degToRad,
23
+ about
24
+ }
package/main.js CHANGED
@@ -1,20 +1,37 @@
1
- import MatrixEngineWGPU from "./src/meWGPU";
1
+ import MatrixEngineWGPU from "./src/world.js";
2
+ import {downloadMeshes} from './src/engine/loader-obj.js';
2
3
 
3
- let application = new MatrixEngineWGPU(()=> {
4
+ export let application = new MatrixEngineWGPU({
5
+ useSingleRenderPass: false,
6
+ canvasSize: 'fullscreen'
7
+ }, () => {
8
+ function onLoadObj(m) {
4
9
 
5
- let c = {
6
- position: { x: -1, y: 3, z: -10},
7
- texturesPaths: ['./res/textures/rust.jpg']
8
- };
10
+ console.log('Loaded objs:', m);
9
11
 
10
- let o = {
11
- position: { x: 5, y: 2, z: -10},
12
- texturesPaths: ['./res/textures/rust.jpg']
13
- };
12
+ application.addMeshObj({
13
+ position: {x: -3, y: 0, z: -5},
14
+ rotation: {x: 0, y: 0, z: 0},
15
+ rotationSpeed: {x: 0, y: 10, z: 0},
16
+ texturesPaths: ['./res/meshes/obj/armor.png'],
17
+ name: 'Armor',
18
+ mesh: m.armor
19
+ })
14
20
 
15
- application.addCube(c)
16
- application.addBall(o)
21
+ application.addMeshObj({
22
+ position: {x: 3, y: 0, z: -5},
23
+ rotation: {x: -90, y: 0, z: 0},
24
+ rotationSpeed: {x: 0, y: 0, z: 0},
25
+ texturesPaths: ['./res/meshes/obj/armor.png'],
26
+ name: 'MyText',
27
+ mesh: m.welcomeText
28
+ })
29
+ }
17
30
 
31
+ downloadMeshes({
32
+ welcomeText: "./res/meshes/blender/piramyd.obj",
33
+ armor: "./res/meshes/obj/armor.obj"
34
+ }, onLoadObj)
18
35
 
19
36
  })
20
37
 
package/package.json CHANGED
@@ -1,17 +1,26 @@
1
1
  {
2
2
  "name": "matrix-engine-wgpu",
3
- "version": "1.0.1",
3
+ "version": "1.0.4",
4
4
  "description": "webGPU powered pwa application.Crazy fast rendering.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "main": "watchify main.js -p [esmify --noImplicitAny] -o public/app.js"
7
+ "main-worker": "watchify app-worker.js -p [esmify --noImplicitAny] -o public/app-worker.js",
8
+ "examples": "watchify examples.js -p [esmify --noImplicitAny] -o public/examples.js",
9
+ "main": "watchify main.js -p [esmify --noImplicitAny] -o public/app.js",
10
+ "build-empty": "watchify empty.js -p [esmify --noImplicitAny] -o public/empty.js",
11
+ "build-all": "npm run main-worker | npm run examples | npm run main | npm run build-empty"
8
12
  },
9
13
  "keywords": [
10
14
  "webGPU",
15
+ "webGPU-scene",
16
+ "webGPU-engine",
11
17
  "matrix",
12
18
  "matrix-engine",
13
19
  "matrix-engine-webGPU",
14
20
  "matrix-calculation",
21
+ "modelView",
22
+ "modelViewProjectionMatrix",
23
+ "ProjectionMatrix",
15
24
  "render",
16
25
  "wgpu",
17
26
  "zlatnaspirala",
@@ -0,0 +1,47 @@
1
+ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2
+
3
+ var canvas = document.createElement('canvas')
4
+ canvas.width = window.innerWidth;
5
+ canvas.height = window.innerHeight;
6
+ document.body.append(canvas)
7
+
8
+ // The web worker is created by passing a path to the worker's source file, which will then be
9
+ // executed on a separate thread.
10
+ const worker = new Worker('app.js');
11
+
12
+ // The primary way to communicate with the worker is to send and receive messages.
13
+ worker.addEventListener('message', (ev) => {
14
+ // The format of the message can be whatever you'd like, but it's helpful to decide on a
15
+ // consistent convention so that you can tell the message types apart as your apps grow in
16
+ // complexity. Here we establish a convention that all messages to and from the worker will
17
+ // have a `type` field that we can use to determine the content of the message.
18
+ switch (ev.data.type) {
19
+ default: {
20
+ console.error(`Unknown Message Type: ${ev.data.type}`);
21
+ }
22
+ }
23
+ });
24
+
25
+ try {
26
+ // In order for the worker to display anything on the page, an OffscreenCanvas must be used.
27
+ // Here we can create one from our normal canvas by calling transferControlToOffscreen().
28
+ // Anything drawn to the OffscreenCanvas that call returns will automatically be displayed on
29
+ // the source canvas on the page.
30
+ const offscreenCanvas = canvas.transferControlToOffscreen();
31
+ const devicePixelRatio = window.devicePixelRatio;
32
+ offscreenCanvas.width = canvas.clientWidth * devicePixelRatio;
33
+ offscreenCanvas.height = canvas.clientHeight * devicePixelRatio;
34
+
35
+ // Send a message to the worker telling it to initialize WebGPU with the OffscreenCanvas. The
36
+ // array passed as the second argument here indicates that the OffscreenCanvas is to be
37
+ // transferred to the worker, meaning this main thread will lose access to it and it will be
38
+ // fully owned by the worker.
39
+ worker.postMessage({ type: 'init', offscreenCanvas, devicePixelRatio: devicePixelRatio }, [offscreenCanvas]);
40
+ } catch (err) {
41
+ // TODO: This catch is added here because React will call init twice with the same canvas, and
42
+ // the second time will fail the transferControlToOffscreen() because it's already been
43
+ // transferred. I'd love to know how to get around that.
44
+ console.warn(err.message);
45
+ worker.terminate();
46
+ }
47
+ },{}]},{},[1]);