Update readme, example project, fix runtime errors
This commit is contained in:
parent
fdf4e1b870
commit
33c4c674bc
@ -1,2 +1,9 @@
|
|||||||
# oktaeder
|
# oktaeder
|
||||||
3D rendering library for WebGPU
|
3D rendering library for WebGPU
|
||||||
|
|
||||||
|
This project uses [pnpm](https://pnpm.io/). If you don't have it, you can get it
|
||||||
|
using npm by running `npm install -g pnpm`. Then, run `pnpm install` to install
|
||||||
|
all dependencies.
|
||||||
|
|
||||||
|
To run the example, run `pnpm start:example` and visit
|
||||||
|
[localhost:8000](http://localhost:8000).
|
||||||
|
11
example/index.html
Normal file
11
example/index.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>oktaeder example</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="bundle.css">
|
||||||
|
<script type="module" src="bundle.js"></script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
102
example/script.ts
Normal file
102
example/script.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { Color, Material, Mesh, Node, PerspectiveCamera, PointLight, Quaternion, Scene, Submesh, Vector3 } from "../src/data/index";
|
||||||
|
import { Renderer } from "../src/oktaeder";
|
||||||
|
import "./style.css";
|
||||||
|
|
||||||
|
new EventSource("/esbuild").addEventListener("change", () => location.reload());
|
||||||
|
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
window.addEventListener("resize", onResize);
|
||||||
|
onResize.call(window);
|
||||||
|
|
||||||
|
const renderer = await Renderer.init(canvas);
|
||||||
|
|
||||||
|
const camera = new PerspectiveCamera({
|
||||||
|
verticalFovRad: 50 * (Math.PI / 180),
|
||||||
|
nearPlane: 0.001,
|
||||||
|
farPlane: Infinity,
|
||||||
|
});
|
||||||
|
|
||||||
|
const vertexBuffer = renderer.createVertexBuffer({ vertexCount: 6 });
|
||||||
|
vertexBuffer.writeTypedArray(0, {
|
||||||
|
position: new Float32Array([
|
||||||
|
-1, 0, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
0, -1, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, -1,
|
||||||
|
0, 0, 1,
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
|
||||||
|
const indexBuffer = renderer.createIndexBuffer({ indexCount: 24, indexFormat: "uint16" });
|
||||||
|
indexBuffer.writeArray(0, [
|
||||||
|
0, 4, 3,
|
||||||
|
4, 1, 3,
|
||||||
|
1, 5, 3,
|
||||||
|
5, 0, 3,
|
||||||
|
4, 0, 2,
|
||||||
|
1, 4, 2,
|
||||||
|
5, 1, 2,
|
||||||
|
0, 5, 2,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const submesh: Submesh = { start: 0, length: 24 };
|
||||||
|
|
||||||
|
const mesh = new Mesh({ vertexBuffer, indexBuffer, submeshes: [submesh] });
|
||||||
|
|
||||||
|
const material = new Material({
|
||||||
|
baseColor: Color.white(),
|
||||||
|
roughness: 0.5,
|
||||||
|
metallic: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const node = new Node({ mesh, materials: [material] });
|
||||||
|
|
||||||
|
const cameraPitchRad = 15 * (Math.PI / 180);
|
||||||
|
const scene = new Scene({
|
||||||
|
nodes: [
|
||||||
|
node,
|
||||||
|
new Node({
|
||||||
|
translation: new Vector3(-1, 1, 0),
|
||||||
|
light: new PointLight({ color: new Color(1, 0, 0) }),
|
||||||
|
}),
|
||||||
|
new Node({
|
||||||
|
translation: new Vector3(0, 1, -1),
|
||||||
|
light: new PointLight({ color: new Color(0, 1, 0) }),
|
||||||
|
}),
|
||||||
|
new Node({
|
||||||
|
translation: new Vector3(1, 1, 0),
|
||||||
|
light: new PointLight({ color: new Color(0, 0, 1) }),
|
||||||
|
}),
|
||||||
|
new Node({
|
||||||
|
translation: new Vector3(0, 1, 1),
|
||||||
|
light: new PointLight({ color: new Color(1, 1, 0) }),
|
||||||
|
}),
|
||||||
|
new Node({
|
||||||
|
translation: new Vector3(0, 0.8, -3),
|
||||||
|
rotation: new Quaternion(Math.sin(0.5 * cameraPitchRad), 0, 0, Math.cos(0.5 * cameraPitchRad)),
|
||||||
|
camera,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
ambientLight: new Color(0.01, 0.01, 0.01),
|
||||||
|
});
|
||||||
|
|
||||||
|
function onResize(this: Window) {
|
||||||
|
canvas.width = this.innerWidth;
|
||||||
|
canvas.height = this.innerHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rotation = Quaternion.identity();
|
||||||
|
|
||||||
|
function draw(time: number) {
|
||||||
|
rotation.y = Math.cos(0.001 * time);
|
||||||
|
rotation.w = Math.sin(0.001 * time);
|
||||||
|
node.setRotation(rotation);
|
||||||
|
|
||||||
|
renderer.render(scene, camera);
|
||||||
|
requestAnimationFrame(draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(draw);
|
||||||
|
|
||||||
|
document.body.appendChild(canvas);
|
10
example/style.css
Normal file
10
example/style.css
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body, canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
@ -18,6 +18,7 @@
|
|||||||
"url": "https://github.com/iszn11/oktaeder.git"
|
"url": "https://github.com/iszn11/oktaeder.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"start:example": "esbuild example/script.ts --bundle --outfile=example/bundle.js --watch --servedir=example --format=esm --sourcemap",
|
||||||
"build": "tsc --build"
|
"build": "tsc --build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -25,6 +26,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@webgpu/types": "^0.1.34",
|
"@webgpu/types": "^0.1.34",
|
||||||
|
"esbuild": "^0.19.2",
|
||||||
"typescript": "5.1.6"
|
"typescript": "5.1.6"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
|
231
pnpm-lock.yaml
generated
231
pnpm-lock.yaml
generated
@ -13,16 +13,247 @@ devDependencies:
|
|||||||
'@webgpu/types':
|
'@webgpu/types':
|
||||||
specifier: ^0.1.34
|
specifier: ^0.1.34
|
||||||
version: 0.1.34
|
version: 0.1.34
|
||||||
|
esbuild:
|
||||||
|
specifier: ^0.19.2
|
||||||
|
version: 0.19.2
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.1.6
|
specifier: 5.1.6
|
||||||
version: 5.1.6
|
version: 5.1.6
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
|
/@esbuild/android-arm64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/android-arm@0.19.2:
|
||||||
|
resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/android-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/darwin-arm64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/darwin-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/freebsd-arm64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [freebsd]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/freebsd-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-arm64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-arm@0.19.2:
|
||||||
|
resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-ia32@0.19.2:
|
||||||
|
resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-loong64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [loong64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-mips64el@0.19.2:
|
||||||
|
resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [mips64el]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-ppc64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [ppc64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-riscv64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-s390x@0.19.2:
|
||||||
|
resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [s390x]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/linux-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/netbsd-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [netbsd]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/openbsd-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [openbsd]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/sunos-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [sunos]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/win32-arm64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/win32-ia32@0.19.2:
|
||||||
|
resolution: {integrity: sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@esbuild/win32-x64@0.19.2:
|
||||||
|
resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
/@webgpu/types@0.1.34:
|
/@webgpu/types@0.1.34:
|
||||||
resolution: {integrity: sha512-9mXtH+CC8q+Ku7Z+1XazNIte81FvfdXwR2lLRO7Ykzjd/hh1J1krJa0gtnkF1kvP11psUmKEPKo7iMTeEcUpNA==}
|
resolution: {integrity: sha512-9mXtH+CC8q+Ku7Z+1XazNIte81FvfdXwR2lLRO7Ykzjd/hh1J1krJa0gtnkF1kvP11psUmKEPKo7iMTeEcUpNA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/esbuild@0.19.2:
|
||||||
|
resolution: {integrity: sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
|
optionalDependencies:
|
||||||
|
'@esbuild/android-arm': 0.19.2
|
||||||
|
'@esbuild/android-arm64': 0.19.2
|
||||||
|
'@esbuild/android-x64': 0.19.2
|
||||||
|
'@esbuild/darwin-arm64': 0.19.2
|
||||||
|
'@esbuild/darwin-x64': 0.19.2
|
||||||
|
'@esbuild/freebsd-arm64': 0.19.2
|
||||||
|
'@esbuild/freebsd-x64': 0.19.2
|
||||||
|
'@esbuild/linux-arm': 0.19.2
|
||||||
|
'@esbuild/linux-arm64': 0.19.2
|
||||||
|
'@esbuild/linux-ia32': 0.19.2
|
||||||
|
'@esbuild/linux-loong64': 0.19.2
|
||||||
|
'@esbuild/linux-mips64el': 0.19.2
|
||||||
|
'@esbuild/linux-ppc64': 0.19.2
|
||||||
|
'@esbuild/linux-riscv64': 0.19.2
|
||||||
|
'@esbuild/linux-s390x': 0.19.2
|
||||||
|
'@esbuild/linux-x64': 0.19.2
|
||||||
|
'@esbuild/netbsd-x64': 0.19.2
|
||||||
|
'@esbuild/openbsd-x64': 0.19.2
|
||||||
|
'@esbuild/sunos-x64': 0.19.2
|
||||||
|
'@esbuild/win32-arm64': 0.19.2
|
||||||
|
'@esbuild/win32-ia32': 0.19.2
|
||||||
|
'@esbuild/win32-x64': 0.19.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tslib@2.6.1:
|
/tslib@2.6.1:
|
||||||
resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==}
|
resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -53,18 +53,20 @@ export class _BinaryWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensureUnusedCapacity(desiredUnusedCapacity: number): _BinaryWriter {
|
ensureUnusedCapacity(desiredUnusedCapacity: number): _BinaryWriter {
|
||||||
return this.ensureCapacity(this._buffer.byteLength + desiredUnusedCapacity);
|
return this.ensureCapacity(this._length + desiredUnusedCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeU32(value: number): _BinaryWriter {
|
writeU32(value: number): _BinaryWriter {
|
||||||
this.ensureUnusedCapacity(4);
|
this.ensureUnusedCapacity(4);
|
||||||
this._dataView.setUint32(this._length, value, true);
|
this._dataView.setUint32(this._length, value, true);
|
||||||
|
this._length += 4;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeF32(value: number): _BinaryWriter {
|
writeF32(value: number): _BinaryWriter {
|
||||||
this.ensureUnusedCapacity(4);
|
this.ensureUnusedCapacity(4);
|
||||||
this._dataView.setFloat32(this._length, value, true);
|
this._dataView.setFloat32(this._length, value, true);
|
||||||
|
this._length += 4;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +118,19 @@ export class _BinaryWriter {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
padToAlign(alignment: number): _BinaryWriter {
|
||||||
|
const alignedLength = (this._length + alignment - 1) & ~(alignment - 1);
|
||||||
|
const padding = alignedLength - this._length;
|
||||||
|
if (padding === 0) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ensureUnusedCapacity(padding);
|
||||||
|
this._typedArray.fill(0, this._length, alignedLength);
|
||||||
|
this._length = alignedLength;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
alloc(byteLength: number): DataView {
|
alloc(byteLength: number): DataView {
|
||||||
this.ensureUnusedCapacity(byteLength);
|
this.ensureUnusedCapacity(byteLength);
|
||||||
const dataView = new DataView(this._buffer, this._length, byteLength);
|
const dataView = new DataView(this._buffer, this._length, byteLength);
|
||||||
|
@ -26,7 +26,7 @@ export interface PerspectiveCameraProps {
|
|||||||
|
|
||||||
export class OrthographicCamera {
|
export class OrthographicCamera {
|
||||||
|
|
||||||
readonly type!: "OrthographicCamera";
|
declare readonly type: "OrthographicCamera";
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ export class OrthographicCamera {
|
|||||||
|
|
||||||
export class PerspectiveCamera {
|
export class PerspectiveCamera {
|
||||||
|
|
||||||
readonly type!: "PerspectiveCamera";
|
declare readonly type: "PerspectiveCamera";
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ export type ColorTuple = readonly [r: number, g: number, b: number];
|
|||||||
|
|
||||||
export class Color {
|
export class Color {
|
||||||
|
|
||||||
readonly type!: "Color";
|
declare readonly type: "Color";
|
||||||
|
|
||||||
r: number;
|
r: number;
|
||||||
g: number;
|
g: number;
|
||||||
|
@ -22,7 +22,7 @@ export interface PointLightProps {
|
|||||||
|
|
||||||
export class DirectionalLight {
|
export class DirectionalLight {
|
||||||
|
|
||||||
readonly type!: "DirectionalLight";
|
get type(): "DirectionalLight" {};
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ export class DirectionalLight {
|
|||||||
|
|
||||||
export class PointLight {
|
export class PointLight {
|
||||||
|
|
||||||
readonly type!: "PointLight";
|
declare readonly type: "PointLight";
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ export interface MaterialProps {
|
|||||||
|
|
||||||
export class Material {
|
export class Material {
|
||||||
|
|
||||||
readonly type!: "Material";
|
declare readonly type: "Material";
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ export type Matrix4x4Tuple = readonly [
|
|||||||
|
|
||||||
export class Matrix4x4 {
|
export class Matrix4x4 {
|
||||||
|
|
||||||
readonly type!: "Matrix4x4";
|
declare readonly type: "Matrix4x4";
|
||||||
|
|
||||||
ix: number;
|
ix: number;
|
||||||
iy: number;
|
iy: number;
|
||||||
|
@ -23,7 +23,7 @@ export interface NodeProps {
|
|||||||
|
|
||||||
export class Node {
|
export class Node {
|
||||||
|
|
||||||
readonly type!: "Node";
|
declare readonly type: "Node";
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export type QuaternionTuple = readonly [x: number, y: number, z: number, w: numb
|
|||||||
|
|
||||||
export class Quaternion {
|
export class Quaternion {
|
||||||
|
|
||||||
readonly type!: "Quaternion";
|
declare readonly type: "Quaternion";
|
||||||
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
@ -16,7 +16,7 @@ export interface SceneProps {
|
|||||||
|
|
||||||
export class Scene {
|
export class Scene {
|
||||||
|
|
||||||
readonly type!: "Scene";
|
declare readonly type: "Scene";
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export type Vector2Tuple = readonly [x: number, y: number];
|
|||||||
|
|
||||||
export class Vector2 {
|
export class Vector2 {
|
||||||
|
|
||||||
readonly type!: "Vector2";
|
declare readonly type: "Vector2";
|
||||||
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
@ -14,7 +14,7 @@ export type Vector3Tuple = readonly [x: number, y: number, z: number];
|
|||||||
|
|
||||||
export class Vector3 {
|
export class Vector3 {
|
||||||
|
|
||||||
readonly type!: "Vector3";
|
declare readonly type: "Vector3";
|
||||||
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
@ -15,7 +15,7 @@ export type Vector4Tuple = readonly [x: number, y: number, z: number, w: number]
|
|||||||
|
|
||||||
export class Vector4 {
|
export class Vector4 {
|
||||||
|
|
||||||
readonly type!: "Vector4";
|
declare readonly type: "Vector4";
|
||||||
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
@ -11,7 +11,7 @@ import { _BinaryWriter as BinaryWriter } from "./_BinaryWriter";
|
|||||||
import { _Mapping as Mapping } from "./_Mapping";
|
import { _Mapping as Mapping } from "./_Mapping";
|
||||||
import { Camera, Material, Matrix4x4, Node, Scene, Vector3, isDirectionalLight, isPointLight, preOrder } from "./data";
|
import { Camera, Material, Matrix4x4, Node, Scene, Vector3, isDirectionalLight, isPointLight, preOrder } from "./data";
|
||||||
import { IndexBuffer, IndexBufferProps, Texture2D, Texture2DProps, VertexBuffer, VertexBufferProps } from "./resources";
|
import { IndexBuffer, IndexBufferProps, Texture2D, Texture2DProps, VertexBuffer, VertexBufferProps } from "./resources";
|
||||||
import { ShaderFlagKey, ShaderFlags, createPipeline, shaderFlagsKey } from "./shader";
|
import { GLOBAL_UNIFORMS_SIZE, MATERIAL_UNIFORMS_SIZE, OBJECT_UNIFORMS_SIZE, ShaderFlagKey, ShaderFlags, _createPipeline, _shaderFlagsKey } from "./shader";
|
||||||
|
|
||||||
const _matrixOStoWSNormal = new Matrix4x4(
|
const _matrixOStoWSNormal = new Matrix4x4(
|
||||||
NaN, NaN, NaN, NaN,
|
NaN, NaN, NaN, NaN,
|
||||||
@ -117,6 +117,7 @@ export class Renderer {
|
|||||||
width: framebufferTexture.width,
|
width: framebufferTexture.width,
|
||||||
height: framebufferTexture.height,
|
height: framebufferTexture.height,
|
||||||
format: "depth",
|
format: "depth",
|
||||||
|
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
||||||
});
|
});
|
||||||
|
|
||||||
this._globalBindGroupLayout = device.createBindGroupLayout({
|
this._globalBindGroupLayout = device.createBindGroupLayout({
|
||||||
@ -266,7 +267,7 @@ export class Renderer {
|
|||||||
this._globalBindGroup = device.createBindGroup({
|
this._globalBindGroup = device.createBindGroup({
|
||||||
layout: this._globalBindGroupLayout,
|
layout: this._globalBindGroupLayout,
|
||||||
entries: [
|
entries: [
|
||||||
{ binding: 0, resource: { buffer: this._uniformBuffer } },
|
{ binding: 0, resource: { buffer: this._uniformBuffer, size: GLOBAL_UNIFORMS_SIZE } },
|
||||||
{ binding: 1, resource: { buffer: this._pointLightBuffer } },
|
{ binding: 1, resource: { buffer: this._pointLightBuffer } },
|
||||||
{ binding: 2, resource: { buffer: this._directionalLightBuffer } },
|
{ binding: 2, resource: { buffer: this._directionalLightBuffer } },
|
||||||
],
|
],
|
||||||
@ -275,7 +276,7 @@ export class Renderer {
|
|||||||
this._objectBindGroup = device.createBindGroup({
|
this._objectBindGroup = device.createBindGroup({
|
||||||
layout: this._objectBindGroupLayout,
|
layout: this._objectBindGroupLayout,
|
||||||
entries: [
|
entries: [
|
||||||
{ binding: 0, resource: { buffer: this._uniformBuffer } },
|
{ binding: 0, resource: { buffer: this._uniformBuffer, size: OBJECT_UNIFORMS_SIZE } },
|
||||||
],
|
],
|
||||||
label: "Object",
|
label: "Object",
|
||||||
});
|
});
|
||||||
@ -336,14 +337,14 @@ export class Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getOrCreatePipeline(flags: ShaderFlags): GPURenderPipeline {
|
_getOrCreatePipeline(flags: ShaderFlags): GPURenderPipeline {
|
||||||
const key = shaderFlagsKey(flags);
|
const key = _shaderFlagsKey(flags);
|
||||||
|
|
||||||
let pipeline = this._pipelineCache.get(key);
|
let pipeline = this._pipelineCache.get(key);
|
||||||
if (pipeline !== undefined) {
|
if (pipeline !== undefined) {
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = createPipeline(this, flags);
|
pipeline = _createPipeline(this, flags);
|
||||||
this._pipelineCache.set(key, pipeline);
|
this._pipelineCache.set(key, pipeline);
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
@ -401,11 +402,12 @@ export class Renderer {
|
|||||||
this._uniformWriter.writeF32(material._normalScale);
|
this._uniformWriter.writeF32(material._normalScale);
|
||||||
this._uniformWriter.writeColorF32(material._emissive);
|
this._uniformWriter.writeColorF32(material._emissive);
|
||||||
this._uniformWriter.writeF32(material._ior);
|
this._uniformWriter.writeF32(material._ior);
|
||||||
|
this._uniformWriter.padToAlign(256);
|
||||||
|
|
||||||
const bindGroup = this._device.createBindGroup({
|
const bindGroup = this._device.createBindGroup({
|
||||||
layout: this._materialBindGroupLayout,
|
layout: this._materialBindGroupLayout,
|
||||||
entries: [
|
entries: [
|
||||||
{ binding: 0, resource: { buffer: this._uniformBuffer } },
|
{ binding: 0, resource: { buffer: this._uniformBuffer, size: MATERIAL_UNIFORMS_SIZE } },
|
||||||
{ binding: 1, resource: this._sampler },
|
{ binding: 1, resource: this._sampler },
|
||||||
{ binding: 2, resource: material._baseColorPartialCoverageTexture?._textureView ?? this._textureWhite._textureView },
|
{ binding: 2, resource: material._baseColorPartialCoverageTexture?._textureView ?? this._textureWhite._textureView },
|
||||||
{ binding: 3, resource: material._occlusionTexture?._textureView ?? this._textureWhite._textureView },
|
{ binding: 3, resource: material._occlusionTexture?._textureView ?? this._textureWhite._textureView },
|
||||||
@ -433,6 +435,7 @@ export class Renderer {
|
|||||||
object._updateWorldMatrix();
|
object._updateWorldMatrix();
|
||||||
this._uniformWriter.writeMatrix4x4(object._worldMatrix);
|
this._uniformWriter.writeMatrix4x4(object._worldMatrix);
|
||||||
this._uniformWriter.writeMatrix4x4(_matrixOStoWSNormal.setObject(object._worldMatrix).inverseTransposeAffine());
|
this._uniformWriter.writeMatrix4x4(_matrixOStoWSNormal.setObject(object._worldMatrix).inverseTransposeAffine());
|
||||||
|
this._uniformWriter.padToAlign(256);
|
||||||
return offset;
|
return offset;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -491,9 +494,7 @@ export class Renderer {
|
|||||||
this._uniformWriter.writeColorF32(scene._ambientLight);
|
this._uniformWriter.writeColorF32(scene._ambientLight);
|
||||||
this._uniformWriter.writeU32(pointLightCount);
|
this._uniformWriter.writeU32(pointLightCount);
|
||||||
this._uniformWriter.writeU32(directionalLightCount);
|
this._uniformWriter.writeU32(directionalLightCount);
|
||||||
this._uniformWriter.writeU32(0);
|
this._uniformWriter.padToAlign(256);
|
||||||
this._uniformWriter.writeU32(0);
|
|
||||||
this._uniformWriter.writeU32(0);
|
|
||||||
|
|
||||||
// upload uniforms
|
// upload uniforms
|
||||||
|
|
||||||
@ -520,11 +521,18 @@ export class Renderer {
|
|||||||
|
|
||||||
pass.setPipeline(renderPipeline);
|
pass.setPipeline(renderPipeline);
|
||||||
|
|
||||||
|
/* WORKAROUND
|
||||||
|
*
|
||||||
|
* As of writing, Chrome doesn't support passing null as the second
|
||||||
|
* argument. We could (and should) bind the buffers unconditionally
|
||||||
|
* for increased safety. For now, we only do this when they are not
|
||||||
|
* null.
|
||||||
|
*/
|
||||||
pass.setVertexBuffer(0, vertexBuffer._positionBuffer);
|
pass.setVertexBuffer(0, vertexBuffer._positionBuffer);
|
||||||
pass.setVertexBuffer(1, vertexBuffer._texCoordBuffer);
|
if (vertexBuffer._texCoordBuffer !== null) pass.setVertexBuffer(1, vertexBuffer._texCoordBuffer);
|
||||||
pass.setVertexBuffer(2, vertexBuffer._lightTexCoordBuffer);
|
if (vertexBuffer._lightTexCoordBuffer !== null) pass.setVertexBuffer(2, vertexBuffer._lightTexCoordBuffer);
|
||||||
pass.setVertexBuffer(3, vertexBuffer._normalBuffer);
|
if (vertexBuffer._normalBuffer !== null) pass.setVertexBuffer(3, vertexBuffer._normalBuffer);
|
||||||
pass.setVertexBuffer(4, vertexBuffer._tangentBuffer);
|
if (vertexBuffer._tangentBuffer !== null) pass.setVertexBuffer(4, vertexBuffer._tangentBuffer);
|
||||||
pass.setIndexBuffer(indexBuffer._buffer, indexBuffer._indexFormat);
|
pass.setIndexBuffer(indexBuffer._buffer, indexBuffer._indexFormat);
|
||||||
|
|
||||||
pass.setBindGroup(2, this._objectBindGroup, [objectOffset]);
|
pass.setBindGroup(2, this._objectBindGroup, [objectOffset]);
|
||||||
|
@ -20,7 +20,7 @@ export interface IndexBufferResizeProps {
|
|||||||
|
|
||||||
export class IndexBuffer {
|
export class IndexBuffer {
|
||||||
|
|
||||||
readonly type!: "IndexBuffer";
|
declare readonly type: "IndexBuffer";
|
||||||
_renderer: Renderer;
|
_renderer: Renderer;
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
@ -21,12 +21,15 @@ export interface Texture2DProps {
|
|||||||
readonly height: number;
|
readonly height: number;
|
||||||
|
|
||||||
readonly format: Texture2DFormat;
|
readonly format: Texture2DFormat;
|
||||||
|
|
||||||
|
readonly usage?: GPUTextureUsageFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Texture2DResizeProps {
|
export interface Texture2DResizeProps {
|
||||||
readonly width?: number;
|
readonly width?: number;
|
||||||
readonly height?: number;
|
readonly height?: number;
|
||||||
readonly format?: Texture2DFormat;
|
readonly format?: Texture2DFormat;
|
||||||
|
readonly usage?: GPUTextureUsageFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Texture2DAdvancedWriteProps {
|
export interface Texture2DAdvancedWriteProps {
|
||||||
@ -39,7 +42,7 @@ export interface Texture2DAdvancedWriteProps {
|
|||||||
|
|
||||||
export class Texture2D {
|
export class Texture2D {
|
||||||
|
|
||||||
readonly type!: "Texture2D";
|
declare readonly type: "Texture2D";
|
||||||
_renderer: Renderer;
|
_renderer: Renderer;
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
@ -53,6 +56,7 @@ export class Texture2D {
|
|||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
format,
|
format,
|
||||||
|
usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
||||||
}: Texture2DProps) {
|
}: Texture2DProps) {
|
||||||
this._renderer = renderer;
|
this._renderer = renderer;
|
||||||
|
|
||||||
@ -62,7 +66,7 @@ export class Texture2D {
|
|||||||
|
|
||||||
this._renderer = renderer;
|
this._renderer = renderer;
|
||||||
this._texture = renderer._device.createTexture({
|
this._texture = renderer._device.createTexture({
|
||||||
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
usage,
|
||||||
size: { width, height },
|
size: { width, height },
|
||||||
format: gpuFormat,
|
format: gpuFormat,
|
||||||
label: name
|
label: name
|
||||||
@ -147,13 +151,14 @@ export class Texture2D {
|
|||||||
width = this._texture.width,
|
width = this._texture.width,
|
||||||
height = this._texture.height,
|
height = this._texture.height,
|
||||||
format = this._format,
|
format = this._format,
|
||||||
|
usage = this._texture.usage,
|
||||||
}: Texture2DResizeProps): Texture2D {
|
}: Texture2DResizeProps): Texture2D {
|
||||||
this._texture.destroy();
|
this._texture.destroy();
|
||||||
|
|
||||||
const gpuFormat = gpuTextureFormat(format);
|
const gpuFormat = gpuTextureFormat(format);
|
||||||
|
|
||||||
this._texture = this._renderer._device.createTexture({
|
this._texture = this._renderer._device.createTexture({
|
||||||
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
usage,
|
||||||
size: { width, height },
|
size: { width, height },
|
||||||
format: gpuFormat,
|
format: gpuFormat,
|
||||||
label: this._name
|
label: this._name
|
||||||
|
@ -51,7 +51,7 @@ export interface VertexBufferWriteTypedArrayProps {
|
|||||||
|
|
||||||
export class VertexBuffer {
|
export class VertexBuffer {
|
||||||
|
|
||||||
readonly type!: "VertexBuffer";
|
declare readonly type: "VertexBuffer";
|
||||||
_renderer: Renderer;
|
_renderer: Renderer;
|
||||||
|
|
||||||
_name: string;
|
_name: string;
|
||||||
|
@ -6,6 +6,13 @@
|
|||||||
|
|
||||||
import { Renderer } from "./oktaeder";
|
import { Renderer } from "./oktaeder";
|
||||||
|
|
||||||
|
// 152 bytes padded to 256
|
||||||
|
export const GLOBAL_UNIFORMS_SIZE = 256;
|
||||||
|
// 64 bytes padded to 256
|
||||||
|
export const MATERIAL_UNIFORMS_SIZE = 256;
|
||||||
|
// 128 bytes padded to 256
|
||||||
|
export const OBJECT_UNIFORMS_SIZE = 256;
|
||||||
|
|
||||||
export type ShaderFlagKey = number;
|
export type ShaderFlagKey = number;
|
||||||
|
|
||||||
export interface ShaderFlags {
|
export interface ShaderFlags {
|
||||||
@ -15,7 +22,7 @@ export interface ShaderFlags {
|
|||||||
readonly tangent: boolean;
|
readonly tangent: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shaderFlagsKey({
|
export function _shaderFlagsKey({
|
||||||
texCoord,
|
texCoord,
|
||||||
lightTexCoord,
|
lightTexCoord,
|
||||||
normal,
|
normal,
|
||||||
@ -29,13 +36,13 @@ export function shaderFlagsKey({
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createPipeline(renderer: Renderer, {
|
export function _createPipeline(renderer: Renderer, {
|
||||||
texCoord,
|
texCoord,
|
||||||
lightTexCoord,
|
lightTexCoord,
|
||||||
normal,
|
normal,
|
||||||
tangent,
|
tangent,
|
||||||
}: ShaderFlags): GPURenderPipeline {
|
}: ShaderFlags): GPURenderPipeline {
|
||||||
const shaderCode = createShaderCode({ texCoord, lightTexCoord, normal, tangent });
|
const shaderCode = _createShaderCode({ texCoord, lightTexCoord, normal, tangent });
|
||||||
|
|
||||||
const shaderModule = renderer._device.createShaderModule({
|
const shaderModule = renderer._device.createShaderModule({
|
||||||
code: shaderCode,
|
code: shaderCode,
|
||||||
@ -130,7 +137,7 @@ export function createPipeline(renderer: Renderer, {
|
|||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createShaderCode({
|
export function _createShaderCode({
|
||||||
texCoord,
|
texCoord,
|
||||||
lightTexCoord,
|
lightTexCoord,
|
||||||
normal,
|
normal,
|
||||||
@ -147,7 +154,7 @@ struct Vertex {
|
|||||||
|
|
||||||
struct Varyings {
|
struct Varyings {
|
||||||
@builtin(position) positionCS: vec4<f32>,
|
@builtin(position) positionCS: vec4<f32>,
|
||||||
@location(0) positionVS: vec4<f32>,
|
@location(0) positionVS: vec3<f32>,
|
||||||
${texCoord ? `@location(1) texCoord: vec2<f32>,` : ""}
|
${texCoord ? `@location(1) texCoord: vec2<f32>,` : ""}
|
||||||
${lightTexCoord ? `@location(2) lightTexCoord: vec2<f32>,` : ""}
|
${lightTexCoord ? `@location(2) lightTexCoord: vec2<f32>,` : ""}
|
||||||
${normal ? `@location(3) normalVS: vec3<f32>,` : ""}
|
${normal ? `@location(3) normalVS: vec3<f32>,` : ""}
|
||||||
@ -219,7 +226,7 @@ fn visibilityGGX(dotNL: f32, dotNV: f32, alpha: f32) -> f32 {
|
|||||||
let vGGX = dotNL * sqrt(dotNV * dotNV * (1.0 - alphaSquared) + alphaSquared);
|
let vGGX = dotNL * sqrt(dotNV * dotNV * (1.0 - alphaSquared) + alphaSquared);
|
||||||
let lGGX = dotNV * sqrt(dotNL * dotNL * (1.0 - alphaSquared) + alphaSquared);
|
let lGGX = dotNV * sqrt(dotNL * dotNL * (1.0 - alphaSquared) + alphaSquared);
|
||||||
let GGX = vGGX + lGGX;
|
let GGX = vGGX + lGGX;
|
||||||
return GGX > 0.0 ? 0.5 / GGX : 0.0;
|
return select(0.0, 0.5 / GGX, GGX > 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn distributionGGX(dotNH: f32, alpha: f32) -> f32 {
|
fn distributionGGX(dotNH: f32, alpha: f32) -> f32 {
|
||||||
@ -270,7 +277,7 @@ fn screenSpaceMatrixTStoVS(positionVS: vec3<f32>, normalVS: vec3<f32>, texCoord:
|
|||||||
let bitangentVS = q1perp * uv0.y + q0perp * uv1.y;
|
let bitangentVS = q1perp * uv0.y + q0perp * uv1.y;
|
||||||
|
|
||||||
let det = max(dot(tangentVS, tangentVS), dot(bitangentVS, bitangentVS));
|
let det = max(dot(tangentVS, tangentVS), dot(bitangentVS, bitangentVS));
|
||||||
let scale = (det == 0.0) ? 0.0 : inserseSqrt(det);
|
let scale = select(0.0, inverseSqrt(det), det != 0.0);
|
||||||
|
|
||||||
return mat3x3(tangentVS * scale, bitangentVS * scale, normalVS);
|
return mat3x3(tangentVS * scale, bitangentVS * scale, normalVS);
|
||||||
}
|
}
|
||||||
@ -297,10 +304,11 @@ fn vert(vertex: Vertex) -> Varyings {
|
|||||||
` : ""}
|
` : ""}
|
||||||
${texCoord ? "output.texCoord = vertex.texCoord;" : ""}
|
${texCoord ? "output.texCoord = vertex.texCoord;" : ""}
|
||||||
${lightTexCoord ? "output.lightTexCoord = vertex.lightTexCoord;" : ""}
|
${lightTexCoord ? "output.lightTexCoord = vertex.lightTexCoord;" : ""}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn frag(fragment: Varyings) -> @location(0) vec2<f32> {
|
fn frag(fragment: Varyings) -> @location(0) vec4<f32> {
|
||||||
var baseColor = _Material.baseColor;
|
var baseColor = _Material.baseColor;
|
||||||
var partialCoverage = _Material.partialCoverage;
|
var partialCoverage = _Material.partialCoverage;
|
||||||
var occlusion = 1.0;
|
var occlusion = 1.0;
|
||||||
@ -357,7 +365,7 @@ fn frag(fragment: Varyings) -> @location(0) vec2<f32> {
|
|||||||
|
|
||||||
var outgoingRadiance = vec3(0.0);
|
var outgoingRadiance = vec3(0.0);
|
||||||
|
|
||||||
for (var i: u32 = 0; i < _Global.pointLightCount; ++i) {
|
for (var i: u32 = 0; i < _Global.pointLightCount; i++) {
|
||||||
let light = _PointLights[i];
|
let light = _PointLights[i];
|
||||||
|
|
||||||
let lightPositionVS = (_Global.matrixWStoVS * vec4(light.positionWS, 1.0)).xyz;
|
let lightPositionVS = (_Global.matrixWStoVS * vec4(light.positionWS, 1.0)).xyz;
|
||||||
@ -373,7 +381,7 @@ fn frag(fragment: Varyings) -> @location(0) vec2<f32> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i: u32 = 0; i < _Global.directionalLightCount; ++i) {
|
for (var i: u32 = 0; i < _Global.directionalLightCount; i++) {
|
||||||
let light = _DirectionalLights[i];
|
let light = _DirectionalLights[i];
|
||||||
|
|
||||||
let lightDirectionVS = normalize((_Global.matrixWStoVS * vec4(light.directionWS, 0.0)).xyz);
|
let lightDirectionVS = normalize((_Global.matrixWStoVS * vec4(light.directionWS, 0.0)).xyz);
|
||||||
|
Loading…
Reference in New Issue
Block a user