From d2dffe1737c74781e80cd799301ef07d8f96a95f Mon Sep 17 00:00:00 2001 From: Tim Knip Date: Thu, 24 Oct 2024 11:18:17 +0200 Subject: [PATCH 1/3] update to latest webgpu spec --- package-lock.json | 16 +++++----- package.json | 2 +- src/renderer/camera/camera.ts | 4 +-- src/renderer/camera/preset-camera.ts | 8 +++-- src/renderer/camera/user-camera.ts | 12 ++++--- src/renderer/renderer.ts | 24 +++++++------- src/renderer/scene.ts | 3 +- src/shaders/frag.wgsl.ts | 48 ++++++++++++++-------------- src/shaders/vert.wgsl.ts | 48 ++++++++++++++-------------- 9 files changed, 85 insertions(+), 80 deletions(-) diff --git a/package-lock.json b/package-lock.json index 06bdf1c..28a84ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "": { "name": "webgpu-gltf-viewer", "version": "1.0.0", - "license": "ISC", + "license": "MIT", "dependencies": { "gl-matrix": "^3.4.3", "stats.js": "^0.17.0" @@ -15,7 +15,7 @@ "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.3.1", "@typescript-eslint/parser": "^5.3.1", - "@webgpu/types": "^0.1.7", + "@webgpu/types": "^0.1.49", "eslint": "^8.2.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-typescript": "^15.0.0", @@ -721,9 +721,9 @@ } }, "node_modules/@webgpu/types": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.7.tgz", - "integrity": "sha512-KOcGuwHPFHHXlXRS9HQSIpUwp9IgocqfMflEnOO8Hhykwk+UlYCxyUwbAN0VgQSpF0slrLcjtz0IRBeuAW1hsw==", + "version": "0.1.49", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.49.tgz", + "integrity": "sha512-NMmS8/DofhH/IFeW+876XrHVWel+J/vdcFCHLDqeJgkH9x0DeiwjVd8LcBdaxdG/T7Rf8VUAYsA8X1efMzLjRQ==", "dev": true }, "node_modules/@webpack-cli/configtest": { @@ -7019,9 +7019,9 @@ } }, "@webgpu/types": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.7.tgz", - "integrity": "sha512-KOcGuwHPFHHXlXRS9HQSIpUwp9IgocqfMflEnOO8Hhykwk+UlYCxyUwbAN0VgQSpF0slrLcjtz0IRBeuAW1hsw==", + "version": "0.1.49", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.49.tgz", + "integrity": "sha512-NMmS8/DofhH/IFeW+876XrHVWel+J/vdcFCHLDqeJgkH9x0DeiwjVd8LcBdaxdG/T7Rf8VUAYsA8X1efMzLjRQ==", "dev": true }, "@webpack-cli/configtest": { diff --git a/package.json b/package.json index 480dacf..6ad9489 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.3.1", "@typescript-eslint/parser": "^5.3.1", - "@webgpu/types": "^0.1.7", + "@webgpu/types": "^0.1.49", "eslint": "^8.2.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-typescript": "^15.0.0", diff --git a/src/renderer/camera/camera.ts b/src/renderer/camera/camera.ts index de343c7..021a9b8 100644 --- a/src/renderer/camera/camera.ts +++ b/src/renderer/camera/camera.ts @@ -1,7 +1,7 @@ -import { vec3, mat4 } from 'gl-matrix'; +import { vec3, vec4, mat4 } from 'gl-matrix'; export default abstract class Camera { - eye = vec3.create(); + eye = vec4.create(); view = mat4.create(); diff --git a/src/renderer/camera/preset-camera.ts b/src/renderer/camera/preset-camera.ts index ce65b26..e420114 100644 --- a/src/renderer/camera/preset-camera.ts +++ b/src/renderer/camera/preset-camera.ts @@ -1,4 +1,4 @@ -import { mat4, vec3 } from 'gl-matrix'; +import { mat4, vec3, vec4 } from 'gl-matrix'; import Camera from './camera'; export default class PresetCamera extends Camera { @@ -31,8 +31,10 @@ export default class PresetCamera extends Camera { } updateView() { - this.eye = vec3.create(); - vec3.transformMat4(this.eye, this.eye, this.globalTransform); + const e = vec3.create(); + this.eye = vec4.create(); + vec3.transformMat4(e, e, this.globalTransform); + vec4.set(this.eye, e[0], e[1], e[2], 0); mat4.invert(this.view, this.globalTransform); } } diff --git a/src/renderer/camera/user-camera.ts b/src/renderer/camera/user-camera.ts index 1a3910f..8221a15 100644 --- a/src/renderer/camera/user-camera.ts +++ b/src/renderer/camera/user-camera.ts @@ -1,4 +1,4 @@ -import { mat4, vec3 } from 'gl-matrix'; +import { mat4, vec3, vec4 } from 'gl-matrix'; import { clamp } from '../../util'; import Camera from './camera'; @@ -81,13 +81,15 @@ export default class UserCamera extends Camera { } updateView() { - this.eye = vec3.fromValues( + + const e = vec3.fromValues( this.center[0], this.center[1], this.center[2] + this.radius ); - vec3.rotateX(this.eye, this.eye, this.center, this.phi); - vec3.rotateY(this.eye, this.eye, this.center, this.theta); - mat4.lookAt(this.view, this.eye, this.center, up); + vec3.rotateX(e, e, this.center, this.phi); + vec3.rotateY(e, e, this.center, this.theta); + mat4.lookAt(this.view, e, this.center, up); + vec4.set(this.eye, e[0], e[1], e[2], 0); } } diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 687a0c8..fa78d86 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -45,10 +45,9 @@ export class Renderer { colorAttachments: [], depthStencilAttachment: { view: depthTexture.createView(), - depthLoadValue: 1.0, - depthStoreOp: 'store', - stencilLoadValue: 0, - stencilStoreOp: 'store', + depthClearValue: 1.0, + depthLoadOp: 'clear', + depthStoreOp: 'store' }, }; @@ -57,7 +56,7 @@ export class Renderer { canvas.clientWidth * devicePixelRatio, canvas.clientHeight * devicePixelRatio, ]; - context.configure({ device, format: contextFormat, size }); + context.configure({ device, format: contextFormat }); depthTexture.destroy(); depthTexture = device.createTexture({ size, @@ -83,7 +82,8 @@ export class Renderer { this.renderPassDesc.colorAttachments = [ { view: this.context.getCurrentTexture().createView(), - loadValue: { r: 0.3, g: 0.5, b: 0.7, a: 1 }, + clearValue: [0, 0, 0, 0], + loadOp: 'clear', storeOp: 'store', }, ]; @@ -106,7 +106,7 @@ export class Renderer { }); }); - passEncoder.endPass(); + passEncoder.end(); this.device.queue.submit([commandEncoder.finish()]); this.stats.end(); @@ -161,14 +161,14 @@ export async function createRenderer(canvas: HTMLCanvasElement) { const adapter = await entry.requestAdapter(); const device = await adapter!.requestDevice(); const context = canvas.getContext('webgpu'); - const format = context!.getPreferredFormat(adapter!); + + canvas.width = canvas.clientWidth * devicePixelRatio; + canvas.height = canvas.clientHeight * devicePixelRatio; + + const format = navigator.gpu.getPreferredCanvasFormat(); context!.configure({ device, format, - size: [ - canvas.clientWidth * devicePixelRatio, - canvas.clientHeight * devicePixelRatio, - ], }); return new Renderer(canvas, device, context!, format); } diff --git a/src/renderer/scene.ts b/src/renderer/scene.ts index 5772602..03c1dae 100644 --- a/src/renderer/scene.ts +++ b/src/renderer/scene.ts @@ -48,7 +48,7 @@ export default class Scene { usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, // eslint-disable-line no-bitwise }); const eyeBuffer = device.createBuffer({ - size: 4 * 3, + size: 4 * 4, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, // eslint-disable-line no-bitwise }); const cameraBindGroup = device.createBindGroup({ @@ -177,6 +177,7 @@ export default class Scene { } }); } + (this.presetCamera || this.userCamera).update(device, passEncoder); } diff --git a/src/shaders/frag.wgsl.ts b/src/shaders/frag.wgsl.ts index db3ed6e..80f582a 100644 --- a/src/shaders/frag.wgsl.ts +++ b/src/shaders/frag.wgsl.ts @@ -31,40 +31,40 @@ export default function frag(primitive: Primitive, material: any) { return /* wgsl */ ` - [[block]] struct Camera + struct Camera { - eye: vec3; + eye: vec4, }; - [[group(0), binding(1)]] var camera: Camera; + @group(0) @binding(1) var camera: Camera; ${ baseColorTexture - ? `[[group(1), binding(1)]] var texSampler: sampler; - [[group(1), binding(2)]] var tex: texture_2d; /* wgsl */` + ? `@group(1) @binding(1) var texSampler: sampler; + @group(1) @binding(2) var tex: texture_2d; /* wgsl */` : '' } ${ metallicRoughnessTexture - ? `[[group(1), binding(3)]] var metalRoughSampler: sampler; - [[group(1), binding(4)]] var metalRoughTex: texture_2d; /* wgsl */` + ? `@group(1) @binding(3) var metalRoughSampler: sampler; + @group(1) @binding(4) var metalRoughTex: texture_2d; /* wgsl */` : '' } ${ normalTexture - ? `[[group(1), binding(5)]] var normalSampler: sampler; - [[group(1), binding(6)]] var normalTex: texture_2d; /* wgsl */` + ? `@group(1) @binding(5) var normalSampler: sampler; + @group(1) @binding(6) var normalTex: texture_2d; /* wgsl */` : '' } ${ occlusionTexture - ? `[[group(1), binding(7)]] var occlusionSampler: sampler; - [[group(1), binding(8)]] var occlusionTex: texture_2d; /* wgsl */` + ? `@group(1) @binding(7) var occlusionSampler: sampler; + @group(1) @binding(8) var occlusionTex: texture_2d; /* wgsl */` : '' } ${ emissiveTexture - ? `[[group(1), binding(9)]] var emissiveSampler: sampler; - [[group(1), binding(10)]] var emissiveTex: texture_2d; /* wgsl */` + ? `@group(1) @binding(9) var emissiveSampler: sampler; + @group(1) @binding(10) var emissiveTex: texture_2d; /* wgsl */` : '' } @@ -74,7 +74,7 @@ export default function frag(primitive: Primitive, material: any) { return vec4(pow(color.rgb, vec3(2.2)), color.a); } - let pi: f32 = 3.141592653589793; + const pi: f32 = 3.141592653589793; fn blinnPhong(color: vec3, l: vec3, @@ -127,30 +127,30 @@ export default function frag(primitive: Primitive, material: any) { return ndotl * (diffuse + specular) * 2.0 + color * 0.1; } - [[stage(fragment)]] - fn main([[location(0)]] vNormal: vec3, - [[location(1)]] worldPos: vec3, + @fragment + fn main(@location(0) vNormal: vec3, + @location(1) worldPos: vec3, ${ hasUV - ? `[[location(${(location += 1)})]] uv: vec2, /* wgsl */` + ? `@location(${(location += 1)}) uv: vec2, /* wgsl */` : '' } ${ hasUV1 - ? `[[location(${(location += 1)})]] uv1: vec2, /* wgsl */` + ? `@location(${(location += 1)}) uv1: vec2, /* wgsl */` : '' } ${ hasTangent - ? `[[location(${(location += 1)})]] tangent: vec3, - [[location(${(location += 1)})]] bitangent: vec3, /* wgsl */` + ? `@location(${(location += 1)}) tangent: vec3, + @location(${(location += 1)}) bitangent: vec3, /* wgsl */` : '' } ${ hasVertexColor - ? `[[location(${(location += 1)})]] vColor: vec4, /* wgsl */` + ? `@location(${(location += 1)}) vColor: vec4, /* wgsl */` : '' - }) -> [[location(0)]] vec4 + }) -> @location(0) vec4 { let lightDir = normalize(vec3(2.0, 4.0, 3.0)); @@ -212,7 +212,7 @@ export default function frag(primitive: Primitive, material: any) { : '' } - let viewDir = normalize(camera.eye - worldPos); + let viewDir = normalize(camera.eye.xyz - worldPos); ${ material.doubleSided ? `if (dot(normal, viewDir) < 0.0) diff --git a/src/shaders/vert.wgsl.ts b/src/shaders/vert.wgsl.ts index aad008c..9c10a33 100644 --- a/src/shaders/vert.wgsl.ts +++ b/src/shaders/vert.wgsl.ts @@ -13,72 +13,72 @@ export default function vert(primitive: Primitive, instanceCount: number) { return /* wgsl */ ` - [[block]] struct Camera +struct Camera { - projView: mat4x4; + projView: mat4x4, }; - [[group(0), binding(0)]] var camera: Camera; + @group(0) @binding(0) var camera: Camera; struct Model { - matrix: mat4x4; - invTr: mat4x4; + matrix: mat4x4, + invTr: mat4x4, }; - [[block]] struct Models + struct Models { - model: [[stride(128)]] array; + model: array, }; - [[group(1), binding(0)]] var models: Models; + @group(1) @binding(0) var models: Models; struct VertexOutput { - [[builtin(position)]] position: vec4; - [[location(0)]] normal: vec3; - [[location(1)]] worldPos: vec3; + @builtin(position) position: vec4, + @location(0) normal: vec3, + @location(1) worldPos: vec3, ${ hasUV - ? `[[location(${(outLocation += 1)})]] uv: vec2; /* wgsl */` + ? `@location(${(outLocation += 1)}) uv: vec2, /* wgsl */` : '' } ${ hasUV1 - ? `[[location(${(outLocation += 1)})]] uv1: vec2; /* wgsl */` + ? `@location(${(outLocation += 1)}) uv1: vec2, /* wgsl */` : '' } ${ hasTangent - ? `[[location(${(outLocation += 1)})]] tangent: vec3; - [[location(${(outLocation += 1)})]] bitangent: vec3; /* wgsl */` + ? `@location(${(outLocation += 1)}) tangent: vec3, + @location(${(outLocation += 1)}) bitangent: vec3, /* wgsl */` : '' } ${ hasVertexColor - ? `[[location(${(outLocation += 1)})]] color: vec4; /* wgsl */` + ? `@location(${(outLocation += 1)}) color: vec4, /* wgsl */` : '' } }; - [[stage(vertex)]] - fn main([[builtin(instance_index)]] instanceIndex : u32, - [[location(0)]] pos: vec3, - [[location(1)]] normal: vec3, + @vertex + fn main(@builtin(instance_index) instanceIndex : u32, + @location(0) pos: vec3, + @location(1) normal: vec3, ${ hasUV - ? `[[location(${(inLocation += 1)})]] uv: vec2, /* wgsl */` + ? `@location(${(inLocation += 1)}) uv: vec2, /* wgsl */` : '' } ${ hasUV1 - ? `[[location(${(inLocation += 1)})]] uv1: vec2, /* wgsl */` + ? `@location(${(inLocation += 1)}) uv1: vec2, /* wgsl */` : '' } ${ hasTangent - ? `[[location(${(inLocation += 1)})]] tangent: vec4, /* wgsl */` + ? `@location(${(inLocation += 1)}) tangent: vec4, /* wgsl */` : '' } ${ hasVertexColor - ? `[[location(${(inLocation += 1)})]] color: vec4, /* wgsl */` + ? `@location(${(inLocation += 1)}) color: vec4, /* wgsl */` : '' }) -> VertexOutput { From 1d09876a6f02f75358e0e84387b8b0393ebfdca4 Mon Sep 17 00:00:00 2001 From: Tim Knip Date: Thu, 24 Oct 2024 11:26:09 +0200 Subject: [PATCH 2/3] update to latest webgpu spec --- src/renderer/camera/camera.ts | 4 ++-- src/renderer/camera/preset-camera.ts | 6 ++---- src/renderer/camera/user-camera.ts | 10 ++++------ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/renderer/camera/camera.ts b/src/renderer/camera/camera.ts index 021a9b8..de343c7 100644 --- a/src/renderer/camera/camera.ts +++ b/src/renderer/camera/camera.ts @@ -1,7 +1,7 @@ -import { vec3, vec4, mat4 } from 'gl-matrix'; +import { vec3, mat4 } from 'gl-matrix'; export default abstract class Camera { - eye = vec4.create(); + eye = vec3.create(); view = mat4.create(); diff --git a/src/renderer/camera/preset-camera.ts b/src/renderer/camera/preset-camera.ts index e420114..8d6e845 100644 --- a/src/renderer/camera/preset-camera.ts +++ b/src/renderer/camera/preset-camera.ts @@ -31,10 +31,8 @@ export default class PresetCamera extends Camera { } updateView() { - const e = vec3.create(); - this.eye = vec4.create(); - vec3.transformMat4(e, e, this.globalTransform); - vec4.set(this.eye, e[0], e[1], e[2], 0); + this.eye = vec3.create(); + vec3.transformMat4(this.eye, this.eye, this.globalTransform); mat4.invert(this.view, this.globalTransform); } } diff --git a/src/renderer/camera/user-camera.ts b/src/renderer/camera/user-camera.ts index 8221a15..e84e754 100644 --- a/src/renderer/camera/user-camera.ts +++ b/src/renderer/camera/user-camera.ts @@ -81,15 +81,13 @@ export default class UserCamera extends Camera { } updateView() { - - const e = vec3.fromValues( + this.eye = vec3.fromValues( this.center[0], this.center[1], this.center[2] + this.radius ); - vec3.rotateX(e, e, this.center, this.phi); - vec3.rotateY(e, e, this.center, this.theta); - mat4.lookAt(this.view, e, this.center, up); - vec4.set(this.eye, e[0], e[1], e[2], 0); + vec3.rotateX(this.eye, this.eye, this.center, this.phi); + vec3.rotateY(this.eye, this.eye, this.center, this.theta); + mat4.lookAt(this.view, this.eye, this.center, up); } } From 55bf9ca201018cbc34ccd98865a336dd4e23ea10 Mon Sep 17 00:00:00 2001 From: Tim Knip Date: Thu, 24 Oct 2024 11:33:45 +0200 Subject: [PATCH 3/3] remove unused imports --- src/renderer/camera/preset-camera.ts | 2 +- src/renderer/camera/user-camera.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/camera/preset-camera.ts b/src/renderer/camera/preset-camera.ts index 8d6e845..ce65b26 100644 --- a/src/renderer/camera/preset-camera.ts +++ b/src/renderer/camera/preset-camera.ts @@ -1,4 +1,4 @@ -import { mat4, vec3, vec4 } from 'gl-matrix'; +import { mat4, vec3 } from 'gl-matrix'; import Camera from './camera'; export default class PresetCamera extends Camera { diff --git a/src/renderer/camera/user-camera.ts b/src/renderer/camera/user-camera.ts index e84e754..1a3910f 100644 --- a/src/renderer/camera/user-camera.ts +++ b/src/renderer/camera/user-camera.ts @@ -1,4 +1,4 @@ -import { mat4, vec3, vec4 } from 'gl-matrix'; +import { mat4, vec3 } from 'gl-matrix'; import { clamp } from '../../util'; import Camera from './camera';