From a0faf0456f63580c5b331e3bc287f445fff827ce Mon Sep 17 00:00:00 2001 From: Zach Date: Mon, 29 Apr 2024 13:08:16 -0400 Subject: [PATCH] Build JS files to make it work with GitHub Pages --- examples/cornell-box-raytraced/index.d.ts | 1 + examples/cornell-box-raytraced/index.html | 2 +- examples/cornell-box-raytraced/index.js | 66 +++ examples/cornell-box-raytraced/index.js.map | 1 + examples/cornell-box/index.d.ts | 1 + examples/cornell-box/index.html | 2 +- examples/cornell-box/index.js | 61 +++ examples/cornell-box/index.js.map | 1 + examples/cornell-box/index.ts | 7 +- examples/hello-eclipse/index.d.ts | 1 + examples/hello-eclipse/index.js | 47 ++ examples/hello-eclipse/index.js.map | 1 + examples/sphere/index.d.ts | 1 + examples/sphere/index.js | 40 ++ examples/sphere/index.js.map | 1 + src/cameras/Camera.d.ts | 6 + src/cameras/Camera.js | 2 + src/cameras/Camera.js.map | 1 + src/cameras/PerspectiveCamera.d.ts | 22 + src/cameras/PerspectiveCamera.js | 46 ++ src/cameras/PerspectiveCamera.js.map | 1 + src/cameras/exports.d.ts | 1 + src/cameras/exports.js | 2 + src/cameras/exports.js.map | 1 + src/constants.d.ts | 2 + src/constants.js | 4 + src/constants.js.map | 1 + src/geometries/Box.d.ts | 8 + src/geometries/Box.js | 91 ++++ src/geometries/Box.js.map | 1 + src/geometries/Geometry.d.ts | 17 + src/geometries/Geometry.js | 47 ++ src/geometries/Geometry.js.map | 1 + src/geometries/Plane.d.ts | 7 + src/geometries/Plane.js | 49 ++ src/geometries/Plane.js.map | 1 + src/geometries/Sphere.d.ts | 8 + src/geometries/Sphere.js | 65 +++ src/geometries/Sphere.js.map | 1 + src/geometries/exports.d.ts | 4 + src/geometries/exports.js | 5 + src/geometries/exports.js.map | 1 + src/index.d.ts | 6 + src/index.js | 7 + src/index.js.map | 1 + src/lights/AmbientLight.d.ts | 7 + src/lights/AmbientLight.js | 11 + src/lights/AmbientLight.js.map | 1 + src/lights/Light.d.ts | 9 + src/lights/Light.js | 11 + src/lights/Light.js.map | 1 + src/lights/PointLight.d.ts | 6 + src/lights/PointLight.js | 11 + src/lights/PointLight.js.map | 1 + src/lights/constants.d.ts | 3 + src/lights/constants.js | 4 + src/lights/constants.js.map | 1 + src/lights/exports.d.ts | 3 + src/lights/exports.js | 4 + src/lights/exports.js.map | 1 + src/materials/BlinnPhong.d.ts | 10 + src/materials/BlinnPhong.js | 14 + src/materials/BlinnPhong.js.map | 1 + src/materials/Lambert.d.ts | 8 + src/materials/Lambert.js | 11 + src/materials/Lambert.js.map | 1 + src/materials/Material.d.ts | 4 + src/materials/Material.js | 7 + src/materials/Material.js.map | 1 + src/materials/Metal.d.ts | 9 + src/materials/Metal.js | 12 + src/materials/Metal.js.map | 1 + src/materials/SolidColor.d.ts | 8 + src/materials/SolidColor.js | 12 + src/materials/SolidColor.js.map | 1 + src/materials/constants.d.ts | 5 + src/materials/constants.js | 6 + src/materials/constants.js.map | 1 + src/materials/exports.d.ts | 6 + src/materials/exports.js | 7 + src/materials/exports.js.map | 1 + src/primitives/Group.d.ts | 12 + src/primitives/Group.js | 21 + src/primitives/Group.js.map | 1 + src/primitives/Mesh.d.ts | 9 + src/primitives/Mesh.js | 10 + src/primitives/Mesh.js.map | 1 + src/primitives/Scene.d.ts | 14 + src/primitives/Scene.js | 38 ++ src/primitives/Scene.js.map | 1 + src/primitives/exports.d.ts | 3 + src/primitives/exports.js | 4 + src/primitives/exports.js.map | 1 + src/renderers/Rasterizer.d.ts | 30 ++ src/renderers/Rasterizer.js | 361 ++++++++++++++ src/renderers/Rasterizer.js.map | 1 + src/renderers/Rasterizer.ts | 4 +- src/renderers/Raytracer.d.ts | 40 ++ src/renderers/Raytracer.js | 505 ++++++++++++++++++++ src/renderers/Raytracer.js.map | 1 + src/renderers/Raytracer.ts | 11 +- src/renderers/Renderer.d.ts | 6 + src/renderers/Renderer.js | 2 + src/renderers/Renderer.js.map | 1 + src/renderers/constants.d.ts | 3 + src/renderers/constants.js | 39 ++ src/renderers/constants.js.map | 1 + src/renderers/exports.d.ts | 2 + src/renderers/exports.js | 3 + src/renderers/exports.js.map | 1 + tsconfig.json | 1 + 111 files changed, 1955 insertions(+), 14 deletions(-) create mode 100644 examples/cornell-box-raytraced/index.d.ts create mode 100644 examples/cornell-box-raytraced/index.js create mode 100644 examples/cornell-box-raytraced/index.js.map create mode 100644 examples/cornell-box/index.d.ts create mode 100644 examples/cornell-box/index.js create mode 100644 examples/cornell-box/index.js.map create mode 100644 examples/hello-eclipse/index.d.ts create mode 100644 examples/hello-eclipse/index.js create mode 100644 examples/hello-eclipse/index.js.map create mode 100644 examples/sphere/index.d.ts create mode 100644 examples/sphere/index.js create mode 100644 examples/sphere/index.js.map create mode 100644 src/cameras/Camera.d.ts create mode 100644 src/cameras/Camera.js create mode 100644 src/cameras/Camera.js.map create mode 100644 src/cameras/PerspectiveCamera.d.ts create mode 100644 src/cameras/PerspectiveCamera.js create mode 100644 src/cameras/PerspectiveCamera.js.map create mode 100644 src/cameras/exports.d.ts create mode 100644 src/cameras/exports.js create mode 100644 src/cameras/exports.js.map create mode 100644 src/constants.d.ts create mode 100644 src/constants.js create mode 100644 src/constants.js.map create mode 100644 src/geometries/Box.d.ts create mode 100644 src/geometries/Box.js create mode 100644 src/geometries/Box.js.map create mode 100644 src/geometries/Geometry.d.ts create mode 100644 src/geometries/Geometry.js create mode 100644 src/geometries/Geometry.js.map create mode 100644 src/geometries/Plane.d.ts create mode 100644 src/geometries/Plane.js create mode 100644 src/geometries/Plane.js.map create mode 100644 src/geometries/Sphere.d.ts create mode 100644 src/geometries/Sphere.js create mode 100644 src/geometries/Sphere.js.map create mode 100644 src/geometries/exports.d.ts create mode 100644 src/geometries/exports.js create mode 100644 src/geometries/exports.js.map create mode 100644 src/index.d.ts create mode 100644 src/index.js create mode 100644 src/index.js.map create mode 100644 src/lights/AmbientLight.d.ts create mode 100644 src/lights/AmbientLight.js create mode 100644 src/lights/AmbientLight.js.map create mode 100644 src/lights/Light.d.ts create mode 100644 src/lights/Light.js create mode 100644 src/lights/Light.js.map create mode 100644 src/lights/PointLight.d.ts create mode 100644 src/lights/PointLight.js create mode 100644 src/lights/PointLight.js.map create mode 100644 src/lights/constants.d.ts create mode 100644 src/lights/constants.js create mode 100644 src/lights/constants.js.map create mode 100644 src/lights/exports.d.ts create mode 100644 src/lights/exports.js create mode 100644 src/lights/exports.js.map create mode 100644 src/materials/BlinnPhong.d.ts create mode 100644 src/materials/BlinnPhong.js create mode 100644 src/materials/BlinnPhong.js.map create mode 100644 src/materials/Lambert.d.ts create mode 100644 src/materials/Lambert.js create mode 100644 src/materials/Lambert.js.map create mode 100644 src/materials/Material.d.ts create mode 100644 src/materials/Material.js create mode 100644 src/materials/Material.js.map create mode 100644 src/materials/Metal.d.ts create mode 100644 src/materials/Metal.js create mode 100644 src/materials/Metal.js.map create mode 100644 src/materials/SolidColor.d.ts create mode 100644 src/materials/SolidColor.js create mode 100644 src/materials/SolidColor.js.map create mode 100644 src/materials/constants.d.ts create mode 100644 src/materials/constants.js create mode 100644 src/materials/constants.js.map create mode 100644 src/materials/exports.d.ts create mode 100644 src/materials/exports.js create mode 100644 src/materials/exports.js.map create mode 100644 src/primitives/Group.d.ts create mode 100644 src/primitives/Group.js create mode 100644 src/primitives/Group.js.map create mode 100644 src/primitives/Mesh.d.ts create mode 100644 src/primitives/Mesh.js create mode 100644 src/primitives/Mesh.js.map create mode 100644 src/primitives/Scene.d.ts create mode 100644 src/primitives/Scene.js create mode 100644 src/primitives/Scene.js.map create mode 100644 src/primitives/exports.d.ts create mode 100644 src/primitives/exports.js create mode 100644 src/primitives/exports.js.map create mode 100644 src/renderers/Rasterizer.d.ts create mode 100644 src/renderers/Rasterizer.js create mode 100644 src/renderers/Rasterizer.js.map create mode 100644 src/renderers/Raytracer.d.ts create mode 100644 src/renderers/Raytracer.js create mode 100644 src/renderers/Raytracer.js.map create mode 100644 src/renderers/Renderer.d.ts create mode 100644 src/renderers/Renderer.js create mode 100644 src/renderers/Renderer.js.map create mode 100644 src/renderers/constants.d.ts create mode 100644 src/renderers/constants.js create mode 100644 src/renderers/constants.js.map create mode 100644 src/renderers/exports.d.ts create mode 100644 src/renderers/exports.js create mode 100644 src/renderers/exports.js.map diff --git a/examples/cornell-box-raytraced/index.d.ts b/examples/cornell-box-raytraced/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/examples/cornell-box-raytraced/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/examples/cornell-box-raytraced/index.html b/examples/cornell-box-raytraced/index.html index d5cd2f3..c9546d3 100644 --- a/examples/cornell-box-raytraced/index.html +++ b/examples/cornell-box-raytraced/index.html @@ -21,6 +21,6 @@ - + diff --git a/examples/cornell-box-raytraced/index.js b/examples/cornell-box-raytraced/index.js new file mode 100644 index 0000000..fda40f2 --- /dev/null +++ b/examples/cornell-box-raytraced/index.js @@ -0,0 +1,66 @@ +import { Box, Mesh, PerspectiveCamera, Scene, SolidColor, Raytracer, AmbientLight, PointLight, Plane, Metal, Lambert, } from '../../src/index.js'; +import { quat, vec3 } from 'wgpu-matrix'; +const canvas = document.querySelector('canvas'); +if (canvas === null) { + throw new Error('Canvas does not exist'); +} +const renderer = new Raytracer(canvas); +renderer.init().then(() => { + const plane = new Plane(1, 1); + const c = 180 / 255; + const white = [c, c, c]; + const leftWall = new Mesh(plane, new Lambert([c, 0, 0])); + vec3.set(-0.5, 0, 0, leftWall.localPosition); + quat.fromEuler(0, Math.PI / 2, 0, 'xyz', leftWall.localQuaternion); + const rightWall = new Mesh(plane, new Lambert([0, c, 0])); + vec3.set(0.5, 0, 0, rightWall.localPosition); + quat.fromEuler(0, -Math.PI / 2, 0, 'xyz', rightWall.localQuaternion); + const backWall = new Mesh(plane, new Lambert(white)); + vec3.set(0, 0, -0.5, backWall.localPosition); + // quat.fromEuler(0, 0, 0, 'xyz', backWall.localQuaternion); + const ground = new Mesh(plane, new Lambert(white)); + vec3.set(0, -0.5, 0, ground.localPosition); + quat.fromEuler(-Math.PI / 2, 0, 0, 'xyz', ground.localQuaternion); + const ceiling = new Mesh(plane, new Lambert(white)); + vec3.set(0, 0.5, 0, ceiling.localPosition); + quat.fromEuler(Math.PI / 2, 0, 0, 'xyz', ceiling.localQuaternion); + const box = new Box(0.3, 0.3, 0.3); + const tallBox = new Mesh(box, new Metal(white, 0)); + vec3.set(-0.25, -0.2, -0.25, tallBox.localPosition); + vec3.set(1, 2, 1, tallBox.localScale); + quat.fromEuler(0, Math.PI / 10, 0, 'xyz', tallBox.localQuaternion); + const shortBox = new Mesh(box, new Lambert(white)); + vec3.set(0.2, -0.35, 0.25, shortBox.localPosition); + quat.fromEuler(0, -Math.PI / 10, 0, 'xyz', shortBox.localQuaternion); + const ambient = new AmbientLight([1, 1, 1]); + const light = new PointLight(); + vec3.set(0, 0.5, 0, light.localPosition); + const lightMesh = new Mesh(new Plane(0.2, 0.2), new SolidColor()); + vec3.set(0, 0.5 - 0.001, 0, lightMesh.localPosition); + quat.fromEuler(Math.PI / 2, 0, 0, 'xyz', lightMesh.localQuaternion); + const scene = new Scene(); + const camera = new PerspectiveCamera(Math.PI / 4, canvas.width / canvas.height); + vec3.set(0, 0, 2, camera.localPosition); + scene.add(leftWall, rightWall, backWall, ground, ceiling, tallBox, shortBox, ambient, light, lightMesh); + // Canvas resize + let i = 0; + const resizeObserver = new ResizeObserver(entries => { + i = 0; + entries.forEach(entry => { + const canvas = entry.target; + const width = entry.contentBoxSize[0].inlineSize; + const height = entry.contentBoxSize[0].blockSize; + canvas.width = width; + canvas.height = height; + renderer.updateCanvas(); + camera.aspectRatio = canvas.width / canvas.height; + }); + }); + resizeObserver.observe(canvas); + function frame() { + renderer.render(scene, camera, i++); + window.requestAnimationFrame(frame); + } + window.requestAnimationFrame(frame); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/examples/cornell-box-raytraced/index.js.map b/examples/cornell-box-raytraced/index.js.map new file mode 100644 index 0000000..ef20498 --- /dev/null +++ b/examples/cornell-box-raytraced/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/cornell-box/index.d.ts b/examples/cornell-box/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/examples/cornell-box/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/examples/cornell-box/index.html b/examples/cornell-box/index.html index 16371d6..740062b 100644 --- a/examples/cornell-box/index.html +++ b/examples/cornell-box/index.html @@ -21,6 +21,6 @@ - + diff --git a/examples/cornell-box/index.js b/examples/cornell-box/index.js new file mode 100644 index 0000000..2544173 --- /dev/null +++ b/examples/cornell-box/index.js @@ -0,0 +1,61 @@ +import { Box, Mesh, PerspectiveCamera, Scene, SolidColor, BlinnPhong, AmbientLight, PointLight, Plane, Metal, Rasterizer, } from '../../src/index.js'; +import { quat, vec3 } from 'wgpu-matrix'; +const canvas = document.querySelector('canvas'); +if (canvas === null) { + throw new Error('Canvas does not exist'); +} +const renderer = new Rasterizer(canvas); +renderer.init().then(() => { + const plane = new Plane(1, 1); + const leftWall = new Mesh(plane, new BlinnPhong([180 / 255, 0, 0])); + vec3.set(-0.5, 0, 0, leftWall.localPosition); + quat.fromEuler(0, Math.PI / 2, 0, 'xyz', leftWall.localQuaternion); + const rightWall = new Mesh(plane, new BlinnPhong([0, 180 / 255, 0])); + vec3.set(0.5, 0, 0, rightWall.localPosition); + quat.fromEuler(0, -Math.PI / 2, 0, 'xyz', rightWall.localQuaternion); + const backWall = new Mesh(plane, new BlinnPhong([180 / 255, 180 / 255, 180 / 255])); + vec3.set(0, 0, -0.5, backWall.localPosition); + // quat.fromEuler(0, 0, 0, 'xyz', backWall.localQuaternion); + const ground = new Mesh(plane, new BlinnPhong([180 / 255, 180 / 255, 180 / 255])); + vec3.set(0, -0.5, 0, ground.localPosition); + quat.fromEuler(-Math.PI / 2, 0, 0, 'xyz', ground.localQuaternion); + const ceiling = new Mesh(plane, new BlinnPhong([180 / 255, 180 / 255, 180 / 255])); + vec3.set(0, 0.5, 0, ceiling.localPosition); + quat.fromEuler(Math.PI / 2, 0, 0, 'xyz', ceiling.localQuaternion); + const box = new Box(0.3, 0.3, 0.3); + const tallBox = new Mesh(box, new Metal([1, 1, 1], 0)); + vec3.set(-0.25, -0.2, -0.25, tallBox.localPosition); + vec3.set(1, 2, 1, tallBox.localScale); + quat.fromEuler(0, Math.PI / 10, 0, 'xyz', tallBox.localQuaternion); + const shortBox = new Mesh(box, new BlinnPhong([180 / 255, 180 / 255, 180 / 255])); + vec3.set(0.2, -0.35, 0.25, shortBox.localPosition); + quat.fromEuler(0, -Math.PI / 10, 0, 'xyz', shortBox.localQuaternion); + const ambient = new AmbientLight([1, 1, 1], 0.1); + const light = new PointLight(); + vec3.set(0, 0.5, 0, light.localPosition); + const lightMesh = new Mesh(new Plane(0.2, 0.2), new SolidColor()); + vec3.set(0, 0.5 - 0.001, 0, lightMesh.localPosition); + quat.fromEuler(Math.PI / 2, 0, 0, 'xyz', lightMesh.localQuaternion); + const scene = new Scene(); + const camera = new PerspectiveCamera(Math.PI / 4, canvas.width / canvas.height); + vec3.set(0, 0, 2, camera.localPosition); + scene.add(leftWall, rightWall, backWall, ground, ceiling, tallBox, shortBox, ambient, light, lightMesh); + const resizeObserver = new ResizeObserver(entries => { + entries.forEach(entry => { + const canvas = entry.target; + const width = entry.contentBoxSize[0].inlineSize; + const height = entry.contentBoxSize[0].blockSize; + canvas.width = width; + canvas.height = height; + camera.aspectRatio = canvas.width / canvas.height; + }); + }); + resizeObserver.observe(canvas); + // renderer.render(scene, camera, 20); + function frame() { + renderer.render(scene, camera); + window.requestAnimationFrame(frame); + } + window.requestAnimationFrame(frame); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/examples/cornell-box/index.js.map b/examples/cornell-box/index.js.map new file mode 100644 index 0000000..10ac418 --- /dev/null +++ b/examples/cornell-box/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/cornell-box/index.ts b/examples/cornell-box/index.ts index 1875440..642bba3 100644 --- a/examples/cornell-box/index.ts +++ b/examples/cornell-box/index.ts @@ -93,12 +93,7 @@ renderer.init().then(() => { lightMesh ); - // Canvas resize - let i = 0; - const resizeObserver = new ResizeObserver(entries => { - i = 0; - entries.forEach(entry => { const canvas = entry.target as HTMLCanvasElement; const width = entry.contentBoxSize[0].inlineSize; @@ -116,7 +111,7 @@ renderer.init().then(() => { // renderer.render(scene, camera, 20); function frame() { - renderer.render(scene, camera, i++); + renderer.render(scene, camera); window.requestAnimationFrame(frame); } diff --git a/examples/hello-eclipse/index.d.ts b/examples/hello-eclipse/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/examples/hello-eclipse/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/examples/hello-eclipse/index.js b/examples/hello-eclipse/index.js new file mode 100644 index 0000000..8c755f3 --- /dev/null +++ b/examples/hello-eclipse/index.js @@ -0,0 +1,47 @@ +import { Box, Mesh, PerspectiveCamera, Scene, SolidColor, BlinnPhong, Rasterizer, AmbientLight, PointLight, } from '../../src/index.js'; +import { quat, vec3 } from 'wgpu-matrix'; +const canvas = document.querySelector('canvas'); +if (canvas === null) { + throw new Error('Canvas does not exist'); +} +const renderer = new Rasterizer(canvas); +renderer.init().then(() => { + const box = new Box(1, 1, 1); + const scene = new Scene(); + const camera = new PerspectiveCamera(Math.PI / 4, canvas.width / canvas.height); + vec3.set(0, 0, 4, camera.localPosition); + const pointLight = new PointLight(); + const lightBulb = new Mesh(new Box(0.2, 0.2, 0.2), new SolidColor()); + // Generate random cubes + for (let i = 0; i < 50; i++) { + const cube = new Mesh(box, new BlinnPhong(vec3.random(), vec3.random(), Math.random() * 100)); + vec3.copy(vec3.mulScalar(vec3.random(), 4), cube.localPosition); + const randomAngle = vec3.random(); + quat.fromEuler(...randomAngle, 'xyz', cube.localQuaternion); + scene.add(cube); + } + scene.add(new AmbientLight([1, 1, 1], 0.1), pointLight, lightBulb); + // Canvas resize + const resizeObserver = new ResizeObserver(entries => { + entries.forEach(entry => { + const canvas = entry.target; + const width = entry.contentBoxSize[0].inlineSize; + const height = entry.contentBoxSize[0].blockSize; + canvas.width = width; + canvas.height = height; + camera.aspectRatio = canvas.width / canvas.height; + }); + }); + resizeObserver.observe(canvas); + let i = 0; + function frame() { + renderer.render(scene, camera); + i++; + vec3.set(Math.sin(i / 100), 0, Math.cos(i / 100), pointLight.localPosition); + vec3.set(Math.sin(i / 100), 0, Math.cos(i / 100), lightBulb.localPosition); + pointLight.intensity = Math.sin(i / 75) / 2 + 0.5; + window.requestAnimationFrame(frame); + } + window.requestAnimationFrame(frame); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/examples/hello-eclipse/index.js.map b/examples/hello-eclipse/index.js.map new file mode 100644 index 0000000..71fa024 --- /dev/null +++ b/examples/hello-eclipse/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/sphere/index.d.ts b/examples/sphere/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/examples/sphere/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/examples/sphere/index.js b/examples/sphere/index.js new file mode 100644 index 0000000..aaf826c --- /dev/null +++ b/examples/sphere/index.js @@ -0,0 +1,40 @@ +import { Sphere, Mesh, PerspectiveCamera, Scene, SolidColor, BlinnPhong, Rasterizer, AmbientLight, PointLight, } from '../../src/index.js'; +import { quat, vec3 } from 'wgpu-matrix'; +const canvas = document.querySelector('canvas'); +if (canvas === null) { + throw new Error('Canvas does not exist'); +} +const renderer = new Rasterizer(canvas); +renderer.init().then(() => { + const sphere = new Mesh(new Sphere(1), new BlinnPhong([1, 0.5, 0.31])); + const lightBulb = new Mesh(new Sphere(0.2), new SolidColor([1, 1, 1])); + const scene = new Scene(); + const camera = new PerspectiveCamera(Math.PI / 4, canvas.width / canvas.height); + vec3.set(0, 0, 4, camera.localPosition); + const pointLight = new PointLight(); + scene.add(new AmbientLight([1, 1, 1], 0.1), pointLight, sphere, lightBulb); + // Canvas resize + const resizeObserver = new ResizeObserver(entries => { + entries.forEach(entry => { + const canvas = entry.target; + const width = entry.contentBoxSize[0].inlineSize; + const height = entry.contentBoxSize[0].blockSize; + canvas.width = width; + canvas.height = height; + camera.aspectRatio = canvas.width / canvas.height; + }); + }); + resizeObserver.observe(canvas); + let i = 0; + function frame() { + renderer.render(scene, camera); + i++; + vec3.set(Math.sin(i / 100) * 2, 0, Math.cos(i / 100) * 2, pointLight.localPosition); + vec3.set(Math.sin(i / 100) * 2, 0, Math.cos(i / 100) * 2, lightBulb.localPosition); + pointLight.intensity = Math.sin(i / 75) / 2 + 0.5; + quat.fromEuler(i / 100, 0, i / 100, 'xyz', sphere.localQuaternion); + window.requestAnimationFrame(frame); + } + window.requestAnimationFrame(frame); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/examples/sphere/index.js.map b/examples/sphere/index.js.map new file mode 100644 index 0000000..699324b --- /dev/null +++ b/examples/sphere/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/cameras/Camera.d.ts b/src/cameras/Camera.d.ts new file mode 100644 index 0000000..2e2b122 --- /dev/null +++ b/src/cameras/Camera.d.ts @@ -0,0 +1,6 @@ +import { mat4 } from 'wgpu-matrix'; +interface Camera { + projectionMatrix: mat4; + projectionMatrixInverse: mat4; +} +export { Camera }; diff --git a/src/cameras/Camera.js b/src/cameras/Camera.js new file mode 100644 index 0000000..092a7e7 --- /dev/null +++ b/src/cameras/Camera.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=Camera.js.map \ No newline at end of file diff --git a/src/cameras/Camera.js.map b/src/cameras/Camera.js.map new file mode 100644 index 0000000..cbc14bd --- /dev/null +++ b/src/cameras/Camera.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Camera.js","sourceRoot":"","sources":["Camera.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/src/cameras/PerspectiveCamera.d.ts b/src/cameras/PerspectiveCamera.d.ts new file mode 100644 index 0000000..87b7b9e --- /dev/null +++ b/src/cameras/PerspectiveCamera.d.ts @@ -0,0 +1,22 @@ +import { Group } from '../primitives/Group.js'; +import { Camera } from './Camera.js'; +import { mat4 } from 'wgpu-matrix'; +declare class PerspectiveCamera extends Group implements Camera { + projectionMatrix: mat4; + projectionMatrixInverse: mat4; + private _verticalFovRadians; + private _aspectRatio; + private _near; + private _far; + constructor(verticalFovRadians?: number, aspectRatio?: number, near?: number, far?: number); + get verticalFovRadians(): number; + set verticalFovRadians(newVerticalFovRadians: number); + get aspectRatio(): number; + set aspectRatio(newAspectRatio: number); + get near(): number; + set near(newNear: number); + get far(): number; + set far(newFar: number); + private updateProjectMatrix; +} +export { PerspectiveCamera }; diff --git a/src/cameras/PerspectiveCamera.js b/src/cameras/PerspectiveCamera.js new file mode 100644 index 0000000..fa49f9d --- /dev/null +++ b/src/cameras/PerspectiveCamera.js @@ -0,0 +1,46 @@ +import { Group } from '../primitives/Group.js'; +import { mat4 } from 'wgpu-matrix'; +class PerspectiveCamera extends Group { + constructor(verticalFovRadians, aspectRatio, near, far) { + super(); + this._verticalFovRadians = verticalFovRadians !== null && verticalFovRadians !== void 0 ? verticalFovRadians : Math.PI / 4; + this._aspectRatio = aspectRatio !== null && aspectRatio !== void 0 ? aspectRatio : 1; + this._near = near !== null && near !== void 0 ? near : 0.1; + this._far = far !== null && far !== void 0 ? far : 1000; + this.updateProjectMatrix(); + } + get verticalFovRadians() { + return this._verticalFovRadians; + } + set verticalFovRadians(newVerticalFovRadians) { + this._verticalFovRadians = newVerticalFovRadians; + this.updateProjectMatrix(); + } + get aspectRatio() { + return this._aspectRatio; + } + set aspectRatio(newAspectRatio) { + this._aspectRatio = newAspectRatio; + this.updateProjectMatrix(); + } + get near() { + return this._near; + } + set near(newNear) { + this._near = newNear; + this.updateProjectMatrix(); + } + get far() { + return this._far; + } + set far(newFar) { + this._far = newFar; + this.updateProjectMatrix(); + } + updateProjectMatrix() { + this.projectionMatrix = mat4.perspective(this._verticalFovRadians, this._aspectRatio, this._near, this._far); + this.projectionMatrixInverse = mat4.invert(this.projectionMatrix); + } +} +export { PerspectiveCamera }; +//# sourceMappingURL=PerspectiveCamera.js.map \ No newline at end of file diff --git a/src/cameras/PerspectiveCamera.js.map b/src/cameras/PerspectiveCamera.js.map new file mode 100644 index 0000000..4d406ac --- /dev/null +++ b/src/cameras/PerspectiveCamera.js.map @@ -0,0 +1 @@ +{"version":3,"file":"PerspectiveCamera.js","sourceRoot":"","sources":["PerspectiveCamera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,wBAAwB,CAAC;AAE7C,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAC;AAEjC,MAAM,iBAAkB,SAAQ,KAAK;IASnC,YACE,kBAA2B,EAC3B,WAAoB,EACpB,IAAa,EACb,GAAY;QAEZ,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,mBAAmB,GAAG,kBAAkB,aAAlB,kBAAkB,cAAlB,kBAAkB,GAAI,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAY,GAAG,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,GAAG,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,GAAG,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,IAAI,CAAC;QAExB,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,kBAAkB;QACpB,OAAO,IAAI,CAAC,mBAAmB,CAAC;IAClC,CAAC;IAED,IAAI,kBAAkB,CAAC,qBAA6B;QAClD,IAAI,CAAC,mBAAmB,GAAG,qBAAqB,CAAC;QACjD,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,WAAW,CAAC,cAAsB;QACpC,IAAI,CAAC,YAAY,GAAG,cAAc,CAAC;QACnC,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,IAAI,CAAC,OAAe;QACtB,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;QACrB,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,GAAG,CAAC,MAAc;QACpB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;QACnB,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,WAAW,CACtC,IAAI,CAAC,mBAAmB,EACxB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,IAAI,CACV,CAAC;QAEF,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACpE,CAAC;CACF;AAED,OAAO,EAAC,iBAAiB,EAAC,CAAC"} \ No newline at end of file diff --git a/src/cameras/exports.d.ts b/src/cameras/exports.d.ts new file mode 100644 index 0000000..a0569b9 --- /dev/null +++ b/src/cameras/exports.d.ts @@ -0,0 +1 @@ +export * from './PerspectiveCamera.js'; diff --git a/src/cameras/exports.js b/src/cameras/exports.js new file mode 100644 index 0000000..323ed89 --- /dev/null +++ b/src/cameras/exports.js @@ -0,0 +1,2 @@ +export * from './PerspectiveCamera.js'; +//# sourceMappingURL=exports.js.map \ No newline at end of file diff --git a/src/cameras/exports.js.map b/src/cameras/exports.js.map new file mode 100644 index 0000000..f130920 --- /dev/null +++ b/src/cameras/exports.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exports.js","sourceRoot":"","sources":["exports.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"} \ No newline at end of file diff --git a/src/constants.d.ts b/src/constants.d.ts new file mode 100644 index 0000000..56eb3ed --- /dev/null +++ b/src/constants.d.ts @@ -0,0 +1,2 @@ +declare const UP: any; +export { UP }; diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..0a451db --- /dev/null +++ b/src/constants.js @@ -0,0 +1,4 @@ +import { vec3 } from 'wgpu-matrix'; +const UP = vec3.create(0, 1, 0); +export { UP }; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/src/constants.js.map b/src/constants.js.map new file mode 100644 index 0000000..489ea97 --- /dev/null +++ b/src/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAC;AAEjC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEhC,OAAO,EAAC,EAAE,EAAC,CAAC"} \ No newline at end of file diff --git a/src/geometries/Box.d.ts b/src/geometries/Box.d.ts new file mode 100644 index 0000000..2e91951 --- /dev/null +++ b/src/geometries/Box.d.ts @@ -0,0 +1,8 @@ +import { Geometry } from './Geometry.js'; +declare class Box extends Geometry { + readonly width: number; + readonly height: number; + readonly depth: number; + constructor(width: number, height: number, depth: number); +} +export { Box }; diff --git a/src/geometries/Box.js b/src/geometries/Box.js new file mode 100644 index 0000000..adf61d1 --- /dev/null +++ b/src/geometries/Box.js @@ -0,0 +1,91 @@ +import { Geometry } from './Geometry.js'; +class Box extends Geometry { + constructor(width, height, depth) { + super(); + this.width = width; + this.height = height; + this.depth = depth; + const halfWidth = width / 2; + const halfHeight = height / 2; + const halfDepth = depth / 2; + // v2-------v3 + // /| /| + // v1-------v0 | +Y + // | | | | | + // |v6------|v7 |---+X + // |/ |/ / + // v5-------v4 +Z + // For correct shading of a cube, each vertex needs to be duplicated twice, + // resulting in 3 copies. Each copy will have its own vertex normal pointing + // along different axes (in the order of X, Y, and then Z). + // prettier-ignore + const vertices = new Float32Array([ + // v0 + halfWidth, halfHeight, halfDepth, // 0 X face + halfWidth, halfHeight, halfDepth, // 1 Y face + halfWidth, halfHeight, halfDepth, // 2 Z face + // v1 + -halfWidth, halfHeight, halfDepth, // 3 + -halfWidth, halfHeight, halfDepth, // 4 + -halfWidth, halfHeight, halfDepth, // 5 + // v2 + -halfWidth, halfHeight, -halfDepth, // 6 + -halfWidth, halfHeight, -halfDepth, // 7 + -halfWidth, halfHeight, -halfDepth, // 8 + // v3 + halfWidth, halfHeight, -halfDepth, // 9 + halfWidth, halfHeight, -halfDepth, // 10 + halfWidth, halfHeight, -halfDepth, // 11 + // v4 + halfWidth, -halfHeight, halfDepth, // 12 + halfWidth, -halfHeight, halfDepth, // 13 + halfWidth, -halfHeight, halfDepth, // 14 + // v5 + -halfWidth, -halfHeight, halfDepth, // 15 + -halfWidth, -halfHeight, halfDepth, // 16 + -halfWidth, -halfHeight, halfDepth, // 17 + // v6 + -halfWidth, -halfHeight, -halfDepth, // 18 + -halfWidth, -halfHeight, -halfDepth, // 19 + -halfWidth, -halfHeight, -halfDepth, // 20 + // v7 + halfWidth, -halfHeight, -halfDepth, // 21 + halfWidth, -halfHeight, -halfDepth, // 22 + halfWidth, -halfHeight, -halfDepth, // 23 + ]); + // 3 consecutive entries in the index buffer define a triangle. Each index + // points to a vertex stored in the vertex data above. The index for the X + // face must point to a vertex in the X face, and so on. In addition, keep + // in mind that front-facing faces need to have their vertices listed + // counter-clockwise, and we are culling (not drawing) back-facing + // triangles. This means that based on the cube diagram above, triangles for + // the +X, +Y, and +Z need to have their vertices listed counter-clockwise, + // and the -X, -Y, and -Z clockwise. + // prettier-ignore + const indices = new Uint32Array([ + 0, 12, 21, 21, 9, 0, // +X face + 1, 10, 7, 7, 4, 1, // +Y face + 2, 5, 14, 14, 5, 17, // +Z face + 3, 6, 18, 18, 15, 3, // -X face + 16, 19, 13, 13, 19, 22, // -Y face + 8, 11, 20, 20, 11, 23, // -Z face + ]); + // prettier-ignore + const vertexNormals = new Float32Array([ + //X normal Y normal Z normal + 1, 0, 0, 0, 1, 0, 0, 0, 1, // v0 + -1, 0, 0, 0, 1, 0, 0, 0, 1, // v1 + -1, 0, 0, 0, 1, 0, 0, 0, -1, // v2 + 1, 0, 0, 0, 1, 0, 0, 0, -1, // v3 + 1, 0, 0, 0, -1, 0, 0, 0, 1, // v4 + -1, 0, 0, 0, -1, 0, 0, 0, 1, // v5 + -1, 0, 0, 0, -1, 0, 0, 0, -1, // v6 + 1, 0, 0, 0, -1, 0, 0, 0, -1, // v7 + ]); + this.setVertices(vertices); + this.setIndices(indices); + this.setVertexNormals(vertexNormals); + } +} +export { Box }; +//# sourceMappingURL=Box.js.map \ No newline at end of file diff --git a/src/geometries/Box.js.map b/src/geometries/Box.js.map new file mode 100644 index 0000000..6e9d308 --- /dev/null +++ b/src/geometries/Box.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Box.js","sourceRoot":"","sources":["Box.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAEvC,MAAM,GAAI,SAAQ,QAAQ;IAKxB,YAAY,KAAa,EAAE,MAAc,EAAE,KAAa;QACtD,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,MAAM,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;QAC5B,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,CAAC;QAC9B,MAAM,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;QAE5B,gBAAgB;QAChB,gBAAgB;QAChB,sBAAsB;QACtB,sBAAsB;QACtB,2BAA2B;QAC3B,qBAAqB;QACrB,oBAAoB;QAEpB,2EAA2E;QAC3E,4EAA4E;QAC5E,2DAA2D;QAC3D,kBAAkB;QAClB,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC;YAC/B,KAAK;YACL,SAAS,EAAG,UAAU,EAAG,SAAS,EAAE,WAAW;YAC/C,SAAS,EAAG,UAAU,EAAG,SAAS,EAAE,WAAW;YAC/C,SAAS,EAAG,UAAU,EAAG,SAAS,EAAE,WAAW;YAE/C,KAAK;YACN,CAAC,SAAS,EAAG,UAAU,EAAG,SAAS,EAAE,IAAI;YACzC,CAAC,SAAS,EAAG,UAAU,EAAG,SAAS,EAAE,IAAI;YACzC,CAAC,SAAS,EAAG,UAAU,EAAG,SAAS,EAAE,IAAI;YAExC,KAAK;YACN,CAAC,SAAS,EAAG,UAAU,EAAE,CAAC,SAAS,EAAE,IAAI;YACzC,CAAC,SAAS,EAAG,UAAU,EAAE,CAAC,SAAS,EAAE,IAAI;YACzC,CAAC,SAAS,EAAG,UAAU,EAAE,CAAC,SAAS,EAAE,IAAI;YAExC,KAAK;YACL,SAAS,EAAG,UAAU,EAAE,CAAC,SAAS,EAAE,IAAI;YACxC,SAAS,EAAG,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;YACzC,SAAS,EAAG,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;YAEzC,KAAK;YACL,SAAS,EAAE,CAAC,UAAU,EAAG,SAAS,EAAE,KAAK;YACzC,SAAS,EAAE,CAAC,UAAU,EAAG,SAAS,EAAE,KAAK;YACzC,SAAS,EAAE,CAAC,UAAU,EAAG,SAAS,EAAE,KAAK;YAEzC,KAAK;YACN,CAAC,SAAS,EAAE,CAAC,UAAU,EAAG,SAAS,EAAE,KAAK;YAC1C,CAAC,SAAS,EAAE,CAAC,UAAU,EAAG,SAAS,EAAE,KAAK;YAC1C,CAAC,SAAS,EAAE,CAAC,UAAU,EAAG,SAAS,EAAE,KAAK;YAEzC,KAAK;YACN,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;YAC1C,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;YAC1C,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;YAEzC,KAAK;YACL,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;YACzC,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;YACzC,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,KAAK;SAC3C,CAAC,CAAC;QAEH,0EAA0E;QAC1E,0EAA0E;QAC1E,0EAA0E;QAC1E,qEAAqE;QACrE,kEAAkE;QAClE,4EAA4E;QAC5E,2EAA2E;QAC3E,oCAAoC;QACpC,kBAAkB;QAClB,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC;YAC7B,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAG,CAAC,EAAG,CAAC,EAAE,UAAU;YACjC,CAAC,EAAE,EAAE,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,UAAU;YACjC,CAAC,EAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAG,CAAC,EAAE,EAAE,EAAE,UAAU;YACjC,CAAC,EAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAG,CAAC,EAAE,UAAU;YAClC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU;YACjC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU;SACnC,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,aAAa,GAAG,IAAI,YAAY,CAAC;YACrC,8BAA8B;YAC3B,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,KAAK;YACnC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,KAAK;YACnC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK;YAClC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK;YAClC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,KAAK;YACnC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,KAAK;YACnC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK;YAClC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK;SACtC,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;CACF;AAED,OAAO,EAAC,GAAG,EAAC,CAAC"} \ No newline at end of file diff --git a/src/geometries/Geometry.d.ts b/src/geometries/Geometry.d.ts new file mode 100644 index 0000000..ea59046 --- /dev/null +++ b/src/geometries/Geometry.d.ts @@ -0,0 +1,17 @@ +import { vec3, vec2, Vec3 } from 'wgpu-matrix'; +declare class Geometry { + vertexPositions: Float32Array; + vertexNormals: Float32Array; + uvs: Float32Array; + indices: Uint32Array; + constructor(vertices?: Float32Array, indices?: Uint32Array, vertexNormals?: Float32Array, uvs?: Float32Array); + setVertices(newVertexPositions: Float32Array): void; + setIndices(newIndices: Uint32Array): void; + setVertexNormals(newVertexNormals: Float32Array): void; + setUVs(newUVs: Float32Array): void; + getNumVertices(): number; + getNumTriangles(): number; + forEachVertex(callback: (index: number, localPosition: vec3, normal: vec3, uv: vec2) => void): void; + forEachTriangle(callback: (index: number, indices: Vec3) => void): void; +} +export { Geometry }; diff --git a/src/geometries/Geometry.js b/src/geometries/Geometry.js new file mode 100644 index 0000000..0732907 --- /dev/null +++ b/src/geometries/Geometry.js @@ -0,0 +1,47 @@ +import { vec3, vec2 } from 'wgpu-matrix'; +class Geometry { + constructor(vertices, indices, vertexNormals, uvs) { + this.vertexPositions = vertices !== null && vertices !== void 0 ? vertices : new Float32Array(); + this.indices = indices !== null && indices !== void 0 ? indices : new Uint32Array(); + this.vertexNormals = vertexNormals !== null && vertexNormals !== void 0 ? vertexNormals : new Float32Array(); + this.uvs = uvs !== null && uvs !== void 0 ? uvs : new Float32Array(); + } + setVertices(newVertexPositions) { + this.vertexPositions = newVertexPositions; + } + setIndices(newIndices) { + this.indices = newIndices; + } + setVertexNormals(newVertexNormals) { + this.vertexNormals = newVertexNormals; + } + setUVs(newUVs) { + this.uvs = newUVs; + } + getNumVertices() { + return this.vertexPositions.length / 3; + } + getNumTriangles() { + return this.indices.length / 3; + } + forEachVertex(callback) { + for (let i = 0; i < this.vertexPositions.length; i += 3) { + callback( + // index + i / 3, + // local position + vec3.create(this.vertexPositions[i + 0], this.vertexPositions[i + 1], this.vertexPositions[i + 2]), + // normal + vec3.create(this.vertexNormals[i + 0], this.vertexNormals[i + 1], this.vertexNormals[i + 2]), + // uv + vec2.create(this.uvs[i], this.uvs[i + 1])); + } + } + forEachTriangle(callback) { + for (let i = 0; i < this.indices.length; i += 3) { + callback(i / 3, vec3.create(this.indices[i + 0], this.indices[i + 1], this.indices[i + 2])); + } + } +} +export { Geometry }; +//# sourceMappingURL=Geometry.js.map \ No newline at end of file diff --git a/src/geometries/Geometry.js.map b/src/geometries/Geometry.js.map new file mode 100644 index 0000000..e3ca14d --- /dev/null +++ b/src/geometries/Geometry.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Geometry.js","sourceRoot":"","sources":["Geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,IAAI,EAAO,MAAM,aAAa,CAAC;AAE7C,MAAM,QAAQ;IAMZ,YACE,QAAuB,EACvB,OAAqB,EACrB,aAA4B,EAC5B,GAAkB;QAElB,IAAI,CAAC,eAAe,GAAG,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,IAAI,YAAY,EAAE,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,IAAI,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,aAAa,GAAG,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,IAAI,YAAY,EAAE,CAAC;QACzD,IAAI,CAAC,GAAG,GAAG,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,IAAI,YAAY,EAAE,CAAC;IACvC,CAAC;IAED,WAAW,CAAC,kBAAgC;QAC1C,IAAI,CAAC,eAAe,GAAG,kBAAkB,CAAC;IAC5C,CAAC;IAED,UAAU,CAAC,UAAuB;QAChC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC;IAC5B,CAAC;IAED,gBAAgB,CAAC,gBAA8B;QAC7C,IAAI,CAAC,aAAa,GAAG,gBAAgB,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,MAAoB;QACzB,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC;IACpB,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,aAAa,CACX,QAKS;QAET,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,QAAQ;YACN,QAAQ;YACR,CAAC,GAAG,CAAC;YACL,iBAAiB;YACjB,IAAI,CAAC,MAAM,CACT,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,EAC3B,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,EAC3B,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAC5B;YACD,SAAS;YACT,IAAI,CAAC,MAAM,CACT,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,EACzB,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,EACzB,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAC1B;YACD,KAAK;YACL,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAC1C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,eAAe,CAAC,QAAgD;QAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,QAAQ,CACN,CAAC,GAAG,CAAC,EACL,IAAI,CAAC,MAAM,CACT,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,EACnB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,EACnB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CACpB,CACF,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAED,OAAO,EAAC,QAAQ,EAAC,CAAC"} \ No newline at end of file diff --git a/src/geometries/Plane.d.ts b/src/geometries/Plane.d.ts new file mode 100644 index 0000000..862aed9 --- /dev/null +++ b/src/geometries/Plane.d.ts @@ -0,0 +1,7 @@ +import { Geometry } from './Geometry.js'; +declare class Plane extends Geometry { + readonly width: number; + readonly height: number; + constructor(width: number, height: number); +} +export { Plane }; diff --git a/src/geometries/Plane.js b/src/geometries/Plane.js new file mode 100644 index 0000000..18dc2eb --- /dev/null +++ b/src/geometries/Plane.js @@ -0,0 +1,49 @@ +import { Geometry } from './Geometry.js'; +class Plane extends Geometry { + constructor(width, height) { + super(); + this.width = width; + this.height = height; + const halfWidth = width / 2; + const halfHeight = height / 2; + // v1--v0 + // |\ | +Y + // | \ | | + // | \| |---+X + // v2--v3 + // prettier-ignore + const vertices = new Float32Array([ + // v0 + halfWidth, halfHeight, 0, // 0 + // halfWidth, halfHeight, 0, // 1 + // v1 + -halfWidth, halfHeight, 0, // 2 + // -halfWidth, halfHeight, 0, // 3 + // v2 + -halfWidth, -halfHeight, 0, // 4 + // -halfWidth, -halfHeight, 0, // 5 + // v3 + halfWidth, -halfHeight, 0, // 6 + // halfWidth, -halfHeight, 0, // 7 + ]); + // prettier-ignore + const indices = new Uint32Array([ + // 0, 2, 6, 6, 2, 4, // +Z face + // 1, 7, 3, 3, 7, 5, // -Z face + 0, 1, 3, 3, 1, 2 + ]); + // prettier-ignore + const vertexNormals = new Float32Array([ + // +Z face -Z face + 0, 0, 1, /* 0, 0, -1, */ // v0 + 0, 0, 1, /* 0, 0, -1, */ // v1 + 0, 0, 1, /* 0, 0, -1, */ // v2 + 0, 0, 1, /* 0, 0, -1, */ // v3 + ]); + this.setVertices(vertices); + this.setIndices(indices); + this.setVertexNormals(vertexNormals); + } +} +export { Plane }; +//# sourceMappingURL=Plane.js.map \ No newline at end of file diff --git a/src/geometries/Plane.js.map b/src/geometries/Plane.js.map new file mode 100644 index 0000000..647916b --- /dev/null +++ b/src/geometries/Plane.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Plane.js","sourceRoot":"","sources":["Plane.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAEvC,MAAM,KAAM,SAAQ,QAAQ;IAI1B,YAAY,KAAa,EAAE,MAAc;QACvC,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,MAAM,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;QAC5B,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,CAAC;QAE9B,SAAS;QACT,eAAe;QACf,eAAe;QACf,oBAAoB;QACpB,SAAS;QAET,kBAAkB;QAClB,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC;YAC/B,KAAK;YACL,SAAS,EAAG,UAAU,EAAE,CAAC,EAAE,IAAI;YAChC,mCAAmC;YAElC,KAAK;YACN,CAAC,SAAS,EAAG,UAAU,EAAE,CAAC,EAAE,IAAI;YAChC,mCAAmC;YAElC,KAAK;YACN,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,IAAI;YAChC,mCAAmC;YAElC,KAAK;YACL,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,IAAI;YAChC,mCAAmC;SACpC,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC;YAC9B,+BAA+B;YAC/B,+BAA+B;YAC/B,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;SACjB,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,aAAa,GAAG,IAAI,YAAY,CAAC;YACrC,mBAAmB;YAChB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,KAAK;YAC9B,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,KAAK;YAC9B,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,KAAK;YAC9B,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,KAAK;SAClC,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;CACF;AAED,OAAO,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/src/geometries/Sphere.d.ts b/src/geometries/Sphere.d.ts new file mode 100644 index 0000000..d40c126 --- /dev/null +++ b/src/geometries/Sphere.d.ts @@ -0,0 +1,8 @@ +import { Geometry } from './Geometry.js'; +declare class Sphere extends Geometry { + readonly radius: number; + readonly widthSegments: number; + readonly heightSegments: number; + constructor(radius: number, widthSegments?: number, heightSegments?: number); +} +export { Sphere }; diff --git a/src/geometries/Sphere.js b/src/geometries/Sphere.js new file mode 100644 index 0000000..ffe0f32 --- /dev/null +++ b/src/geometries/Sphere.js @@ -0,0 +1,65 @@ +import { Geometry } from './Geometry.js'; +class Sphere extends Geometry { + constructor(radius, widthSegments = 32, heightSegments = 16) { + super(); + this.radius = radius; + this.widthSegments = widthSegments; + this.heightSegments = heightSegments; + const vertices = new Float32Array(3 * this.widthSegments * (this.heightSegments + 1)); + const normals = new Float32Array(3 * this.widthSegments * (this.heightSegments + 1)); + for (let height = 0; height < heightSegments + 1; height++) { + for (let width = 0; width < widthSegments; width++) { + const normalizedWidth = width / widthSegments; + const normalizedHeight = height / heightSegments; + const theta = Math.PI * normalizedHeight; + const phi = Math.PI * 2 * normalizedWidth; + // Parametric equation of a sphere: + // x = x0 + r * sin(t) * cos(p) + // y = y0 + r * cos(t) + // z = z0 + r * sin(t) * sin(p) + const unit_x = Math.sin(theta) * Math.cos(phi); + const unit_y = Math.cos(theta); + const unit_z = Math.sin(theta) * Math.sin(phi); + const index = width + height * widthSegments; + vertices[index * 3 + 0] = radius * unit_x; + vertices[index * 3 + 1] = radius * unit_y; + vertices[index * 3 + 2] = radius * unit_z; + normals[index * 3 + 0] = unit_x; + normals[index * 3 + 1] = unit_y; + normals[index * 3 + 2] = unit_z; + } + } + // Index (widthSegments=3, heightSegments=2): + // + // 0-1-2-0 + // |/|/|/| + // 3-4-5-3 <--- UV sphere when stretched into a rectangle + // |/|/|/| + // 6-7-8-6 + const indices = new Uint32Array(3 * 2 * widthSegments * heightSegments); + for (let height = 0; height < heightSegments; height++) { + for (let width = 0; width < widthSegments; width++) { + // v0-v1 + // |/ | <--- A quad from the stretched UV sphere above + // v3-v2 + const v0 = width + height * widthSegments; + const v1 = ((width + 1) % widthSegments) + height * widthSegments; + const v2 = ((width + 1) % widthSegments) + (height + 1) * widthSegments; + const v3 = width + (height + 1) * widthSegments; + const offset = (width + height * widthSegments) * 6; + // Front-facing faces have their vertices in counter-clockwise order + indices[offset + 0] = v0; + indices[offset + 1] = v3; + indices[offset + 2] = v1; + indices[offset + 3] = v1; + indices[offset + 4] = v3; + indices[offset + 5] = v2; + } + } + this.setVertices(vertices); + this.setIndices(indices); + this.setVertexNormals(normals); + } +} +export { Sphere }; +//# sourceMappingURL=Sphere.js.map \ No newline at end of file diff --git a/src/geometries/Sphere.js.map b/src/geometries/Sphere.js.map new file mode 100644 index 0000000..9d6c710 --- /dev/null +++ b/src/geometries/Sphere.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Sphere.js","sourceRoot":"","sources":["Sphere.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/geometries/exports.d.ts b/src/geometries/exports.d.ts new file mode 100644 index 0000000..1b93735 --- /dev/null +++ b/src/geometries/exports.d.ts @@ -0,0 +1,4 @@ +export * from './Box.js'; +export * from './Geometry.js'; +export * from './Plane.js'; +export * from './Sphere.js'; diff --git a/src/geometries/exports.js b/src/geometries/exports.js new file mode 100644 index 0000000..85e2646 --- /dev/null +++ b/src/geometries/exports.js @@ -0,0 +1,5 @@ +export * from './Box.js'; +export * from './Geometry.js'; +export * from './Plane.js'; +export * from './Sphere.js'; +//# sourceMappingURL=exports.js.map \ No newline at end of file diff --git a/src/geometries/exports.js.map b/src/geometries/exports.js.map new file mode 100644 index 0000000..2686322 --- /dev/null +++ b/src/geometries/exports.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exports.js","sourceRoot":"","sources":["exports.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"} \ No newline at end of file diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 0000000..2d28edb --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,6 @@ +export * from './cameras/exports.js'; +export * from './geometries/exports.js'; +export * from './lights/exports.js'; +export * from './materials/exports.js'; +export * from './primitives/exports.js'; +export * from './renderers/exports.js'; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..bf85a33 --- /dev/null +++ b/src/index.js @@ -0,0 +1,7 @@ +export * from './cameras/exports.js'; +export * from './geometries/exports.js'; +export * from './lights/exports.js'; +export * from './materials/exports.js'; +export * from './primitives/exports.js'; +export * from './renderers/exports.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/src/index.js.map b/src/index.js.map new file mode 100644 index 0000000..cbbea28 --- /dev/null +++ b/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC"} \ No newline at end of file diff --git a/src/lights/AmbientLight.d.ts b/src/lights/AmbientLight.d.ts new file mode 100644 index 0000000..5471791 --- /dev/null +++ b/src/lights/AmbientLight.d.ts @@ -0,0 +1,7 @@ +import { Light } from './Light.js'; +import { Vec3 } from 'wgpu-matrix'; +declare class AmbientLight extends Light { + readonly type: number; + constructor(color?: Vec3, intensity?: number); +} +export { AmbientLight }; diff --git a/src/lights/AmbientLight.js b/src/lights/AmbientLight.js new file mode 100644 index 0000000..66a717c --- /dev/null +++ b/src/lights/AmbientLight.js @@ -0,0 +1,11 @@ +import { Light } from './Light.js'; +import { vec3 } from 'wgpu-matrix'; +import { AMBIENT_LIGHT } from './constants.js'; +class AmbientLight extends Light { + constructor(color = vec3.create(1, 1, 1), intensity = 1) { + super(color, intensity); + this.type = AMBIENT_LIGHT; + } +} +export { AmbientLight }; +//# sourceMappingURL=AmbientLight.js.map \ No newline at end of file diff --git a/src/lights/AmbientLight.js.map b/src/lights/AmbientLight.js.map new file mode 100644 index 0000000..26fbb4e --- /dev/null +++ b/src/lights/AmbientLight.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AmbientLight.js","sourceRoot":"","sources":["AmbientLight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,IAAI,EAAO,MAAM,aAAa,CAAC;AACvC,OAAO,EAAC,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAE7C,MAAM,YAAa,SAAQ,KAAK;IAG9B,YAAY,QAAc,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC;QAC3D,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAHR,SAAI,GAAW,aAAa,CAAC;IAI/C,CAAC;CACF;AAED,OAAO,EAAC,YAAY,EAAC,CAAC"} \ No newline at end of file diff --git a/src/lights/Light.d.ts b/src/lights/Light.d.ts new file mode 100644 index 0000000..d49d676 --- /dev/null +++ b/src/lights/Light.d.ts @@ -0,0 +1,9 @@ +import { Vec3 } from 'wgpu-matrix'; +import { Object3D } from '../primitives/Group.js'; +declare abstract class Light extends Object3D { + readonly type: number; + color: Vec3; + intensity: number; + constructor(color: Vec3, intensity: number); +} +export { Light }; diff --git a/src/lights/Light.js b/src/lights/Light.js new file mode 100644 index 0000000..0fb6b33 --- /dev/null +++ b/src/lights/Light.js @@ -0,0 +1,11 @@ +import { Object3D } from '../primitives/Group.js'; +class Light extends Object3D { + constructor(color, intensity) { + super(); + this.type = 0; + this.color = color; + this.intensity = intensity; + } +} +export { Light }; +//# sourceMappingURL=Light.js.map \ No newline at end of file diff --git a/src/lights/Light.js.map b/src/lights/Light.js.map new file mode 100644 index 0000000..4744858 --- /dev/null +++ b/src/lights/Light.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Light.js","sourceRoot":"","sources":["Light.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAEhD,MAAe,KAAM,SAAQ,QAAQ;IAKnC,YAAY,KAAW,EAAE,SAAiB;QACxC,KAAK,EAAE,CAAC;QALD,SAAI,GAAW,CAAC,CAAC;QAOxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,OAAO,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/src/lights/PointLight.d.ts b/src/lights/PointLight.d.ts new file mode 100644 index 0000000..00dbd19 --- /dev/null +++ b/src/lights/PointLight.d.ts @@ -0,0 +1,6 @@ +import { Light } from './Light.js'; +declare class PointLight extends Light { + readonly type = 2; + constructor(color?: any, intensity?: number); +} +export { PointLight }; diff --git a/src/lights/PointLight.js b/src/lights/PointLight.js new file mode 100644 index 0000000..cf467ff --- /dev/null +++ b/src/lights/PointLight.js @@ -0,0 +1,11 @@ +import { Light } from './Light.js'; +import { POINT_LIGHT } from './constants.js'; +import { vec3 } from 'wgpu-matrix'; +class PointLight extends Light { + constructor(color = vec3.create(1, 1, 1), intensity = 1) { + super(color, intensity); + this.type = POINT_LIGHT; + } +} +export { PointLight }; +//# sourceMappingURL=PointLight.js.map \ No newline at end of file diff --git a/src/lights/PointLight.js.map b/src/lights/PointLight.js.map new file mode 100644 index 0000000..c3704d5 --- /dev/null +++ b/src/lights/PointLight.js.map @@ -0,0 +1 @@ +{"version":3,"file":"PointLight.js","sourceRoot":"","sources":["PointLight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAC;AAEjC,MAAM,UAAW,SAAQ,KAAK;IAG5B,YAAY,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC;QACrD,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAHR,SAAI,GAAG,WAAW,CAAC;IAIrC,CAAC;CACF;AAED,OAAO,EAAC,UAAU,EAAC,CAAC"} \ No newline at end of file diff --git a/src/lights/constants.d.ts b/src/lights/constants.d.ts new file mode 100644 index 0000000..74b1f0c --- /dev/null +++ b/src/lights/constants.d.ts @@ -0,0 +1,3 @@ +declare const AMBIENT_LIGHT = 1; +declare const POINT_LIGHT = 2; +export { AMBIENT_LIGHT, POINT_LIGHT }; diff --git a/src/lights/constants.js b/src/lights/constants.js new file mode 100644 index 0000000..3dccfa6 --- /dev/null +++ b/src/lights/constants.js @@ -0,0 +1,4 @@ +const AMBIENT_LIGHT = 1; +const POINT_LIGHT = 2; +export { AMBIENT_LIGHT, POINT_LIGHT }; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/src/lights/constants.js.map b/src/lights/constants.js.map new file mode 100644 index 0000000..79bf462 --- /dev/null +++ b/src/lights/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["constants.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,OAAO,EAAC,aAAa,EAAE,WAAW,EAAC,CAAC"} \ No newline at end of file diff --git a/src/lights/exports.d.ts b/src/lights/exports.d.ts new file mode 100644 index 0000000..948450e --- /dev/null +++ b/src/lights/exports.d.ts @@ -0,0 +1,3 @@ +export * from './Light.js'; +export * from './AmbientLight.js'; +export * from './PointLight.js'; diff --git a/src/lights/exports.js b/src/lights/exports.js new file mode 100644 index 0000000..aa79d1a --- /dev/null +++ b/src/lights/exports.js @@ -0,0 +1,4 @@ +export * from './Light.js'; +export * from './AmbientLight.js'; +export * from './PointLight.js'; +//# sourceMappingURL=exports.js.map \ No newline at end of file diff --git a/src/lights/exports.js.map b/src/lights/exports.js.map new file mode 100644 index 0000000..d810856 --- /dev/null +++ b/src/lights/exports.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exports.js","sourceRoot":"","sources":["exports.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"} \ No newline at end of file diff --git a/src/materials/BlinnPhong.d.ts b/src/materials/BlinnPhong.d.ts new file mode 100644 index 0000000..4855e7c --- /dev/null +++ b/src/materials/BlinnPhong.d.ts @@ -0,0 +1,10 @@ +import { Material } from './Material.js'; +import { Vec3 } from 'wgpu-matrix'; +declare class BlinnPhong extends Material { + readonly type = 2; + color: Vec3; + specular: Vec3; + shininess: number; + constructor(color?: Vec3, specular?: Vec3, shininess?: number); +} +export { BlinnPhong }; diff --git a/src/materials/BlinnPhong.js b/src/materials/BlinnPhong.js new file mode 100644 index 0000000..6e7ba7c --- /dev/null +++ b/src/materials/BlinnPhong.js @@ -0,0 +1,14 @@ +import { Material } from './Material.js'; +import { BLINN_PHONG } from './constants.js'; +import { vec3 } from 'wgpu-matrix'; +class BlinnPhong extends Material { + constructor(color = vec3.create(1, 1, 1), specular = vec3.create(0x11 / 0xff, 0x11 / 0xff, 0x11 / 0xff), shininess = 30) { + super(); + this.type = BLINN_PHONG; + this.color = color; + this.specular = specular; + this.shininess = shininess; + } +} +export { BlinnPhong }; +//# sourceMappingURL=BlinnPhong.js.map \ No newline at end of file diff --git a/src/materials/BlinnPhong.js.map b/src/materials/BlinnPhong.js.map new file mode 100644 index 0000000..954f50d --- /dev/null +++ b/src/materials/BlinnPhong.js.map @@ -0,0 +1 @@ +{"version":3,"file":"BlinnPhong.js","sourceRoot":"","sources":["BlinnPhong.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AACvC,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAC,IAAI,EAAO,MAAM,aAAa,CAAC;AAEvC,MAAM,UAAW,SAAQ,QAAQ;IAM/B,YACE,QAAc,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAClC,WAAiB,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,EACnE,SAAS,GAAG,EAAE;QAEd,KAAK,EAAE,CAAC;QAVQ,SAAI,GAAG,WAAW,CAAC;QAYnC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,OAAO,EAAC,UAAU,EAAC,CAAC"} \ No newline at end of file diff --git a/src/materials/Lambert.d.ts b/src/materials/Lambert.d.ts new file mode 100644 index 0000000..55614c2 --- /dev/null +++ b/src/materials/Lambert.d.ts @@ -0,0 +1,8 @@ +import { Material } from './Material.js'; +import { Vec3 } from 'wgpu-matrix'; +declare class Lambert extends Material { + readonly type = 3; + color: Vec3; + constructor(color: Vec3); +} +export { Lambert }; diff --git a/src/materials/Lambert.js b/src/materials/Lambert.js new file mode 100644 index 0000000..a63bbd6 --- /dev/null +++ b/src/materials/Lambert.js @@ -0,0 +1,11 @@ +import { LAMBERT } from './constants.js'; +import { Material } from './Material.js'; +class Lambert extends Material { + constructor(color) { + super(); + this.type = LAMBERT; + this.color = color; + } +} +export { Lambert }; +//# sourceMappingURL=Lambert.js.map \ No newline at end of file diff --git a/src/materials/Lambert.js.map b/src/materials/Lambert.js.map new file mode 100644 index 0000000..47b549b --- /dev/null +++ b/src/materials/Lambert.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Lambert.js","sourceRoot":"","sources":["Lambert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAGvC,MAAM,OAAQ,SAAQ,QAAQ;IAI5B,YAAY,KAAW;QACrB,KAAK,EAAE,CAAC;QAJQ,SAAI,GAAG,OAAO,CAAC;QAM/B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,OAAO,EAAC,OAAO,EAAC,CAAC"} \ No newline at end of file diff --git a/src/materials/Material.d.ts b/src/materials/Material.d.ts new file mode 100644 index 0000000..9da7212 --- /dev/null +++ b/src/materials/Material.d.ts @@ -0,0 +1,4 @@ +declare abstract class Material { + readonly type: number; +} +export { Material }; diff --git a/src/materials/Material.js b/src/materials/Material.js new file mode 100644 index 0000000..cb51380 --- /dev/null +++ b/src/materials/Material.js @@ -0,0 +1,7 @@ +class Material { + constructor() { + this.type = 0; + } +} +export { Material }; +//# sourceMappingURL=Material.js.map \ No newline at end of file diff --git a/src/materials/Material.js.map b/src/materials/Material.js.map new file mode 100644 index 0000000..73cd970 --- /dev/null +++ b/src/materials/Material.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Material.js","sourceRoot":"","sources":["Material.ts"],"names":[],"mappings":"AAAA,MAAe,QAAQ;IAAvB;QACW,SAAI,GAAW,CAAC,CAAC;IAC5B,CAAC;CAAA;AAED,OAAO,EAAC,QAAQ,EAAC,CAAC"} \ No newline at end of file diff --git a/src/materials/Metal.d.ts b/src/materials/Metal.d.ts new file mode 100644 index 0000000..4e1a6e9 --- /dev/null +++ b/src/materials/Metal.d.ts @@ -0,0 +1,9 @@ +import { Material } from './Material.js'; +import { Vec3 } from 'wgpu-matrix'; +declare class Metal extends Material { + readonly type = 4; + color: Vec3; + fuzziness: number; + constructor(color: Vec3, fuzziness: number); +} +export { Metal }; diff --git a/src/materials/Metal.js b/src/materials/Metal.js new file mode 100644 index 0000000..a9c9368 --- /dev/null +++ b/src/materials/Metal.js @@ -0,0 +1,12 @@ +import { Material } from './Material.js'; +import { METAL } from './constants.js'; +class Metal extends Material { + constructor(color, fuzziness) { + super(); + this.type = METAL; + this.color = color; + this.fuzziness = fuzziness; + } +} +export { Metal }; +//# sourceMappingURL=Metal.js.map \ No newline at end of file diff --git a/src/materials/Metal.js.map b/src/materials/Metal.js.map new file mode 100644 index 0000000..3dd652c --- /dev/null +++ b/src/materials/Metal.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Metal.js","sourceRoot":"","sources":["Metal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AACvC,OAAO,EAAC,KAAK,EAAC,MAAM,gBAAgB,CAAC;AAGrC,MAAM,KAAM,SAAQ,QAAQ;IAK1B,YAAY,KAAW,EAAE,SAAiB;QACxC,KAAK,EAAE,CAAC;QALQ,SAAI,GAAG,KAAK,CAAC;QAO7B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,OAAO,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/src/materials/SolidColor.d.ts b/src/materials/SolidColor.d.ts new file mode 100644 index 0000000..90d1a6b --- /dev/null +++ b/src/materials/SolidColor.d.ts @@ -0,0 +1,8 @@ +import { Material } from './Material.js'; +import { Vec3 } from 'wgpu-matrix'; +declare class SolidColor extends Material { + readonly type = 1; + color: Vec3; + constructor(color?: Vec3); +} +export { SolidColor }; diff --git a/src/materials/SolidColor.js b/src/materials/SolidColor.js new file mode 100644 index 0000000..f43a121 --- /dev/null +++ b/src/materials/SolidColor.js @@ -0,0 +1,12 @@ +import { SOLID_COLOR } from './constants.js'; +import { Material } from './Material.js'; +import { vec3 } from 'wgpu-matrix'; +class SolidColor extends Material { + constructor(color = vec3.create(1, 1, 1)) { + super(); + this.type = SOLID_COLOR; + this.color = color; + } +} +export { SolidColor }; +//# sourceMappingURL=SolidColor.js.map \ No newline at end of file diff --git a/src/materials/SolidColor.js.map b/src/materials/SolidColor.js.map new file mode 100644 index 0000000..59b3d17 --- /dev/null +++ b/src/materials/SolidColor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"SolidColor.js","sourceRoot":"","sources":["SolidColor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AACvC,OAAO,EAAC,IAAI,EAAO,MAAM,aAAa,CAAC;AAEvC,MAAM,UAAW,SAAQ,QAAQ;IAI/B,YAAY,QAAc,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5C,KAAK,EAAE,CAAC;QAJQ,SAAI,GAAG,WAAW,CAAC;QAKnC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,OAAO,EAAC,UAAU,EAAC,CAAC"} \ No newline at end of file diff --git a/src/materials/constants.d.ts b/src/materials/constants.d.ts new file mode 100644 index 0000000..f6da818 --- /dev/null +++ b/src/materials/constants.d.ts @@ -0,0 +1,5 @@ +declare const SOLID_COLOR = 1; +declare const BLINN_PHONG = 2; +declare const LAMBERT = 3; +declare const METAL = 4; +export { SOLID_COLOR, BLINN_PHONG, LAMBERT, METAL }; diff --git a/src/materials/constants.js b/src/materials/constants.js new file mode 100644 index 0000000..0357907 --- /dev/null +++ b/src/materials/constants.js @@ -0,0 +1,6 @@ +const SOLID_COLOR = 1; +const BLINN_PHONG = 2; +const LAMBERT = 3; +const METAL = 4; +export { SOLID_COLOR, BLINN_PHONG, LAMBERT, METAL }; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/src/materials/constants.js.map b/src/materials/constants.js.map new file mode 100644 index 0000000..e61b560 --- /dev/null +++ b/src/materials/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["constants.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,OAAO,GAAG,CAAC,CAAC;AAClB,MAAM,KAAK,GAAG,CAAC,CAAC;AAEhB,OAAO,EAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/src/materials/exports.d.ts b/src/materials/exports.d.ts new file mode 100644 index 0000000..01dd9c0 --- /dev/null +++ b/src/materials/exports.d.ts @@ -0,0 +1,6 @@ +export * from './constants.js'; +export * from './Lambert.js'; +export * from './Material.js'; +export * from './Metal.js'; +export * from './SolidColor.js'; +export * from './BlinnPhong.js'; diff --git a/src/materials/exports.js b/src/materials/exports.js new file mode 100644 index 0000000..d56e4a4 --- /dev/null +++ b/src/materials/exports.js @@ -0,0 +1,7 @@ +export * from './constants.js'; +export * from './Lambert.js'; +export * from './Material.js'; +export * from './Metal.js'; +export * from './SolidColor.js'; +export * from './BlinnPhong.js'; +//# sourceMappingURL=exports.js.map \ No newline at end of file diff --git a/src/materials/exports.js.map b/src/materials/exports.js.map new file mode 100644 index 0000000..db90439 --- /dev/null +++ b/src/materials/exports.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exports.js","sourceRoot":"","sources":["exports.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"} \ No newline at end of file diff --git a/src/primitives/Group.d.ts b/src/primitives/Group.d.ts new file mode 100644 index 0000000..207fdda --- /dev/null +++ b/src/primitives/Group.d.ts @@ -0,0 +1,12 @@ +import { vec3, quat } from 'wgpu-matrix'; +declare class Group { + children: Group[]; + localPosition: vec3; + localQuaternion: quat; + localScale: vec3; + static readonly DEFAULT_UP: vec3; + constructor(); + add(...children: Group[]): void; + traverse(callback: (group: Group, relativePosition: vec3, relativeRotation: quat, relativeScale: vec3, localPosition: vec3, localRotation: quat, localScale: vec3) => void, offsetPosition?: vec3, offsetRotation?: quat, offsetScale?: vec3): void; +} +export { Group, Group as Object3D }; diff --git a/src/primitives/Group.js b/src/primitives/Group.js new file mode 100644 index 0000000..aa47d01 --- /dev/null +++ b/src/primitives/Group.js @@ -0,0 +1,21 @@ +import { vec3, quat } from 'wgpu-matrix'; +class Group { + constructor() { + this.children = []; + this.localPosition = vec3.create(); + this.localQuaternion = quat.identity(); + this.localScale = vec3.create(1, 1, 1); + } + add(...children) { + this.children.push(...children); + } + traverse(callback, offsetPosition = vec3.create(), offsetRotation = quat.identity(), offsetScale = vec3.create(1, 1, 1)) { + callback(this, vec3.add(this.localPosition, offsetPosition), quat.multiply(this.localQuaternion, offsetRotation), vec3.multiply(this.localScale, offsetScale), this.localPosition, this.localQuaternion, this.localScale); + this.children.forEach(child => { + child.traverse(callback.bind(child), vec3.add(this.localPosition, offsetPosition), quat.multiply(this.localQuaternion, offsetRotation), vec3.multiply(this.localScale, offsetScale)); + }); + } +} +Group.DEFAULT_UP = vec3.create(0, 1, 0); +export { Group, Group as Object3D }; +//# sourceMappingURL=Group.js.map \ No newline at end of file diff --git a/src/primitives/Group.js.map b/src/primitives/Group.js.map new file mode 100644 index 0000000..3b6f136 --- /dev/null +++ b/src/primitives/Group.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Group.js","sourceRoot":"","sources":["Group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,IAAI,EAAa,MAAM,aAAa,CAAC;AAGnD,MAAM,KAAK;IAQT;QACE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACnC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,GAAG,CAAC,GAAG,QAAiB;QACtB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,QAAQ,CACN,QAQS,EACT,iBAAuB,IAAI,CAAC,MAAM,EAAE,EACpC,iBAAuB,IAAI,CAAC,QAAQ,EAAE,EACtC,cAAoB,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAExC,QAAQ,CACN,IAAI,EACJ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,EAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,EACnD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAC3C,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,eAAe,EACpB,IAAI,CAAC,UAAU,CAChB,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC5B,KAAK,CAAC,QAAQ,CACZ,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,EAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,EACnD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAC5C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;;AA7Ce,gBAAU,GAAS,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAgD1D,OAAO,EAAC,KAAK,EAAE,KAAK,IAAI,QAAQ,EAAC,CAAC"} \ No newline at end of file diff --git a/src/primitives/Mesh.d.ts b/src/primitives/Mesh.d.ts new file mode 100644 index 0000000..ccede4f --- /dev/null +++ b/src/primitives/Mesh.d.ts @@ -0,0 +1,9 @@ +import { Geometry } from '../geometries/Geometry.js'; +import { Material } from '../materials/Material.js'; +import { Group } from './Group.js'; +declare class Mesh extends Group { + geometry: Geometry; + material: Material; + constructor(geometry: Geometry, material: Material); +} +export { Mesh }; diff --git a/src/primitives/Mesh.js b/src/primitives/Mesh.js new file mode 100644 index 0000000..6c3d548 --- /dev/null +++ b/src/primitives/Mesh.js @@ -0,0 +1,10 @@ +import { Group } from './Group.js'; +class Mesh extends Group { + constructor(geometry, material) { + super(); + this.geometry = geometry; + this.material = material; + } +} +export { Mesh }; +//# sourceMappingURL=Mesh.js.map \ No newline at end of file diff --git a/src/primitives/Mesh.js.map b/src/primitives/Mesh.js.map new file mode 100644 index 0000000..3ae7561 --- /dev/null +++ b/src/primitives/Mesh.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Mesh.js","sourceRoot":"","sources":["Mesh.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEjC,MAAM,IAAK,SAAQ,KAAK;IAItB,YAAY,QAAkB,EAAE,QAAkB;QAChD,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED,OAAO,EAAC,IAAI,EAAC,CAAC"} \ No newline at end of file diff --git a/src/primitives/Scene.d.ts b/src/primitives/Scene.d.ts new file mode 100644 index 0000000..d6f0a75 --- /dev/null +++ b/src/primitives/Scene.d.ts @@ -0,0 +1,14 @@ +import { Group } from './Group.js'; +declare class Scene extends Group { + stats: { + outdated: boolean; + meshes: number; + vertices: number; + triangles: number; + lights: number; + }; + constructor(); + add(...children: Group[]): void; + updateStats(): void; +} +export { Scene }; diff --git a/src/primitives/Scene.js b/src/primitives/Scene.js new file mode 100644 index 0000000..d5083ac --- /dev/null +++ b/src/primitives/Scene.js @@ -0,0 +1,38 @@ +import { Light } from '../lights/Light.js'; +import { Group } from './Group.js'; +import { Mesh } from './Mesh.js'; +class Scene extends Group { + constructor() { + super(); + this.stats = { + outdated: false, + meshes: 0, + vertices: 0, + triangles: 0, + lights: 0, + }; + } + add(...children) { + this.children.push(...children); + this.stats.outdated = true; + } + updateStats() { + let meshes = 0; + let vertices = 0; + let triangles = 0; + let lights = 0; + this.traverse(group => { + if (group instanceof Mesh) { + meshes++; + vertices += group.geometry.vertexPositions.length / 3; + triangles += group.geometry.indices.length / 3; + } + else if (group instanceof Light) { + lights++; + } + }); + this.stats = { meshes, vertices, triangles, lights, outdated: false }; + } +} +export { Scene }; +//# sourceMappingURL=Scene.js.map \ No newline at end of file diff --git a/src/primitives/Scene.js.map b/src/primitives/Scene.js.map new file mode 100644 index 0000000..bd375ab --- /dev/null +++ b/src/primitives/Scene.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Scene.js","sourceRoot":"","sources":["Scene.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAE/B,MAAM,KAAM,SAAQ,KAAK;IASvB;QACE,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,KAAK,GAAG;YACX,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,CAAC;YACT,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC;SACV,CAAC;IACJ,CAAC;IAEQ,GAAG,CAAC,GAAG,QAAiB;QAC/B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED,WAAW;QACT,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YACpB,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;gBAC1B,MAAM,EAAE,CAAC;gBACT,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;gBACtD,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YACjD,CAAC;iBAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAClC,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,GAAG,EAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAC,CAAC;IACtE,CAAC;CACF;AAED,OAAO,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/src/primitives/exports.d.ts b/src/primitives/exports.d.ts new file mode 100644 index 0000000..27d1a29 --- /dev/null +++ b/src/primitives/exports.d.ts @@ -0,0 +1,3 @@ +export * from './Group.js'; +export * from './Mesh.js'; +export * from './Scene.js'; diff --git a/src/primitives/exports.js b/src/primitives/exports.js new file mode 100644 index 0000000..b13798c --- /dev/null +++ b/src/primitives/exports.js @@ -0,0 +1,4 @@ +export * from './Group.js'; +export * from './Mesh.js'; +export * from './Scene.js'; +//# sourceMappingURL=exports.js.map \ No newline at end of file diff --git a/src/primitives/exports.js.map b/src/primitives/exports.js.map new file mode 100644 index 0000000..ead66df --- /dev/null +++ b/src/primitives/exports.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exports.js","sourceRoot":"","sources":["exports.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"} \ No newline at end of file diff --git a/src/renderers/Rasterizer.d.ts b/src/renderers/Rasterizer.d.ts new file mode 100644 index 0000000..1383306 --- /dev/null +++ b/src/renderers/Rasterizer.d.ts @@ -0,0 +1,30 @@ +import { Scene } from '../primitives/exports.js'; +import { PerspectiveCamera } from '../cameras/exports.js'; +import { Renderer } from './Renderer.js'; +declare class Rasterizer implements Renderer { + readonly canvas: HTMLCanvasElement; + private device?; + private context?; + private format?; + private depthTexture?; + private renderPassDescriptor?; + private bindGroupLayout?; + private bindGroup?; + private pipeline?; + private viewProjectionMatrixBuffer?; + private cameraPositionBuffer?; + private vertexBuffer?; + private indexBuffer?; + private materialBuffer?; + private lightBuffer?; + constructor(canvas?: HTMLCanvasElement); + init(): Promise; + render(scene: Scene, camera: PerspectiveCamera): void; + private getSceneData; + private setCanvasFormatAndContext; + private setDepthTexture; + private setRenderPassDescriptor; + private setBindGroup; + private setPipeline; +} +export { Rasterizer }; diff --git a/src/renderers/Rasterizer.js b/src/renderers/Rasterizer.js new file mode 100644 index 0000000..23a55b2 --- /dev/null +++ b/src/renderers/Rasterizer.js @@ -0,0 +1,361 @@ +import { Mesh } from '../primitives/exports.js'; +import { UP } from '../constants.js'; +import { Light } from '../lights/Light.js'; +import { vertexBufferLayout } from './constants.js'; +// Shaders +import solidColorShader from '../materials/solid_color.wgsl'; +import blinnPhongShader from '../materials/blinn_phong.wgsl'; +import rasterizerShader from './rasterizer.wgsl'; +// External +import { vec3, mat4, quat } from 'wgpu-matrix'; +import { BLINN_PHONG } from '../materials/constants.js'; +class Rasterizer { + constructor(canvas) { + this.canvas = canvas !== null && canvas !== void 0 ? canvas : document.createElement('canvas'); + } + async init() { + // Get WebGPU device + if (!navigator.gpu) + throw Error('WebGPU is not supported in this browser.'); + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) + throw Error('Could not request WebGPU adapter.'); + const device = await adapter.requestDevice(); + if (!device) + throw Error('Could not request WebGPU logical device.'); + this.device = device; + this.setCanvasFormatAndContext(); + this.setDepthTexture(); + this.setRenderPassDescriptor(); + this.setBindGroup(); + this.setPipeline(); + } + render(scene, camera) { + // FIXME: Find a way to make sure that init is always called and thus this + // if statement redundant. + if (!this.device || + !this.depthTexture || + !this.renderPassDescriptor || + !this.viewProjectionMatrixBuffer || + !this.cameraPositionBuffer || + !this.context || + !this.pipeline) { + throw Error('Renderer has not been initiated. Call .init() first.'); + } + const canvasTexture = this.context.getCurrentTexture(); + // @ts-ignore + this.renderPassDescriptor.colorAttachments[0].view = + canvasTexture.createView(); + if (this.depthTexture.width !== canvasTexture.width || + this.depthTexture.height !== canvasTexture.height) { + this.depthTexture.destroy(); + this.depthTexture = this.device.createTexture({ + size: [canvasTexture.width, canvasTexture.height], + format: 'depth24plus', + usage: GPUTextureUsage.RENDER_ATTACHMENT, + }); + // @ts-ignore + this.renderPassDescriptor.depthStencilAttachment.view = + this.depthTexture.createView(); + } + if (scene.stats.outdated) { + scene.updateStats(); + } + const { vertexData, indexData, materialData, lightData } = this.getSceneData(scene); + // Write vertex and index data to GPU buffer + if (this.vertexBuffer) + this.vertexBuffer.destroy(); + this.vertexBuffer = this.device.createBuffer({ + label: 'Rasterizer vertex buffer', + size: vertexData.byteLength, + usage: GPUBufferUsage.VERTEX, + mappedAtCreation: true, + }); + new Float32Array(this.vertexBuffer.getMappedRange()).set(vertexData); + this.vertexBuffer.unmap(); + if (this.indexBuffer) + this.indexBuffer.destroy(); + this.indexBuffer = this.device.createBuffer({ + label: 'Rasterizer index buffer', + size: indexData.byteLength, + usage: GPUBufferUsage.INDEX, + mappedAtCreation: true, + }); + new Uint32Array(this.indexBuffer.getMappedRange()).set(indexData); + this.indexBuffer.unmap(); + // Create the camera uniform buffer (view projection matrix) + const transformedCameraPosition = vec3.transformMat4([0, 0, 0], mat4.translation(camera.localPosition)); + const viewMatrix = mat4.lookAt(transformedCameraPosition, vec3.create(0, 0, 0), UP); + const viewProjectionMatrix = mat4.multiply(camera.projectionMatrix, viewMatrix); + this.device.queue.writeBuffer(this.viewProjectionMatrixBuffer, 0, viewProjectionMatrix); + this.device.queue.writeBuffer(this.cameraPositionBuffer, 0, transformedCameraPosition); + // Create the material buffer + this.materialBuffer = this.device.createBuffer({ + label: 'Rasterizer material buffer', + size: materialData.byteLength, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, + }); + this.device.queue.writeBuffer(this.materialBuffer, 0, materialData); + // Create the light buffer + this.lightBuffer = this.device.createBuffer({ + label: 'Rasterizer light buffer', + size: lightData.byteLength, + usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, + }); + this.device.queue.writeBuffer(this.lightBuffer, 0, lightData); + this.bindGroup = this.device.createBindGroup({ + label: 'Rasterizer bind group', + layout: this.bindGroupLayout, + entries: [ + { + binding: 0, + resource: { buffer: this.viewProjectionMatrixBuffer }, + }, + { + binding: 1, + resource: { buffer: this.cameraPositionBuffer }, + }, + { + binding: 2, + resource: { buffer: this.materialBuffer }, + }, + { + binding: 3, + resource: { buffer: this.lightBuffer }, + }, + ], + }); + // Render pass + const encoder = this.device.createCommandEncoder(); + const pass = encoder.beginRenderPass(this.renderPassDescriptor); + pass.setPipeline(this.pipeline); + pass.setVertexBuffer(0, this.vertexBuffer); + pass.setIndexBuffer(this.indexBuffer, 'uint32'); + pass.setBindGroup(0, this.bindGroup); + pass.drawIndexed(indexData.length); + pass.end(); + this.device.queue.submit([encoder.finish()]); + } + getSceneData(scene) { + const numComponents = 9; // Position X, Y, Z, normal X, Y, Z, U & V, matIdx + const vertexData = new Float32Array(scene.stats.vertices * numComponents); + const indexData = new Float32Array(scene.stats.triangles * 3); + const materialData = new Float32Array(scene.stats.meshes * 8); + const lightData = new Float32Array(scene.stats.lights * 8); + let vertexDataOffset = 0; + let indexDataOffset = 0; + let materialDataOffset = 0; + let materialIndex = 0; + let lightDataOffset = 0; + let numVerticesProcessed = 0; + scene.traverse((group, globalPosition, globalRotation, globalScale) => { + const worldMatrix = mat4.translation(globalPosition); + const { angle, axis } = quat.toAxisAngle(globalRotation); + mat4.rotate(worldMatrix, axis, angle, worldMatrix); + mat4.scale(worldMatrix, globalScale, worldMatrix); + const worldMatrixInverseTranspose = mat4.invert(worldMatrix); + mat4.transpose(worldMatrixInverseTranspose, worldMatrixInverseTranspose); + if (group instanceof Mesh) { + const mesh = group; + // Material + let color = [0, 0, 0]; + let specular = [0, 0, 0]; + let shininess = 0; + if (mesh.material.type < 5) { + const coloredMaterial = mesh.material; + color = coloredMaterial.color; + } + if (mesh.material.type === BLINN_PHONG) { + const blinnPhongMaterial = mesh.material; + specular = blinnPhongMaterial.specular; + shininess = blinnPhongMaterial.shininess; + } + materialData[materialDataOffset++] = color[0]; + materialData[materialDataOffset++] = color[1]; + materialData[materialDataOffset++] = color[2]; + materialData[materialDataOffset++] = shininess; + materialData[materialDataOffset++] = specular[0]; + materialData[materialDataOffset++] = specular[1]; + materialData[materialDataOffset++] = specular[2]; + materialData[materialDataOffset++] = mesh.material.type; + // Vertices + mesh.geometry.forEachTriangle((_index, indices) => { + indexData[indexDataOffset++] = indices[0] + numVerticesProcessed; + indexData[indexDataOffset++] = indices[1] + numVerticesProcessed; + indexData[indexDataOffset++] = indices[2] + numVerticesProcessed; + }); + mesh.geometry.forEachVertex((_index, position, normal, uv) => { + const transformedPosition = vec3.transformMat4(position, worldMatrix); + const transformedNormal = vec3.transformMat4(normal, worldMatrixInverseTranspose); + vertexData[vertexDataOffset++] = transformedPosition[0]; + vertexData[vertexDataOffset++] = transformedPosition[1]; + vertexData[vertexDataOffset++] = transformedPosition[2]; + vertexData[vertexDataOffset++] = transformedNormal[0]; + vertexData[vertexDataOffset++] = transformedNormal[1]; + vertexData[vertexDataOffset++] = transformedNormal[2]; + vertexData[vertexDataOffset++] = uv[0]; + vertexData[vertexDataOffset++] = uv[1]; + vertexData[vertexDataOffset++] = materialIndex; + numVerticesProcessed++; + }); + materialIndex++; + } + // Light + if (group instanceof Light) { + const light = group; + const transformedLightPosition = vec3.transformMat4([0, 0, 0], worldMatrix); + lightData[lightDataOffset++] = transformedLightPosition[0]; // 0 + lightData[lightDataOffset++] = transformedLightPosition[1]; + lightData[lightDataOffset++] = transformedLightPosition[2]; + lightData[lightDataOffset++] = light.intensity; + lightData[lightDataOffset++] = light.color[0]; // 16 + lightData[lightDataOffset++] = light.color[1]; + lightData[lightDataOffset++] = light.color[2]; + lightData[lightDataOffset++] = light.type; + } + }); + return { vertexData, indexData, materialData, lightData }; + } + setCanvasFormatAndContext() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + this.context = this.canvas.getContext('webgpu'); + if (!this.context) { + throw new Error('WebGPU context not found.'); + } + this.format = navigator.gpu.getPreferredCanvasFormat(); + this.context.configure({ device: this.device, format: this.format }); + } + setDepthTexture() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + if (!this.context) { + throw new Error('Canvas context has not been set. Call .setCanvasFormatAndContext() first.'); + } + const canvasTexture = this.context.getCurrentTexture(); + this.depthTexture = this.device.createTexture({ + size: [canvasTexture.width, canvasTexture.height], + format: 'depth24plus', + usage: GPUTextureUsage.RENDER_ATTACHMENT, + }); + } + setRenderPassDescriptor() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + if (!this.context) { + throw new Error('Canvas context has not been set. Call .setCanvasFormatAndContext() first.'); + } + if (!this.depthTexture) { + throw new Error('Depth texture has not been set. Call .setDepthTexture() first.'); + } + const canvasTexture = this.context.getCurrentTexture(); + this.renderPassDescriptor = { + label: 'Rasterizer render pass descriptor', + colorAttachments: [ + { + view: canvasTexture.createView(), + loadOp: 'clear', + clearValue: [0, 0, 0, 1], + storeOp: 'store', + }, + ], + depthStencilAttachment: { + view: this.depthTexture.createView(), + depthClearValue: 1.0, + depthLoadOp: 'clear', + depthStoreOp: 'store', + }, + }; + } + setBindGroup() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + this.bindGroupLayout = this.device.createBindGroupLayout({ + label: 'Rasterizer bind group layout', + entries: [ + { + binding: 0, + visibility: GPUShaderStage.VERTEX, + buffer: { type: 'uniform' }, + }, + { + binding: 1, + visibility: GPUShaderStage.FRAGMENT, + buffer: { type: 'uniform' }, + }, + { + binding: 2, + visibility: GPUShaderStage.FRAGMENT, + buffer: { type: 'read-only-storage' }, + }, + { + binding: 3, + visibility: GPUShaderStage.FRAGMENT, + buffer: { type: 'read-only-storage' }, + }, + ], + }); + this.viewProjectionMatrixBuffer = this.device.createBuffer({ + label: 'Rasterizer view projection matrix buffer', + size: /*elements=*/ 16 * /*float32 size=*/ 4, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + this.cameraPositionBuffer = this.device.createBuffer({ + label: 'Rasterizer camera position buffer', + size: /*elements=*/ 3 * /*float32 size=*/ 4, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + } + setPipeline() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + if (!this.format) { + throw new Error('Canvas format has not been set. Call .setCanvasFormatAndContext() first.'); + } + if (!this.bindGroupLayout) { + throw new Error('Bind group layout has not been set. Call .setBindGroup() first.'); + } + const pipelineLayout = this.device.createPipelineLayout({ + label: 'Rasterizer pipeline layout', + bindGroupLayouts: [this.bindGroupLayout], + }); + const module = this.device.createShaderModule({ + code: solidColorShader + blinnPhongShader + rasterizerShader, + }); + this.pipeline = this.device.createRenderPipeline({ + label: 'Rasterizer pipeline', + layout: pipelineLayout, + vertex: { + module: module, + entryPoint: 'vertexMain', + buffers: [vertexBufferLayout], + }, + fragment: { + module: module, + entryPoint: 'fragmentMain', + targets: [ + { + format: this.format, + }, + ], + }, + primitive: { + topology: 'triangle-list', + frontFace: 'ccw', + cullMode: 'back', + }, + depthStencil: { + depthWriteEnabled: true, + depthCompare: 'less', + format: 'depth24plus', + }, + }); + } +} +export { Rasterizer }; +//# sourceMappingURL=Rasterizer.js.map \ No newline at end of file diff --git a/src/renderers/Rasterizer.js.map b/src/renderers/Rasterizer.js.map new file mode 100644 index 0000000..69d364a --- /dev/null +++ b/src/renderers/Rasterizer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Rasterizer.js","sourceRoot":"","sources":["Rasterizer.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/renderers/Rasterizer.ts b/src/renderers/Rasterizer.ts index 73fb661..6fb4ced 100644 --- a/src/renderers/Rasterizer.ts +++ b/src/renderers/Rasterizer.ts @@ -78,6 +78,7 @@ class Rasterizer implements Renderer { const canvasTexture = this.context.getCurrentTexture(); + // @ts-ignore this.renderPassDescriptor.colorAttachments[0].view = canvasTexture.createView(); @@ -93,6 +94,7 @@ class Rasterizer implements Renderer { usage: GPUTextureUsage.RENDER_ATTACHMENT, }); + // @ts-ignore this.renderPassDescriptor.depthStencilAttachment.view = this.depthTexture.createView(); } @@ -174,7 +176,7 @@ class Rasterizer implements Renderer { this.bindGroup = this.device.createBindGroup({ label: 'Rasterizer bind group', - layout: this.bindGroupLayout, + layout: this.bindGroupLayout as GPUBindGroupLayout, entries: [ { binding: 0, diff --git a/src/renderers/Raytracer.d.ts b/src/renderers/Raytracer.d.ts new file mode 100644 index 0000000..f74299a --- /dev/null +++ b/src/renderers/Raytracer.d.ts @@ -0,0 +1,40 @@ +import { PerspectiveCamera } from '../cameras/exports.js'; +import { Scene } from '../primitives/exports.js'; +import { Renderer } from './Renderer.js'; +declare class Raytracer implements Renderer { + readonly canvas: HTMLCanvasElement; + private device?; + private context?; + private format?; + private renderPassDescriptor?; + private bindGroupLayout?; + private bindGroup?; + private pipelineLayout?; + private computePipeline?; + private renderPipeline?; + private vertexData?; + private indexData?; + private materialData?; + private frameBuffer?; + private resolutionBuffer?; + private frameNumberBuffer?; + private cameraPositionBuffer?; + private viewportBuffer?; + private frameBufferViewVertexBuffer?; + private vertexBuffer?; + private indexBuffer?; + private materialBuffer?; + private lightBuffer?; + constructor(canvas?: HTMLCanvasElement); + init(): Promise; + render(scene: Scene, camera: PerspectiveCamera, frame?: number): void; + updateCanvas(): void; + private getSceneData; + private setCanvasFormatAndContext; + private setRenderPassDescriptor; + private setBindGroup; + private setVertexBuffer; + private setComputePipeline; + private setRenderPipeline; +} +export { Raytracer }; diff --git a/src/renderers/Raytracer.js b/src/renderers/Raytracer.js new file mode 100644 index 0000000..47ec93f --- /dev/null +++ b/src/renderers/Raytracer.js @@ -0,0 +1,505 @@ +import { Mesh } from '../primitives/exports.js'; +import { mat4, quat, vec3 } from 'wgpu-matrix'; +import { UP } from '../constants.js'; +import { BLINN_PHONG, METAL, } from '../materials/exports.js'; +import { Light } from '../lights/exports.js'; +// Shaders +import randomShader from './random.wgsl'; +import raytracerShader from './raytracer.wgsl'; +import frameBufferViewShader from './frame_buffer_view.wgsl'; +class Raytracer { + constructor(canvas) { + this.canvas = canvas !== null && canvas !== void 0 ? canvas : document.createElement('canvas'); + } + async init() { + // Get WebGPU device + if (!navigator.gpu) + throw Error('WebGPU is not supported in this browser.'); + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) + throw Error('Could not request WebGPU adapter.'); + const device = await adapter.requestDevice({ + requiredLimits: { + maxStorageBufferBindingSize: 536870912, // 512 MB + }, + }); + if (!device) + throw Error('Could not request WebGPU logical device.'); + this.device = device; + this.resolutionBuffer = this.device.createBuffer({ + label: 'Ray tracer frame dimensions buffer', + size: 2 * Uint32Array.BYTES_PER_ELEMENT, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + this.frameNumberBuffer = this.device.createBuffer({ + label: 'Ray tracer frame number buffer', + size: 4, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + this.cameraPositionBuffer = this.device.createBuffer({ + label: 'Ray tracer camera position buffer', + size: 3 * Float32Array.BYTES_PER_ELEMENT, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + this.viewportBuffer = this.device.createBuffer({ + label: 'Ray tracer viewport buffer', + size: (9 + 3) * Float32Array.BYTES_PER_ELEMENT, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + this.setCanvasFormatAndContext(); + this.setRenderPassDescriptor(); + this.setBindGroup(); + this.setVertexBuffer(); + this.setComputePipeline(); + this.setRenderPipeline(); + this.updateCanvas(); + } + render(scene, camera, frame = 0) { + if (!this.device || + !this.context || + !this.renderPassDescriptor || + !this.computePipeline || + !this.renderPipeline || + !this.frameBufferViewVertexBuffer || + !this.bindGroupLayout || + !this.frameNumberBuffer || + !this.cameraPositionBuffer || + !this.viewportBuffer) { + throw Error('Renderer has not been initiated. Call .init() first.'); + } + this.device.queue.writeBuffer(this.frameNumberBuffer, 0, new Uint32Array([frame])); + this.device.queue.writeBuffer(this.cameraPositionBuffer, 0, camera.localPosition // TODO: consider global position + ); + // Calculate viewport data + const lookAt = [0, 0, 0]; + const focalLength = vec3.length(vec3.subtract(camera.localPosition, lookAt)); + const h = Math.tan(camera.verticalFovRadians / 2); + const viewportHeight = 2 * h * focalLength; + const viewportWidth = viewportHeight * camera.aspectRatio; + // Opposite of camera direction + const w = vec3.normalize(vec3.subtract(camera.localPosition, lookAt)); + const u = vec3.normalize(vec3.cross(UP, w)); // Local right + const v = vec3.cross(w, u); // Local up + const viewportU = vec3.mulScalar(u, viewportWidth); + const viewportV = vec3.mulScalar(vec3.negate(v), viewportHeight); + const viewportDu = vec3.divScalar(viewportU, this.canvas.width); + const viewportDv = vec3.divScalar(viewportV, this.canvas.height); + const halfViewportU = vec3.divScalar(viewportU, 2); + const halfViewportV = vec3.divScalar(viewportV, 2); + // viewportUpperLeft = cameraPos - (w * focalLength) - U / 2 - V / 2 + const viewportUpperLeft = vec3.sub(vec3.sub(vec3.sub(camera.localPosition, vec3.mulScalar(w, focalLength)), halfViewportU), halfViewportV); + const pixelDuv = vec3.add(viewportDu, viewportDv); + const halfPixelDuv = vec3.mulScalar(pixelDuv, 0.5); + const viewportOrigin = vec3.add(viewportUpperLeft, halfPixelDuv); + const viewportData = new Float32Array(9 + 3); + viewportData.set(viewportOrigin, 0); + viewportData.set(viewportDu, 4); + viewportData.set(viewportDv, 8); + this.device.queue.writeBuffer(this.viewportBuffer, 0, viewportData); + const canvasTexture = this.context.getCurrentTexture(); + // @ts-ignore + this.renderPassDescriptor.colorAttachments[0].view = + canvasTexture.createView(); + if (!this.vertexData || + !this.indexData || + !this.materialData || + scene.stats.outdated) { + const { vertexData, indexData, materialData } = this.getSceneData(scene); + this.vertexData = vertexData; + this.indexData = indexData; + this.materialData = materialData; + if (this.vertexBuffer) + this.vertexBuffer.destroy(); + this.vertexBuffer = this.device.createBuffer({ + label: 'Ray tracer vertex buffer', + size: this.vertexData.byteLength, + usage: GPUBufferUsage.STORAGE, + mappedAtCreation: true, + }); + new Float32Array(this.vertexBuffer.getMappedRange()).set(this.vertexData); + this.vertexBuffer.unmap(); + if (this.indexBuffer) + this.indexBuffer.destroy(); + this.indexBuffer = this.device.createBuffer({ + label: 'Ray tracer index buffer', + size: this.indexData.byteLength, + usage: GPUBufferUsage.STORAGE, + mappedAtCreation: true, + }); + new Uint32Array(this.indexBuffer.getMappedRange()).set(this.indexData); + this.indexBuffer.unmap(); + if (this.materialBuffer) + this.materialBuffer.destroy(); + this.materialBuffer = this.device.createBuffer({ + label: 'Ray tracer material buffer', + size: this.materialData.byteLength, + usage: GPUBufferUsage.STORAGE, + mappedAtCreation: true, + }); + new Float32Array(this.materialBuffer.getMappedRange()).set(this.materialData); + this.materialBuffer.unmap(); + } + this.bindGroup = this.device.createBindGroup({ + label: 'Ray tracer bind group', + layout: this.bindGroupLayout, + entries: [ + { + binding: 0, + resource: { buffer: this.resolutionBuffer }, + }, + { + binding: 1, + resource: { buffer: this.frameBuffer }, + }, + { + binding: 2, + resource: { buffer: this.frameNumberBuffer }, + }, + { + binding: 3, + resource: { buffer: this.cameraPositionBuffer }, + }, + { + binding: 4, + resource: { buffer: this.viewportBuffer }, + }, + { + binding: 5, + resource: { buffer: this.vertexBuffer }, + }, + { + binding: 6, + resource: { buffer: this.indexBuffer }, + }, + { + binding: 7, + resource: { buffer: this.materialBuffer }, + }, + ], + }); + const encoder = this.device.createCommandEncoder(); + const computePass = encoder.beginComputePass(); + computePass.setPipeline(this.computePipeline); + computePass.setBindGroup(0, this.bindGroup); + const workgroupCountX = Math.ceil(this.canvas.width / 8); + const workgroupCountY = Math.ceil(this.canvas.height / 8); + computePass.dispatchWorkgroups(workgroupCountX, workgroupCountY); + computePass.end(); + const renderPass = encoder.beginRenderPass(this.renderPassDescriptor); + renderPass.setPipeline(this.renderPipeline); + renderPass.setVertexBuffer(0, this.frameBufferViewVertexBuffer); + renderPass.setBindGroup(0, this.bindGroup); + renderPass.draw(6); + renderPass.end(); + this.device.queue.submit([encoder.finish()]); + } + updateCanvas() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + if (!this.resolutionBuffer) { + throw new Error('Frame dimensions buffer has not been created.'); + } + if (this.frameBuffer) { + this.frameBuffer.destroy(); + } + this.frameBuffer = this.device.createBuffer({ + label: 'Ray tracer frame buffer', + size: 4 * + Float32Array.BYTES_PER_ELEMENT * + this.canvas.width * + this.canvas.height, + usage: GPUBufferUsage.STORAGE, + }); + // Update the frame dimensions buffer + this.device.queue.writeBuffer(this.resolutionBuffer, 0, new Uint32Array([this.canvas.width, this.canvas.height])); + } + getSceneData(scene) { + if (scene.stats.outdated) { + scene.updateStats(); + } + const vertexData = new Float32Array(scene.stats.vertices * 12); + const indexData = new Uint32Array(scene.stats.triangles * 4); + const materialData = new Float32Array(scene.stats.meshes * 8); + const lightData = new Float32Array(scene.stats.lights * 8); + let vertexDataOffset = 0; + let indexDataOffset = 0; + let materialDataOffset = 0; + let materialIndex = 0; + let lightDataOffset = 0; + let numVerticesProcessed = 0; + scene.traverse((group, globalPosition, globalRotation, globalScale) => { + const worldMatrix = mat4.translation(globalPosition); + const { angle, axis } = quat.toAxisAngle(globalRotation); + mat4.rotate(worldMatrix, axis, angle, worldMatrix); + mat4.scale(worldMatrix, globalScale, worldMatrix); + const worldMatrixInverseTranspose = mat4.invert(worldMatrix); + mat4.transpose(worldMatrixInverseTranspose, worldMatrixInverseTranspose); + if (group instanceof Mesh) { + const mesh = group; + // Material + let color = [0, 0, 0]; + let specular = [0, 0, 0]; + let shininess = 0; + if (mesh.material.type < 5) { + const coloredMaterial = mesh.material; + color = coloredMaterial.color; + } + if (mesh.material.type === BLINN_PHONG) { + const blinnPhongMaterial = mesh.material; + specular = blinnPhongMaterial.specular; + shininess = blinnPhongMaterial.shininess; + } + if (mesh.material.type === METAL) { + const metalMaterial = mesh.material; + shininess = metalMaterial.fuzziness; + } + materialData[materialDataOffset++] = color[0]; + materialData[materialDataOffset++] = color[1]; + materialData[materialDataOffset++] = color[2]; + materialData[materialDataOffset++] = shininess; + materialData[materialDataOffset++] = specular[0]; + materialData[materialDataOffset++] = specular[1]; + materialData[materialDataOffset++] = specular[2]; + materialData[materialDataOffset++] = mesh.material.type; + // Vertices + mesh.geometry.forEachTriangle((_index, indices) => { + indexData[indexDataOffset++] = indices[0] + numVerticesProcessed; + indexData[indexDataOffset++] = indices[1] + numVerticesProcessed; + indexData[indexDataOffset++] = indices[2] + numVerticesProcessed; + indexData[indexDataOffset++] = 0; // Pad + }); + mesh.geometry.forEachVertex((_index, position, normal, uv) => { + const transformedPosition = vec3.transformMat4(position, worldMatrix); + const transformedNormal = vec3.transformMat4(normal, worldMatrixInverseTranspose); + vertexData[vertexDataOffset++] = transformedPosition[0]; + vertexData[vertexDataOffset++] = transformedPosition[1]; + vertexData[vertexDataOffset++] = transformedPosition[2]; + vertexData[vertexDataOffset++] = 0; // Pad + vertexData[vertexDataOffset++] = transformedNormal[0]; + vertexData[vertexDataOffset++] = transformedNormal[1]; + vertexData[vertexDataOffset++] = transformedNormal[2]; + vertexData[vertexDataOffset++] = 0; // Pad + vertexData[vertexDataOffset++] = uv[0]; + vertexData[vertexDataOffset++] = uv[1]; + vertexData[vertexDataOffset++] = materialIndex; + vertexData[vertexDataOffset++] = 0; // Pad + numVerticesProcessed++; + }); + materialIndex++; + } + // Light + if (group instanceof Light) { + const light = group; + const transformedLightPosition = vec3.transformMat4([0, 0, 0], worldMatrix); + lightData[lightDataOffset++] = transformedLightPosition[0]; // 0 + lightData[lightDataOffset++] = transformedLightPosition[1]; + lightData[lightDataOffset++] = transformedLightPosition[2]; + lightData[lightDataOffset++] = light.intensity; + lightData[lightDataOffset++] = light.color[0]; // 16 + lightData[lightDataOffset++] = light.color[1]; + lightData[lightDataOffset++] = light.color[2]; + lightData[lightDataOffset++] = light.type; + } + }); + return { vertexData, indexData, materialData, lightData }; + } + setCanvasFormatAndContext() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + this.context = this.canvas.getContext('webgpu'); + if (!this.context) { + throw new Error('WebGPU context not found.'); + } + this.format = navigator.gpu.getPreferredCanvasFormat(); + this.context.configure({ device: this.device, format: this.format }); + } + setRenderPassDescriptor() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + if (!this.context) { + throw new Error('Canvas context has not been set. Call .setCanvasFormatAndContext() first.'); + } + const canvasTexture = this.context.getCurrentTexture(); + this.renderPassDescriptor = { + label: 'Rasterizer render pass descriptor', + colorAttachments: [ + { + view: canvasTexture.createView(), + loadOp: 'clear', + clearValue: [0, 0, 0, 1], + storeOp: 'store', + }, + ], + }; + } + setBindGroup() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + this.bindGroupLayout = this.device.createBindGroupLayout({ + label: 'Rasterizer bind group layout', + entries: [ + { + // Frame dimensions + binding: 0, + visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT, + buffer: { type: 'uniform' }, + }, + { + // Frame buffer + binding: 1, + visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT, + buffer: { type: 'storage' }, + }, + { + // Frame + binding: 2, + visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT, + buffer: { type: 'uniform' }, + }, + { + // Camera position + binding: 3, + visibility: GPUShaderStage.COMPUTE, + buffer: { type: 'uniform' }, + }, + { + // Viewport + binding: 4, + visibility: GPUShaderStage.COMPUTE, + buffer: { type: 'uniform' }, + }, + { + // Vertices + binding: 5, + visibility: GPUShaderStage.COMPUTE, + buffer: { type: 'read-only-storage' }, + }, + { + // Faces + binding: 6, + visibility: GPUShaderStage.COMPUTE, + buffer: { type: 'read-only-storage' }, + }, + { + // Materials + binding: 7, + visibility: GPUShaderStage.COMPUTE, + buffer: { type: 'read-only-storage' }, + }, + ], + }); + } + setVertexBuffer() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + // v0-------v1 Y (0, 0)---> U + // | | ^ | + // | | | v + // v3-------v2 (-1, -1)--->X V + // prettier-ignore + const vertexData = new Float32Array([ + // X Y U V + -1, -1, 0, 1, // v3 + 1, -1, 1, 1, // v2 + -1, 1, 0, 0, // v0 + -1, 1, 0, 0, // v0 + 1, -1, 1, 1, // v2 + 1, 1, 1, 0, // v1 + ]); + this.frameBufferViewVertexBuffer = this.device.createBuffer({ + label: 'Ray tracer vertex buffer', + size: vertexData.byteLength, + usage: GPUBufferUsage.VERTEX, + mappedAtCreation: true, + }); + new Float32Array(this.frameBufferViewVertexBuffer.getMappedRange()).set(vertexData); + this.frameBufferViewVertexBuffer.unmap(); + } + setComputePipeline() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + if (!this.bindGroupLayout) { + throw new Error('Bind group layout has not been set. Call .setBindGroup() first.'); + } + this.pipelineLayout = this.device.createPipelineLayout({ + label: 'Rasterizer pipeline layout', + bindGroupLayouts: [this.bindGroupLayout], + }); + this.computePipeline = this.device.createComputePipeline({ + label: 'Ray tracer compute pipeline', + layout: this.pipelineLayout, + compute: { + module: this.device.createShaderModule({ + label: 'Ray tracer shader module', + code: randomShader + raytracerShader, + }), + entryPoint: 'computeMain', + }, + }); + } + setRenderPipeline() { + if (!this.device) { + throw new Error('GPU device has not been set.'); + } + if (!this.format) { + throw new Error('Canvas format has not been set. Call .setCanvasFormatAndContext() first.'); + } + if (!this.bindGroupLayout) { + throw new Error('Bind group layout has not been set. Call .setBindGroup() first.'); + } + if (!this.pipelineLayout) { + throw new Error('Pipeline layout has not been set. Call .setComputePipeline() first.'); + } + const vertexBufferLayout = { + arrayStride: 4 * 4, + attributes: [ + { + // position + format: 'float32x2', + offset: 0, + shaderLocation: 1, + }, + { + // uv + format: 'float32x2', + offset: 8, + shaderLocation: 2, + }, + ], + }; + const module = this.device.createShaderModule({ + code: frameBufferViewShader, + }); + this.renderPipeline = this.device.createRenderPipeline({ + label: 'Rasterizer pipeline', + layout: this.pipelineLayout, + vertex: { + module: module, + entryPoint: 'vertexMain', + buffers: [vertexBufferLayout], + }, + fragment: { + module: module, + entryPoint: 'fragmentMain', + targets: [ + { + format: this.format, + }, + ], + }, + primitive: { + topology: 'triangle-list', + frontFace: 'ccw', + cullMode: 'back', + }, + }); + } +} +export { Raytracer }; +//# sourceMappingURL=Raytracer.js.map \ No newline at end of file diff --git a/src/renderers/Raytracer.js.map b/src/renderers/Raytracer.js.map new file mode 100644 index 0000000..2ac3a57 --- /dev/null +++ b/src/renderers/Raytracer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Raytracer.js","sourceRoot":"","sources":["Raytracer.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/renderers/Raytracer.ts b/src/renderers/Raytracer.ts index fdf2cf8..be434d0 100644 --- a/src/renderers/Raytracer.ts +++ b/src/renderers/Raytracer.ts @@ -178,6 +178,7 @@ class Raytracer implements Renderer { const canvasTexture = this.context.getCurrentTexture(); + // @ts-ignore this.renderPassDescriptor.colorAttachments[0].view = canvasTexture.createView(); @@ -232,11 +233,11 @@ class Raytracer implements Renderer { entries: [ { binding: 0, - resource: {buffer: this.resolutionBuffer}, + resource: {buffer: this.resolutionBuffer as GPUBuffer}, }, { binding: 1, - resource: {buffer: this.frameBuffer}, + resource: {buffer: this.frameBuffer as GPUBuffer}, }, { binding: 2, @@ -252,15 +253,15 @@ class Raytracer implements Renderer { }, { binding: 5, - resource: {buffer: this.vertexBuffer}, + resource: {buffer: this.vertexBuffer as GPUBuffer}, }, { binding: 6, - resource: {buffer: this.indexBuffer}, + resource: {buffer: this.indexBuffer as GPUBuffer}, }, { binding: 7, - resource: {buffer: this.materialBuffer}, + resource: {buffer: this.materialBuffer as GPUBuffer}, }, ], }); diff --git a/src/renderers/Renderer.d.ts b/src/renderers/Renderer.d.ts new file mode 100644 index 0000000..1533f81 --- /dev/null +++ b/src/renderers/Renderer.d.ts @@ -0,0 +1,6 @@ +import { Scene } from '../primitives/Scene.js'; +import { PerspectiveCamera } from '../cameras/PerspectiveCamera.js'; +interface Renderer { + render(scene: Scene, camera: PerspectiveCamera): void; +} +export { Renderer }; diff --git a/src/renderers/Renderer.js b/src/renderers/Renderer.js new file mode 100644 index 0000000..8071930 --- /dev/null +++ b/src/renderers/Renderer.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=Renderer.js.map \ No newline at end of file diff --git a/src/renderers/Renderer.js.map b/src/renderers/Renderer.js.map new file mode 100644 index 0000000..5cc7c45 --- /dev/null +++ b/src/renderers/Renderer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Renderer.js","sourceRoot":"","sources":["Renderer.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/src/renderers/constants.d.ts b/src/renderers/constants.d.ts new file mode 100644 index 0000000..b87f9ca --- /dev/null +++ b/src/renderers/constants.d.ts @@ -0,0 +1,3 @@ +/// +declare const vertexBufferLayout: GPUVertexBufferLayout; +export { vertexBufferLayout }; diff --git a/src/renderers/constants.js b/src/renderers/constants.js new file mode 100644 index 0000000..34356bd --- /dev/null +++ b/src/renderers/constants.js @@ -0,0 +1,39 @@ +// The vertex buffer layout +// +// Data: | Position X| Position Y| Position Z| +// Bytes: | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|… +// | Normal X| Normal Y| Normal Z| +// |12|13|14|15|16|17|18|19|20|21|22|23|… +// | U| V|MaterialIdx| +// |24|25|26|27|28|29|30|31|32|33|34|35| +const vertexBufferLayout = { + arrayStride: 9 * 4, + attributes: [ + { + // position + format: 'float32x3', + offset: 0, + shaderLocation: 1, + }, + { + // vertex normals + format: 'float32x3', + offset: 12, + shaderLocation: 2, + }, + { + // UV + format: 'float32x2', + offset: 24, + shaderLocation: 3, + }, + { + // material index + format: 'float32', + offset: 32, + shaderLocation: 4, + }, + ], +}; +export { vertexBufferLayout }; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/src/renderers/constants.js.map b/src/renderers/constants.js.map new file mode 100644 index 0000000..c57893e --- /dev/null +++ b/src/renderers/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["constants.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,EAAE;AACF,+CAA+C;AAC/C,gDAAgD;AAChD,+CAA+C;AAC/C,gDAAgD;AAChD,+CAA+C;AAC/C,+CAA+C;AAC/C,MAAM,kBAAkB,GAA0B;IAChD,WAAW,EAAE,CAAC,GAAG,CAAC;IAClB,UAAU,EAAE;QACV;YACE,WAAW;YACX,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE,CAAC;YACT,cAAc,EAAE,CAAC;SAClB;QACD;YACE,iBAAiB;YACjB,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE,EAAE;YACV,cAAc,EAAE,CAAC;SAClB;QACD;YACE,KAAK;YACL,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE,EAAE;YACV,cAAc,EAAE,CAAC;SAClB;QACD;YACE,iBAAiB;YACjB,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,EAAE;YACV,cAAc,EAAE,CAAC;SAClB;KACF;CACF,CAAC;AAEF,OAAO,EAAC,kBAAkB,EAAC,CAAC"} \ No newline at end of file diff --git a/src/renderers/exports.d.ts b/src/renderers/exports.d.ts new file mode 100644 index 0000000..812481d --- /dev/null +++ b/src/renderers/exports.d.ts @@ -0,0 +1,2 @@ +export { Rasterizer } from './Rasterizer.js'; +export { Raytracer } from './Raytracer.js'; diff --git a/src/renderers/exports.js b/src/renderers/exports.js new file mode 100644 index 0000000..8aab77b --- /dev/null +++ b/src/renderers/exports.js @@ -0,0 +1,3 @@ +export { Rasterizer } from './Rasterizer.js'; +export { Raytracer } from './Raytracer.js'; +//# sourceMappingURL=exports.js.map \ No newline at end of file diff --git a/src/renderers/exports.js.map b/src/renderers/exports.js.map new file mode 100644 index 0000000..1b4e07b --- /dev/null +++ b/src/renderers/exports.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exports.js","sourceRoot":"","sources":["exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC"} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 1b42156..2cb8f51 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,7 @@ "rootDir": ".", "types": ["@webgpu/types"], "noImplicitOverride": true, + "skipLibCheck": true }, "include": ["src/**/*.ts", "test/**/*.ts", "examples/**/*.ts"] }