@ifc-lite/renderer 1.0.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/dist/picker.js ADDED
@@ -0,0 +1,215 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ export class Picker {
5
+ device;
6
+ pipeline;
7
+ depthTexture;
8
+ colorTexture;
9
+ uniformBuffer;
10
+ expressIdBuffer;
11
+ bindGroup;
12
+ maxMeshes = 10000;
13
+ constructor(device, width = 1, height = 1) {
14
+ this.device = device.getDevice();
15
+ // Create textures for picking
16
+ this.colorTexture = this.device.createTexture({
17
+ size: { width, height },
18
+ format: 'r32uint',
19
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
20
+ });
21
+ this.depthTexture = this.device.createTexture({
22
+ size: { width, height },
23
+ format: 'depth24plus',
24
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
25
+ });
26
+ // Create uniform buffer for viewProj matrix only (16 floats = 64 bytes)
27
+ this.uniformBuffer = this.device.createBuffer({
28
+ size: 64,
29
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
30
+ });
31
+ // Create storage buffer for expressIds (one u32 per mesh, +1 encoding)
32
+ // We'll upload all expressIds at once, then use instance_index to look them up
33
+ this.expressIdBuffer = this.device.createBuffer({
34
+ size: this.maxMeshes * 4, // 4 bytes per u32
35
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
36
+ });
37
+ // Create picker shader that uses storage buffer for per-object expressId
38
+ const shaderModule = this.device.createShaderModule({
39
+ code: `
40
+ struct Uniforms {
41
+ viewProj: mat4x4<f32>,
42
+ }
43
+ @binding(0) @group(0) var<uniform> uniforms: Uniforms;
44
+ @binding(1) @group(0) var<storage, read> expressIds: array<u32>;
45
+
46
+ struct VertexInput {
47
+ @location(0) position: vec3<f32>,
48
+ @location(1) normal: vec3<f32>,
49
+ }
50
+
51
+ struct VertexOutput {
52
+ @builtin(position) position: vec4<f32>,
53
+ @location(0) @interpolate(flat) objectId: u32,
54
+ }
55
+
56
+ @vertex
57
+ fn vs_main(input: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput {
58
+ var output: VertexOutput;
59
+ // Identity transform - positions are already in world space
60
+ output.position = uniforms.viewProj * vec4<f32>(input.position, 1.0);
61
+ // Look up expressId from storage buffer using instance index
62
+ output.objectId = expressIds[instanceIndex];
63
+ return output;
64
+ }
65
+
66
+ @fragment
67
+ fn fs_main(input: VertexOutput) -> @location(0) u32 {
68
+ return input.objectId;
69
+ }
70
+ `,
71
+ });
72
+ this.pipeline = this.device.createRenderPipeline({
73
+ layout: 'auto',
74
+ vertex: {
75
+ module: shaderModule,
76
+ entryPoint: 'vs_main',
77
+ buffers: [
78
+ {
79
+ arrayStride: 24,
80
+ attributes: [
81
+ { shaderLocation: 0, offset: 0, format: 'float32x3' },
82
+ { shaderLocation: 1, offset: 12, format: 'float32x3' },
83
+ ],
84
+ },
85
+ ],
86
+ },
87
+ fragment: {
88
+ module: shaderModule,
89
+ entryPoint: 'fs_main',
90
+ targets: [{ format: 'r32uint' }],
91
+ },
92
+ primitive: {
93
+ topology: 'triangle-list',
94
+ cullMode: 'back',
95
+ },
96
+ depthStencil: {
97
+ format: 'depth24plus',
98
+ depthWriteEnabled: true,
99
+ depthCompare: 'less',
100
+ },
101
+ });
102
+ // Create bind group using the pipeline's auto-generated layout
103
+ // IMPORTANT: Must use getBindGroupLayout() when pipeline uses layout: 'auto'
104
+ this.bindGroup = this.device.createBindGroup({
105
+ layout: this.pipeline.getBindGroupLayout(0),
106
+ entries: [
107
+ {
108
+ binding: 0,
109
+ resource: { buffer: this.uniformBuffer },
110
+ },
111
+ {
112
+ binding: 1,
113
+ resource: { buffer: this.expressIdBuffer },
114
+ },
115
+ ],
116
+ });
117
+ }
118
+ /**
119
+ * Pick object at screen coordinates
120
+ */
121
+ async pick(x, y, width, height, meshes, viewProj) {
122
+ // Resize textures if needed
123
+ if (this.colorTexture.width !== width || this.colorTexture.height !== height) {
124
+ this.colorTexture.destroy();
125
+ this.depthTexture.destroy();
126
+ this.colorTexture = this.device.createTexture({
127
+ size: { width, height },
128
+ format: 'r32uint',
129
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
130
+ });
131
+ this.depthTexture = this.device.createTexture({
132
+ size: { width, height },
133
+ format: 'depth24plus',
134
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
135
+ });
136
+ }
137
+ // Recreate texture views each time to avoid reuse issues
138
+ // WebGPU texture views cannot be reused after being submitted
139
+ const colorView = this.colorTexture.createView();
140
+ const depthView = this.depthTexture.createView();
141
+ // Render picker pass
142
+ const encoder = this.device.createCommandEncoder();
143
+ const pass = encoder.beginRenderPass({
144
+ colorAttachments: [
145
+ {
146
+ view: colorView,
147
+ loadOp: 'clear',
148
+ clearValue: { r: 0, g: 0, b: 0, a: 0 },
149
+ storeOp: 'store',
150
+ },
151
+ ],
152
+ depthStencilAttachment: {
153
+ view: depthView,
154
+ depthClearValue: 1.0,
155
+ depthLoadOp: 'clear',
156
+ depthStoreOp: 'store',
157
+ },
158
+ });
159
+ // Upload viewProj matrix to uniform buffer (once for all meshes)
160
+ this.device.queue.writeBuffer(this.uniformBuffer, 0, viewProj);
161
+ // Build expressId array for all meshes (expressId + 1, so 0 = no hit)
162
+ const expressIdArray = new Uint32Array(meshes.length);
163
+ for (let i = 0; i < meshes.length; i++) {
164
+ const mesh = meshes[i];
165
+ if (mesh) {
166
+ expressIdArray[i] = mesh.expressId + 1;
167
+ }
168
+ }
169
+ this.device.queue.writeBuffer(this.expressIdBuffer, 0, expressIdArray);
170
+ pass.setPipeline(this.pipeline);
171
+ pass.setBindGroup(0, this.bindGroup);
172
+ // Draw each mesh with its index as the first instance
173
+ // The shader will use this instance_index to look up the expressId
174
+ for (let i = 0; i < meshes.length; i++) {
175
+ const mesh = meshes[i];
176
+ if (!mesh)
177
+ continue;
178
+ pass.setVertexBuffer(0, mesh.vertexBuffer);
179
+ pass.setIndexBuffer(mesh.indexBuffer, 'uint32');
180
+ // Draw 1 instance, starting at instance i (so instance_index = i in shader)
181
+ pass.drawIndexed(mesh.indexCount, 1, 0, 0, i);
182
+ }
183
+ pass.end();
184
+ // Read pixel at click position
185
+ // WebGPU requires bytesPerRow to be a multiple of 256
186
+ const BYTES_PER_ROW = 256;
187
+ const readBuffer = this.device.createBuffer({
188
+ size: BYTES_PER_ROW,
189
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
190
+ });
191
+ encoder.copyTextureToBuffer({
192
+ texture: this.colorTexture,
193
+ origin: { x: Math.floor(x), y: Math.floor(y), z: 0 },
194
+ }, {
195
+ buffer: readBuffer,
196
+ bytesPerRow: BYTES_PER_ROW,
197
+ rowsPerImage: 1,
198
+ }, { width: 1, height: 1 });
199
+ this.device.queue.submit([encoder.finish()]);
200
+ // GPUMapMode.READ = 1 (WebGPU spec)
201
+ await readBuffer.mapAsync(1); // GPUMapMode.READ
202
+ const data = new Uint32Array(readBuffer.getMappedRange());
203
+ const objectId = data[0];
204
+ readBuffer.unmap();
205
+ readBuffer.destroy();
206
+ // objectId is expressId + 1 (so 0 = no hit)
207
+ // Return expressId directly
208
+ return objectId > 0 ? objectId - 1 : null;
209
+ }
210
+ updateUniforms(viewProj) {
211
+ // Update viewProj matrix only
212
+ this.device.queue.writeBuffer(this.uniformBuffer, 0, viewProj);
213
+ }
214
+ }
215
+ //# sourceMappingURL=picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.js","sourceRoot":"","sources":["../src/picker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * WebGPU render pipeline setup
3
+ */
4
+ import { WebGPUDevice } from './device.js';
5
+ export declare class RenderPipeline {
6
+ private device;
7
+ private pipeline;
8
+ private depthTexture;
9
+ private depthTextureView;
10
+ private uniformBuffer;
11
+ private bindGroup;
12
+ private currentWidth;
13
+ private currentHeight;
14
+ constructor(device: WebGPUDevice, width?: number, height?: number);
15
+ /**
16
+ * Update uniform buffer with camera matrices, PBR material, section plane, and selection state
17
+ */
18
+ updateUniforms(viewProj: Float32Array, model: Float32Array, color?: [number, number, number, number], material?: {
19
+ metallic?: number;
20
+ roughness?: number;
21
+ }, sectionPlane?: {
22
+ normal: [number, number, number];
23
+ distance: number;
24
+ enabled: boolean;
25
+ }, isSelected?: boolean): void;
26
+ /**
27
+ * Check if resize is needed
28
+ */
29
+ needsResize(width: number, height: number): boolean;
30
+ /**
31
+ * Resize depth texture
32
+ */
33
+ resize(width: number, height: number): void;
34
+ getPipeline(): GPURenderPipeline;
35
+ getDepthTextureView(): GPUTextureView;
36
+ getBindGroup(): GPUBindGroup;
37
+ getBindGroupLayout(): GPUBindGroupLayout;
38
+ getUniformBufferSize(): number;
39
+ }
40
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,gBAAgB,CAAiB;IACzC,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,aAAa,CAAS;gBAElB,MAAM,EAAE,YAAY,EAAE,KAAK,GAAE,MAAU,EAAE,MAAM,GAAE,MAAU;IAmLvE;;OAEG;IACH,cAAc,CACV,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACxC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EACpD,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EACvF,UAAU,CAAC,EAAE,OAAO,GACrB,IAAI;IA+CP;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAInD;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAe3C,WAAW,IAAI,iBAAiB;IAIhC,mBAAmB,IAAI,cAAc;IAIrC,YAAY,IAAI,YAAY;IAI5B,kBAAkB,IAAI,kBAAkB;IAIxC,oBAAoB,IAAI,MAAM;CAGjC"}
@@ -0,0 +1,266 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ export class RenderPipeline {
5
+ device;
6
+ pipeline;
7
+ depthTexture;
8
+ depthTextureView;
9
+ uniformBuffer;
10
+ bindGroup;
11
+ currentWidth;
12
+ currentHeight;
13
+ constructor(device, width = 1, height = 1) {
14
+ this.currentWidth = width;
15
+ this.currentHeight = height;
16
+ this.device = device.getDevice();
17
+ const format = device.getFormat();
18
+ // Create depth texture
19
+ this.depthTexture = this.device.createTexture({
20
+ size: { width, height },
21
+ format: 'depth24plus',
22
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
23
+ });
24
+ this.depthTextureView = this.depthTexture.createView();
25
+ // Create uniform buffer for camera matrices, PBR material, and section plane
26
+ // Layout: viewProj (64 bytes) + model (64 bytes) + baseColor (16 bytes) + metallicRoughness (8 bytes) +
27
+ // sectionPlane (16 bytes: vec3 normal + float position) + flags (16 bytes: u32 isSelected + u32 sectionEnabled + padding) = 192 bytes
28
+ // WebGPU requires uniform buffers to be aligned to 16 bytes
29
+ this.uniformBuffer = this.device.createBuffer({
30
+ size: 192, // 12 * 16 bytes = properly aligned
31
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
32
+ });
33
+ // Create shader module with PBR lighting, section plane clipping, and selection outline
34
+ const shaderModule = this.device.createShaderModule({
35
+ code: `
36
+ struct Uniforms {
37
+ viewProj: mat4x4<f32>,
38
+ model: mat4x4<f32>,
39
+ baseColor: vec4<f32>,
40
+ metallicRoughness: vec2<f32>, // x = metallic, y = roughness
41
+ _padding1: vec2<f32>,
42
+ sectionPlane: vec4<f32>, // xyz = plane normal, w = plane distance
43
+ flags: vec4<u32>, // x = isSelected, y = sectionEnabled, z,w = reserved
44
+ }
45
+ @binding(0) @group(0) var<uniform> uniforms: Uniforms;
46
+
47
+ struct VertexInput {
48
+ @location(0) position: vec3<f32>,
49
+ @location(1) normal: vec3<f32>,
50
+ }
51
+
52
+ struct VertexOutput {
53
+ @builtin(position) position: vec4<f32>,
54
+ @location(0) worldPos: vec3<f32>,
55
+ @location(1) normal: vec3<f32>,
56
+ @location(2) @interpolate(flat) objectId: u32,
57
+ }
58
+
59
+ @vertex
60
+ fn vs_main(input: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput {
61
+ var output: VertexOutput;
62
+ let worldPos = uniforms.model * vec4<f32>(input.position, 1.0);
63
+ output.position = uniforms.viewProj * worldPos;
64
+ output.worldPos = worldPos.xyz;
65
+ output.normal = normalize((uniforms.model * vec4<f32>(input.normal, 0.0)).xyz);
66
+ output.objectId = instanceIndex;
67
+ return output;
68
+ }
69
+
70
+ // PBR helper functions
71
+ fn fresnelSchlick(cosTheta: f32, F0: vec3<f32>) -> vec3<f32> {
72
+ return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
73
+ }
74
+
75
+ fn distributionGGX(NdotH: f32, roughness: f32) -> f32 {
76
+ let a = roughness * roughness;
77
+ let a2 = a * a;
78
+ let NdotH2 = NdotH * NdotH;
79
+ let num = a2;
80
+ let denomBase = (NdotH2 * (a2 - 1.0) + 1.0);
81
+ let denom = 3.14159265 * denomBase * denomBase;
82
+ return num / max(denom, 0.0000001);
83
+ }
84
+
85
+ fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 {
86
+ let r = (roughness + 1.0);
87
+ let k = (r * r) / 8.0;
88
+ let num = NdotV;
89
+ let denom = NdotV * (1.0 - k) + k;
90
+ return num / max(denom, 0.0000001);
91
+ }
92
+
93
+ fn geometrySmith(NdotV: f32, NdotL: f32, roughness: f32) -> f32 {
94
+ let ggx2 = geometrySchlickGGX(NdotV, roughness);
95
+ let ggx1 = geometrySchlickGGX(NdotL, roughness);
96
+ return ggx1 * ggx2;
97
+ }
98
+
99
+ @fragment
100
+ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
101
+ // Section plane clipping
102
+ if (uniforms.flags.y == 1u) {
103
+ let planeNormal = uniforms.sectionPlane.xyz;
104
+ let planeDistance = uniforms.sectionPlane.w;
105
+ let distToPlane = dot(input.worldPos, planeNormal) - planeDistance;
106
+ if (distToPlane > 0.0) {
107
+ discard;
108
+ }
109
+ }
110
+
111
+ let N = normalize(input.normal);
112
+ let L = normalize(vec3<f32>(0.5, 1.0, 0.3)); // Light direction
113
+
114
+ let NdotL = max(dot(N, L), 0.0);
115
+
116
+ var baseColor = uniforms.baseColor.rgb;
117
+
118
+ // Simple diffuse lighting with ambient
119
+ let ambient = 0.3;
120
+ let diffuse = NdotL * 0.7;
121
+
122
+ var color = baseColor * (ambient + diffuse);
123
+
124
+ // Selection highlight - add glow/fresnel effect
125
+ if (uniforms.flags.x == 1u) {
126
+ // Calculate view direction for fresnel effect
127
+ let V = normalize(-input.worldPos); // Assuming camera at origin (simplified)
128
+ let NdotV = max(dot(N, V), 0.0);
129
+
130
+ // Fresnel-like edge highlight for selection
131
+ let fresnel = pow(1.0 - NdotV, 2.0);
132
+ let highlightColor = vec3<f32>(0.3, 0.6, 1.0); // Blue highlight
133
+ color = mix(color, highlightColor, fresnel * 0.5 + 0.2);
134
+ }
135
+
136
+ // Gamma correction (IFC colors are typically in sRGB)
137
+ color = pow(color, vec3<f32>(1.0 / 2.2));
138
+
139
+ return vec4<f32>(color, uniforms.baseColor.a);
140
+ }
141
+ `,
142
+ });
143
+ // Create render pipeline
144
+ this.pipeline = this.device.createRenderPipeline({
145
+ layout: 'auto',
146
+ vertex: {
147
+ module: shaderModule,
148
+ entryPoint: 'vs_main',
149
+ buffers: [
150
+ {
151
+ arrayStride: 24, // 6 floats * 4 bytes
152
+ attributes: [
153
+ { shaderLocation: 0, offset: 0, format: 'float32x3' }, // position
154
+ { shaderLocation: 1, offset: 12, format: 'float32x3' }, // normal
155
+ ],
156
+ },
157
+ ],
158
+ },
159
+ fragment: {
160
+ module: shaderModule,
161
+ entryPoint: 'fs_main',
162
+ targets: [{ format }],
163
+ },
164
+ primitive: {
165
+ topology: 'triangle-list',
166
+ cullMode: 'none', // Disable culling to debug - IFC winding order varies
167
+ },
168
+ depthStencil: {
169
+ format: 'depth24plus',
170
+ depthWriteEnabled: true,
171
+ depthCompare: 'less',
172
+ },
173
+ });
174
+ // Create bind group using the pipeline's auto-generated layout
175
+ // IMPORTANT: Must use getBindGroupLayout() when pipeline uses layout: 'auto'
176
+ this.bindGroup = this.device.createBindGroup({
177
+ layout: this.pipeline.getBindGroupLayout(0),
178
+ entries: [
179
+ {
180
+ binding: 0,
181
+ resource: { buffer: this.uniformBuffer },
182
+ },
183
+ ],
184
+ });
185
+ }
186
+ /**
187
+ * Update uniform buffer with camera matrices, PBR material, section plane, and selection state
188
+ */
189
+ updateUniforms(viewProj, model, color, material, sectionPlane, isSelected) {
190
+ // Create buffer with proper alignment:
191
+ // viewProj (16 floats) + model (16 floats) + baseColor (4 floats) + metallicRoughness (2 floats) + padding (2 floats)
192
+ // + sectionPlane (4 floats) + flags (4 u32) = 48 floats = 192 bytes
193
+ const buffer = new Float32Array(48);
194
+ const flagBuffer = new Uint32Array(buffer.buffer, 176, 4); // flags at byte 176
195
+ // viewProj: mat4x4<f32> at offset 0 (16 floats)
196
+ buffer.set(viewProj, 0);
197
+ // model: mat4x4<f32> at offset 16 (16 floats)
198
+ buffer.set(model, 16);
199
+ // baseColor: vec4<f32> at offset 32 (4 floats)
200
+ if (color) {
201
+ buffer.set(color, 32);
202
+ }
203
+ else {
204
+ // Default white color
205
+ buffer.set([1.0, 1.0, 1.0, 1.0], 32);
206
+ }
207
+ // metallicRoughness: vec2<f32> at offset 36 (2 floats)
208
+ const metallic = material?.metallic ?? 0.0;
209
+ const roughness = material?.roughness ?? 0.6;
210
+ buffer[36] = metallic;
211
+ buffer[37] = roughness;
212
+ // padding at offset 38-39 (2 floats)
213
+ // sectionPlane: vec4<f32> at offset 40 (4 floats - normal xyz + distance w)
214
+ if (sectionPlane) {
215
+ buffer[40] = sectionPlane.normal[0];
216
+ buffer[41] = sectionPlane.normal[1];
217
+ buffer[42] = sectionPlane.normal[2];
218
+ buffer[43] = sectionPlane.distance;
219
+ }
220
+ // flags: vec4<u32> at offset 44 (4 u32 - using flagBuffer view)
221
+ flagBuffer[0] = isSelected ? 1 : 0; // isSelected
222
+ flagBuffer[1] = sectionPlane?.enabled ? 1 : 0; // sectionEnabled
223
+ flagBuffer[2] = 0; // reserved
224
+ flagBuffer[3] = 0; // reserved
225
+ // Write the buffer
226
+ this.device.queue.writeBuffer(this.uniformBuffer, 0, buffer);
227
+ }
228
+ /**
229
+ * Check if resize is needed
230
+ */
231
+ needsResize(width, height) {
232
+ return this.currentWidth !== width || this.currentHeight !== height;
233
+ }
234
+ /**
235
+ * Resize depth texture
236
+ */
237
+ resize(width, height) {
238
+ if (width <= 0 || height <= 0)
239
+ return;
240
+ this.currentWidth = width;
241
+ this.currentHeight = height;
242
+ this.depthTexture.destroy();
243
+ this.depthTexture = this.device.createTexture({
244
+ size: { width, height },
245
+ format: 'depth24plus',
246
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
247
+ });
248
+ this.depthTextureView = this.depthTexture.createView();
249
+ }
250
+ getPipeline() {
251
+ return this.pipeline;
252
+ }
253
+ getDepthTextureView() {
254
+ return this.depthTextureView;
255
+ }
256
+ getBindGroup() {
257
+ return this.bindGroup;
258
+ }
259
+ getBindGroupLayout() {
260
+ return this.pipeline.getBindGroupLayout(0);
261
+ }
262
+ getUniformBufferSize() {
263
+ return 192; // 48 floats * 4 bytes
264
+ }
265
+ }
266
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Post-processing effects for Blender-quality rendering
3
+ * Includes SSAO, tone mapping, and edge enhancement
4
+ */
5
+ import { WebGPUDevice } from './device.js';
6
+ export interface PostProcessorOptions {
7
+ enableSSAO?: boolean;
8
+ enableEdgeEnhancement?: boolean;
9
+ ssaoRadius?: number;
10
+ ssaoIntensity?: number;
11
+ }
12
+ /**
13
+ * Post-processing pipeline
14
+ * Currently implements enhanced tone mapping in shader
15
+ * SSAO and edge enhancement can be added as separate passes
16
+ */
17
+ export declare class PostProcessor {
18
+ private _device;
19
+ private options;
20
+ constructor(device: WebGPUDevice, options?: PostProcessorOptions);
21
+ /**
22
+ * Apply post-processing effects
23
+ * Currently tone mapping is handled in the main shader
24
+ * This class provides infrastructure for future SSAO and edge detection
25
+ */
26
+ apply(_inputTexture: GPUTexture, _outputTexture: GPUTexture): void;
27
+ /**
28
+ * Update post-processing options
29
+ */
30
+ updateOptions(options: Partial<PostProcessorOptions>): void;
31
+ }
32
+ //# sourceMappingURL=post-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-processor.d.ts","sourceRoot":"","sources":["../src/post-processor.ts"],"names":[],"mappings":"AAIA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,oBAAoB;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,qBAAa,aAAa;IACtB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,OAAO,CAAuB;gBAE1B,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,oBAAyB;IAWpE;;;;OAIG;IACH,KAAK,CAAC,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,GAAG,IAAI;IASlE;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,IAAI;CAG9D"}
@@ -0,0 +1,42 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Post-processing pipeline
6
+ * Currently implements enhanced tone mapping in shader
7
+ * SSAO and edge enhancement can be added as separate passes
8
+ */
9
+ export class PostProcessor {
10
+ _device;
11
+ options;
12
+ constructor(device, options = {}) {
13
+ this._device = device;
14
+ this.options = {
15
+ enableSSAO: false,
16
+ enableEdgeEnhancement: false,
17
+ ssaoRadius: 0.5,
18
+ ssaoIntensity: 1.0,
19
+ ...options,
20
+ };
21
+ }
22
+ /**
23
+ * Apply post-processing effects
24
+ * Currently tone mapping is handled in the main shader
25
+ * This class provides infrastructure for future SSAO and edge detection
26
+ */
27
+ apply(_inputTexture, _outputTexture) {
28
+ // Tone mapping is already applied in the main PBR shader
29
+ // SSAO and edge enhancement would be implemented here as separate passes
30
+ // Reserved for future use
31
+ void this._device;
32
+ void _inputTexture;
33
+ void _outputTexture;
34
+ }
35
+ /**
36
+ * Update post-processing options
37
+ */
38
+ updateOptions(options) {
39
+ this.options = { ...this.options, ...options };
40
+ }
41
+ }
42
+ //# sourceMappingURL=post-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-processor.js","sourceRoot":"","sources":["../src/post-processor.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAgB/D;;;;GAIG;AACH,MAAM,OAAO,aAAa;IACd,OAAO,CAAe;IACtB,OAAO,CAAuB;IAEtC,YAAY,MAAoB,EAAE,UAAgC,EAAE;QAChE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG;YACX,UAAU,EAAE,KAAK;YACjB,qBAAqB,EAAE,KAAK;YAC5B,UAAU,EAAE,GAAG;YACf,aAAa,EAAE,GAAG;YAClB,GAAG,OAAO;SACb,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAyB,EAAE,cAA0B;QACvD,yDAAyD;QACzD,yEAAyE;QACzE,0BAA0B;QAC1B,KAAK,IAAI,CAAC,OAAO,CAAC;QAClB,KAAK,aAAa,CAAC;QACnB,KAAK,cAAc,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,OAAsC;QAChD,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IACnD,CAAC;CACJ"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Scene graph and mesh management
3
+ */
4
+ import type { Mesh } from './types.js';
5
+ export declare class Scene {
6
+ private meshes;
7
+ /**
8
+ * Add mesh to scene
9
+ */
10
+ addMesh(mesh: Mesh): void;
11
+ /**
12
+ * Get all meshes
13
+ */
14
+ getMeshes(): Mesh[];
15
+ /**
16
+ * Clear scene
17
+ */
18
+ clear(): void;
19
+ /**
20
+ * Calculate bounding box
21
+ */
22
+ getBounds(): {
23
+ min: {
24
+ x: number;
25
+ y: number;
26
+ z: number;
27
+ };
28
+ max: {
29
+ x: number;
30
+ y: number;
31
+ z: number;
32
+ };
33
+ } | null;
34
+ }
35
+ //# sourceMappingURL=scene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAc;IAE5B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIzB;;OAEG;IACH,SAAS,IAAI,IAAI,EAAE;IAInB;;OAEG;IACH,KAAK,IAAI,IAAI;IAYb;;OAEG;IACH,SAAS,IAAI;QAAE,GAAG,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,GAAG,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAAG,IAAI;CAU3G"}