webgpubridge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ <div align="center">
2
+
3
+ # WebGPUbridge
4
+
5
+ ### A small, explicit bridge from portable 3D descriptions to WebGPU.
6
+
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178c6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![Module](https://img.shields.io/badge/module-ESM-f7df1e?logo=javascript&logoColor=111827)](package.json) [![WebGPU](https://img.shields.io/badge/WebGPU-native-005a9c?logo=webgpu&logoColor=white)](https://www.w3.org/TR/webgpu/) [![Status](https://img.shields.io/badge/status-pre--alpha-f5a623)](https://shaderlab.dev)
8
+
9
+ [shaderlab.dev](https://shaderlab.dev)
10
+
11
+ </div>
12
+
13
+ WebGPUbridge materializes Web3D Kit descriptors as WebGPU-ready data and
14
+ caller-owned GPU resources. It keeps scene descriptions portable while leaving
15
+ adapter selection, device ownership, rendering, and asset loading explicit.
16
+
17
+ ## Install
18
+
19
+ ```sh
20
+ npm install webgpubridge web3d-kit
21
+ ```
22
+
23
+ ```ts
24
+ import { mesh, planeGeometry, shaderMaterial } from "web3d-kit";
25
+ import { createWebGPUObject } from "webgpubridge";
26
+
27
+ const object = createWebGPUObject(
28
+ mesh({
29
+ geometry: planeGeometry({ width: 2, height: 2 }),
30
+ material: shaderMaterial({ vertexShader, fragmentShader }),
31
+ }),
32
+ );
33
+ ```
34
+
35
+ ## Architecture
36
+
37
+ ```text
38
+ shader-runtime webgl-kit
39
+ │ │
40
+ └─────────┬────────┘
41
+
42
+ web3d-kit
43
+
44
+
45
+ webgpubridge
46
+
47
+
48
+ WebGPU
49
+ ```
50
+
51
+ `web3d-kit` owns portable descriptions; `webgpubridge` materializes those
52
+ descriptions without taking ownership of a WebGPU adapter, device, or queue.
53
+
54
+ ## Supported conversions
55
+
56
+ - vectors, transforms, bounds, scenes, groups, meshes, and cameras
57
+ - plane, box, sphere, and simple position/index buffer geometry
58
+ - basic, standard, and shader material envelopes
59
+ - tightly packed scalar and vector uniform blocks
60
+ - explicit GPU buffer, shader module, and render-pipeline helpers
61
+
62
+ ## Lifecycle
63
+
64
+ Use `disposeWebGPUBuffer` or `disposeWebGPUGeometry` explicitly. The bridge
65
+ does not request an adapter or device, submit work, or dispose caller-owned
66
+ pipelines and textures.
@@ -0,0 +1,107 @@
1
+ import type { Bounds3D, CameraDescriptor, ColorValue, GeometryDescriptor, MaterialDescriptor, SceneDescriptor, SceneNode, Transform3D, UniformMap, UniformValue, Vec2, Vec3, Vec4 } from "web3d-kit";
2
+ /** The small subset of WebGPU used by this adapter, kept structural so the
3
+ * package can be used with browser and Node WebGPU implementations alike. */
4
+ export interface WebGPUDevice {
5
+ createBuffer(descriptor: {
6
+ size: number;
7
+ usage: number;
8
+ mappedAtCreation?: boolean;
9
+ }): WebGPUBuffer;
10
+ createShaderModule(descriptor: {
11
+ code: string;
12
+ label?: string;
13
+ }): WebGPUShaderModule;
14
+ }
15
+ export interface WebGPUBuffer {
16
+ destroy(): void;
17
+ getMappedRange?(): ArrayBuffer;
18
+ unmap?(): void;
19
+ }
20
+ export interface WebGPUShaderModule {
21
+ readonly label?: string;
22
+ }
23
+ export interface WebGPUQueue {
24
+ writeBuffer(buffer: WebGPUBuffer, offset: number, data: ArrayBufferView): void;
25
+ }
26
+ export interface WebGPURenderPipelineDescriptor {
27
+ layout?: unknown;
28
+ vertex: {
29
+ module: WebGPUShaderModule;
30
+ entryPoint?: string;
31
+ buffers?: readonly unknown[];
32
+ };
33
+ fragment?: {
34
+ module: WebGPUShaderModule;
35
+ entryPoint?: string;
36
+ targets?: readonly unknown[];
37
+ };
38
+ primitive?: Record<string, unknown>;
39
+ }
40
+ export interface WebGPUTransform {
41
+ position?: Vec3;
42
+ rotation?: Vec3;
43
+ scale?: Vec3;
44
+ }
45
+ export interface WebGPUUniform {
46
+ value: UniformValue;
47
+ offset: number;
48
+ }
49
+ export interface WebGPUUniformBlock {
50
+ data: Float32Array;
51
+ uniforms: Readonly<Record<string, WebGPUUniform>>;
52
+ }
53
+ export interface WebGPUGeometry {
54
+ readonly positions: Float32Array;
55
+ readonly indices?: Uint32Array;
56
+ readonly bounds?: Bounds3D;
57
+ }
58
+ export interface WebGPUBufferGeometry extends WebGPUGeometry {
59
+ readonly vertexBuffer: WebGPUBuffer;
60
+ readonly indexBuffer?: WebGPUBuffer;
61
+ readonly vertexCount: number;
62
+ readonly indexCount: number;
63
+ }
64
+ export interface WebGPUMaterial {
65
+ readonly type: MaterialDescriptor["type"];
66
+ readonly color?: ColorValue;
67
+ readonly opacity?: number;
68
+ readonly transparent?: boolean;
69
+ readonly side?: MaterialDescriptor["side"];
70
+ readonly vertexShader?: string;
71
+ readonly fragmentShader?: string;
72
+ readonly uniforms: UniformBlock;
73
+ }
74
+ export type UniformBlock = WebGPUUniformBlock;
75
+ export interface WebGPUObject {
76
+ type: "mesh" | "group";
77
+ name?: string;
78
+ visible: boolean;
79
+ transform?: Transform3D;
80
+ metadata?: SceneNode["metadata"];
81
+ geometry?: WebGPUGeometry;
82
+ material?: WebGPUMaterial;
83
+ children: WebGPUObject[];
84
+ }
85
+ export interface WebGPUScene {
86
+ type: "scene";
87
+ metadata?: SceneDescriptor["metadata"];
88
+ children: WebGPUObject[];
89
+ }
90
+ export declare const toWebGPUVector2: (value: Vec2) => Float32Array;
91
+ export declare const toWebGPUVector3: (value: Vec3) => Float32Array;
92
+ export declare const toWebGPUVector4: (value: Vec4) => Float32Array;
93
+ export declare function applyWebGPUTransform(target: {
94
+ transform?: Transform3D;
95
+ }, transform?: Transform3D): typeof target;
96
+ export declare function toWebGPUGeometry(descriptor: GeometryDescriptor): WebGPUGeometry;
97
+ /** Converts uniforms to a tightly packed scalar/vector block. Values remain immutable. */
98
+ export declare function toWebGPUUniforms(uniforms?: UniformMap): WebGPUUniformBlock;
99
+ export declare function toWebGPUMaterial(descriptor: MaterialDescriptor): WebGPUMaterial;
100
+ export declare function createWebGPUBufferGeometry(device: WebGPUDevice, descriptor: GeometryDescriptor, queue?: WebGPUQueue): WebGPUBufferGeometry;
101
+ export declare function createWebGPUShaderModule(device: WebGPUDevice, code: string, label?: string): WebGPUShaderModule;
102
+ export declare function createWebGPURenderPipeline(device: WebGPUDevice, descriptor: WebGPURenderPipelineDescriptor): unknown;
103
+ export declare function createWebGPUObject(descriptor: SceneNode): WebGPUObject;
104
+ export declare function toWebGPUScene(descriptor: SceneDescriptor): WebGPUScene;
105
+ export declare function toWebGPUCamera(descriptor: CameraDescriptor): CameraDescriptor;
106
+ export declare function disposeWebGPUBuffer(buffer: WebGPUBuffer): void;
107
+ export declare function disposeWebGPUGeometry(geometry: WebGPUBufferGeometry): void;
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ const m=e=>new Float32Array(e),p=e=>new Float32Array(e),b=e=>new Float32Array(e);function d(e,t){return t&&(e.transform={...t,position:t.position&&[...t.position],rotation:t.rotation&&[...t.rotation],scale:t.scale&&[...t.scale]}),e}function l(e){if(e.type==="buffer")return{positions:new Float32Array(e.positions.flat()),indices:e.indices&&new Uint32Array(e.indices)};if(e.type==="plane"){const n=e.width/2,o=e.height/2;return{positions:new Float32Array([-n,-o,0,n,-o,0,n,o,0,-n,o,0]),indices:new Uint32Array([0,1,2,0,2,3])}}if(e.type==="box"){const n=e.width/2,o=e.height/2,i=e.depth/2,s=[[-n,-o,-i],[n,-o,-i],[n,o,-i],[-n,o,-i],[-n,-o,i],[n,-o,i],[n,o,i],[-n,o,i]];return{positions:new Float32Array(s.flat()),indices:new Uint32Array([0,1,2,0,2,3,4,6,5,4,7,6,0,4,5,0,5,1,2,6,7,2,7,3,0,3,7,0,7,4,1,5,6,1,6,2])}}const t=Math.max(3,e.heightSegments??16),a=Math.max(3,e.widthSegments??32),r=[],f=[];for(let n=0;n<=t;n++)for(let o=0;o<=a;o++){const i=n/t,s=o/a,u=i*Math.PI,y=s*Math.PI*2;r.push(Math.sin(u)*Math.cos(y)*e.radius,Math.cos(u)*e.radius,Math.sin(u)*Math.sin(y)*e.radius)}for(let n=0;n<t;n++)for(let o=0;o<a;o++){const i=n*(a+1)+o;f.push(i,i+a+1,i+1,i+1,i+a+1,i+a+2)}return{positions:new Float32Array(r),indices:new Uint32Array(f)}}function P(e){return l(e)}function c(e={}){const t=[],a={};for(const[r,f]of Object.entries(e)){const n=t.length;typeof f=="boolean"||typeof f=="number"?t.push(typeof f=="boolean"?f?1:0:f):t.push(...f),a[r]={value:f,offset:n}}return{data:new Float32Array(t),uniforms:a}}function x(e){return{type:e.type,color:"color"in e?e.color:void 0,opacity:e.opacity,transparent:e.transparent??(e.opacity!==void 0&&e.opacity<1),side:e.side,vertexShader:e.type==="shader"?e.vertexShader:void 0,fragmentShader:e.type==="shader"?e.fragmentShader:void 0,uniforms:c(e.type==="shader"?e.uniforms:{})}}function U(e,t,a){const r=l(t),f=e.createBuffer({size:r.positions.byteLength,usage:40});a?.writeBuffer(f,0,r.positions);const n=r.indices?e.createBuffer({size:r.indices.byteLength,usage:24}):void 0;return n&&r.indices&&a?.writeBuffer(n,0,r.indices),{...r,vertexBuffer:f,indexBuffer:n,vertexCount:r.positions.length/3,indexCount:r.indices?.length??0}}function w(e,t,a){return e.createShaderModule({code:t,...a?{label:a}:{}})}function G(e,t){const a=e.createRenderPipeline;if(!a)throw new TypeError("The supplied WebGPU device does not support createRenderPipeline.");return a.call(e,t)}function h(e){const t={type:e.type,name:e.name,visible:e.visible??!0,transform:e.transform,metadata:e.metadata,children:[]};return e.type==="mesh"?(t.geometry=l(e.geometry),t.material=x(e.material)):t.children=(e.children??[]).map(h),t}function g(e){return{type:"scene",metadata:e.metadata,children:(e.children??[]).map(h)}}function W(e){return{...e,transform:e.transform&&{...e.transform}}}function A(e){e.destroy()}function M(e){e.vertexBuffer.destroy(),e.indexBuffer?.destroy()}export{d as applyWebGPUTransform,U as createWebGPUBufferGeometry,h as createWebGPUObject,G as createWebGPURenderPipeline,w as createWebGPUShaderModule,A as disposeWebGPUBuffer,M as disposeWebGPUGeometry,W as toWebGPUCamera,P as toWebGPUGeometry,x as toWebGPUMaterial,g as toWebGPUScene,c as toWebGPUUniforms,m as toWebGPUVector2,p as toWebGPUVector3,b as toWebGPUVector4};
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "webgpubridge",
3
+ "version": "0.1.0",
4
+ "description": "Small adapters between portable Web3D Kit descriptors and WebGPU.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "sideEffects": false,
20
+ "homepage": "https://shaderlab.dev",
21
+ "scripts": {
22
+ "build": "tsc --project tsconfig.json",
23
+ "postbuild": "npm run dist --prefix \"$npm_config_local_prefix\" -- \"$PWD\"",
24
+ "pretest": "npm run build",
25
+ "test": "node --test test/*.test.mjs"
26
+ },
27
+ "dependencies": {
28
+ "web3d-kit": "^0.1.0"
29
+ },
30
+ "devDependencies": {
31
+ "typescript": "^5.9.3"
32
+ }
33
+ }