@rings-webgpu/core 1.0.42 → 1.0.44

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.
@@ -1686,21 +1686,47 @@
1686
1686
  this.adapter = await navigator.gpu.requestAdapter({
1687
1687
  powerPreference: "high-performance"
1688
1688
  // 或 low-power
1689
+ // xrCompatible: canvasConfig?.xrCompatible, // 可选:如果需要 XR 支持
1689
1690
  });
1690
1691
  if (this.adapter == null) {
1691
1692
  throw new Error("Your browser does not support WebGPU!");
1692
1693
  }
1694
+ const requiredFeatures = [];
1695
+ const requireFeature = (feature) => {
1696
+ const supported = this.adapter.features.has(feature);
1697
+ if (supported) {
1698
+ requiredFeatures.push(feature);
1699
+ }
1700
+ return supported;
1701
+ };
1702
+ requireFeature("bgra8unorm-storage");
1703
+ requireFeature("depth-clip-control");
1704
+ requireFeature("depth32float-stencil8");
1705
+ requireFeature("indirect-first-instance");
1706
+ requireFeature("rg11b10ufloat-renderable");
1707
+ requireFeature("float32-filterable");
1708
+ requireFeature("float32-blendable");
1709
+ requireFeature("timestamp-query");
1710
+ requireFeature("shader-f16");
1711
+ requireFeature("clip-distances");
1712
+ requireFeature("texture-compression-bc");
1713
+ requireFeature("texture-compression-etc2");
1714
+ requireFeature("texture-compression-astc");
1715
+ const adapterLimits = this.adapter?.limits;
1716
+ const requiredLimits = {};
1717
+ if (adapterLimits) {
1718
+ for (const limitName in adapterLimits) {
1719
+ if (limitName === "minSubgroupSize" || limitName === "maxSubgroupSize") {
1720
+ continue;
1721
+ }
1722
+ requiredLimits[limitName] = adapterLimits[limitName];
1723
+ }
1724
+ }
1693
1725
  this.device = await this.adapter.requestDevice({
1694
- requiredFeatures: [
1695
- "bgra8unorm-storage",
1696
- "depth-clip-control",
1697
- "depth32float-stencil8",
1698
- "indirect-first-instance",
1699
- "rg11b10ufloat-renderable"
1700
- ],
1701
- requiredLimits: {
1702
- minUniformBufferOffsetAlignment: 256,
1703
- maxStorageBufferBindingSize: this.adapter.limits.maxStorageBufferBindingSize
1726
+ requiredFeatures,
1727
+ requiredLimits,
1728
+ defaultQueue: {
1729
+ label: "RingsDefaultQueue"
1704
1730
  }
1705
1731
  });
1706
1732
  if (this.device == null) {
@@ -1708,15 +1734,18 @@
1708
1734
  }
1709
1735
  this._pixelRatio = this.canvasConfig?.devicePixelRatio || window.devicePixelRatio || 1;
1710
1736
  this._pixelRatio = Math.min(this._pixelRatio, 2);
1711
- this.device.label = "device";
1737
+ this.device.label = "RingsWebGPUDevice";
1712
1738
  this.presentationFormat = navigator.gpu.getPreferredCanvasFormat();
1713
1739
  this.context = this.canvas.getContext("webgpu");
1714
1740
  this.context.configure({
1715
1741
  device: this.device,
1716
1742
  format: this.presentationFormat,
1717
- usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
1743
+ // RENDER_ATTACHMENT is required, COPY_SRC allows scene grab/copy operations
1744
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
1718
1745
  alphaMode: "premultiplied",
1719
- colorSpace: `srgb`
1746
+ colorSpace: "srgb"
1747
+ // Optional: viewFormats can be added here if needed for SRGB views
1748
+ // viewFormats: [this.presentationFormat + '-srgb']
1720
1749
  });
1721
1750
  this._resizeEvent = new CResizeEvent(CResizeEvent.RESIZE, {
1722
1751
  width: this.windowWidth,
@@ -22886,11 +22915,23 @@ struct InstanceData {
22886
22915
  let radius = length(vec2f((diagonal1 - diagonal2) * 0.5, offDiagonal));
22887
22916
  let lambda1 = mid + radius;
22888
22917
  let lambda2 = max(mid - radius, MIN_LAMBDA);
22918
+
22919
+ let vmin = min(MAX_SPLAT_SIZE, min(viewport.x, viewport.y));
22920
+ let l1 = 2.0 * min(sqrt(2.0 * lambda1), vmin);
22921
+ let l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);
22922
+
22923
+ // if (l1 < 2.0 && l2 < 2.0) {
22924
+ // return discardSplat();
22925
+ // }
22926
+
22927
+ let centerProj = projMat * vec4f(splat_cam, 1.0);
22928
+ let c = centerProj.ww * vec2f(1.0 / viewport.x, 1.0 / viewport.y);
22929
+
22889
22930
  let diagonalVector = normalize(vec2f(offDiagonal, lambda1 - diagonal1));
22890
22931
 
22891
22932
  // Calculate axis vectors with size clamping
22892
- let v1 = min(sqrt(2.0 * lambda1), MAX_SPLAT_SIZE) * diagonalVector;
22893
- let v2 = min(sqrt(2.0 * lambda2), MAX_SPLAT_SIZE) * vec2f(diagonalVector.y, -diagonalVector.x);
22933
+ let v1 = l1 * diagonalVector;
22934
+ let v2 = l2 * vec2f(diagonalVector.y, -diagonalVector.x);
22894
22935
 
22895
22936
  // WebGPU Y-axis flip: WebGPU NDC Y goes from top(-1) to bottom(1), opposite of WebGL
22896
22937
  return vec4f(v1.x, -v1.y, v2.x, -v2.y);
@@ -22956,11 +22997,13 @@ struct InstanceData {
22956
22997
  let v1v2 = calcV1V2(splat_cam.xyz, splatData.covA, splatData.covB, W, viewport, matrix_projection);
22957
22998
 
22958
22999
  // Calculate scale based on alpha (optimized formula)
22959
- let scale = min(1.0, sqrt(LOG_255 + log(color.a)) * 0.5);
23000
+ let t = pow(splat_cam.z + 0.5, 5);
23001
+ let scale = min(1.0, sqrt(-log(1.0 / (255.0 * color.a))) / 2.0);
22960
23002
 
22961
23003
  // Apply visBoost (size multiplier)
22962
23004
  let visBoost = materialUniform.tex_params.w;
22963
- let v1v2_scaled = v1v2 * (scale * visBoost);
23005
+ let expt = exp(-1.0 / t);
23006
+ let v1v2_scaled = v1v2 * (scale * visBoost * expt);
22964
23007
 
22965
23008
  // Pixel coverage culling (vectorized squared length calculation)
22966
23009
  let v1v2_sq = v1v2_scaled * v1v2_scaled;
@@ -22994,7 +23037,7 @@ struct InstanceData {
22994
23037
 
22995
23038
  var o: VSOut;
22996
23039
  o.member = splat_proj + vec4f(offset, 0.0, 0.0);
22997
- o.vTexCoord = vertex_pos * (scale * 0.5);
23040
+ o.vTexCoord = vertex_pos * (scale);
22998
23041
  o.vColor = color;
22999
23042
 
23000
23043
  return o;
@@ -23008,16 +23051,30 @@ struct InstanceData {
23008
23051
 
23009
23052
  // Constants
23010
23053
  const ALPHA_THRESHOLD: f32 = 0.00392156863; // 1.0 / 255.0
23011
- const GAUSSIAN_SCALE: f32 = 4.0;
23054
+ // const GAUSSIAN_SCALE: f32 = 4.0;
23055
+ const EXP4 = exp(-4.0);
23056
+ const INV_EXP4 = 1.0 / (1.0 - EXP4);
23057
+
23058
+ fn normExp(x: f32) -> f32 {
23059
+ return (exp(x * -4.0) - EXP4) * INV_EXP4;
23060
+ }
23012
23061
 
23013
23062
  // === evalSplat() - optimized gaussian evaluation ===
23014
23063
  fn evalSplat(texCoord: vec2f, color: vec4f) -> vec4f {
23015
23064
  let A = dot(texCoord, texCoord);
23065
+
23066
+ if (A > 1.0) {
23067
+ discard;
23068
+ // return vec4f(1.0, 0.0, 0.0, 0.5);
23069
+ }
23016
23070
 
23017
23071
  // Branch-less optimization using select
23018
- let gaussian = exp(-A * GAUSSIAN_SCALE) * color.a;
23019
- let alpha = select(gaussian, 0.0, A > 1.0 || gaussian < ALPHA_THRESHOLD);
23020
-
23072
+ var alpha = normExp(A) * color.a;
23073
+
23074
+ if (alpha < ALPHA_THRESHOLD) {
23075
+ discard;
23076
+ // alpha = 0.5;
23077
+ }
23021
23078
  return vec4f(color.rgb, alpha);
23022
23079
  }
23023
23080
 
@@ -23264,8 +23321,9 @@ struct InstanceData {
23264
23321
  pass.cullMode = GPUCullMode.none;
23265
23322
  pass.shaderState.transparent = true;
23266
23323
  pass.shaderState.blendMode = BlendMode.NORMAL;
23267
- pass.shaderState.writeMasks = [15, 15];
23324
+ pass.shaderState.writeMasks = [15, 0];
23268
23325
  pass.shaderState.castReflection = false;
23326
+ pass.shaderState.depthCompare = GPUCompareFunction.less;
23269
23327
  this.addRenderPass(pass);
23270
23328
  this.setDefault();
23271
23329
  }
@@ -24014,17 +24072,17 @@ struct InstanceData {
24014
24072
  const meshPositions = new Float32Array(12 * batchSize);
24015
24073
  for (let i = 0; i < batchSize; ++i) {
24016
24074
  meshPositions.set([
24017
- -2,
24018
- -2,
24075
+ -1,
24076
+ -1,
24019
24077
  i,
24020
- 2,
24021
- -2,
24078
+ 1,
24079
+ -1,
24022
24080
  i,
24023
- 2,
24024
- 2,
24081
+ 1,
24082
+ 1,
24025
24083
  i,
24026
- -2,
24027
- 2,
24084
+ -1,
24085
+ 1,
24028
24086
  i
24029
24087
  ], i * 12);
24030
24088
  }
@@ -25368,7 +25426,6 @@ struct InstanceData {
25368
25426
  }
25369
25427
 
25370
25428
  o.color = vColor;
25371
- o.gBuffer = vec4f(0.0);
25372
25429
  return o;
25373
25430
  }
25374
25431
  `
@@ -25395,7 +25452,7 @@ struct InstanceData {
25395
25452
  pass.cullMode = GPUCullMode.none;
25396
25453
  pass.shaderState.transparent = false;
25397
25454
  pass.shaderState.blendMode = BlendMode.NORMAL;
25398
- pass.shaderState.writeMasks = [15, 15];
25455
+ pass.shaderState.writeMasks = [15, 0];
25399
25456
  pass.shaderState.castReflection = false;
25400
25457
  this.addRenderPass(pass);
25401
25458
  this.setDefault();
@@ -27488,6 +27545,8 @@ struct InstanceData {
27488
27545
  static matrixCount = 0;
27489
27546
  static lastRenderPassState;
27490
27547
  static LastCommand;
27548
+ static multiTextureViewCache = /* @__PURE__ */ new WeakMap();
27549
+ static swapchainTextureCache = { texture: null, view: null };
27491
27550
  static bindPipeline(encoder, renderShader) {
27492
27551
  if (GPUContext.lastShader != renderShader) {
27493
27552
  GPUContext.lastShader = renderShader;
@@ -27575,21 +27634,40 @@ struct InstanceData {
27575
27634
  const renderTarget = renderPassState.renderTargets[i];
27576
27635
  let att = renderPassState.renderPassDescriptor.colorAttachments[i];
27577
27636
  if (renderPassState.multisample > 0 && renderPassState.renderTargets.length == 1) {
27578
- att.view = renderPassState.multiTexture.createView();
27637
+ let multiView = this.multiTextureViewCache.get(renderPassState.multiTexture);
27638
+ if (!multiView) {
27639
+ multiView = renderPassState.multiTexture.createView();
27640
+ this.multiTextureViewCache.set(renderPassState.multiTexture, multiView);
27641
+ }
27642
+ att.view = multiView;
27579
27643
  att.resolveTarget = renderTarget.getGPUView();
27580
27644
  } else {
27581
- att.view = renderTarget.getGPUTexture().createView();
27645
+ att.view = renderTarget.getGPUView();
27582
27646
  }
27583
27647
  }
27584
27648
  return command.beginRenderPass(renderPassState.renderPassDescriptor);
27585
27649
  } else {
27586
27650
  let att0 = renderPassState.renderPassDescriptor.colorAttachments[0];
27587
27651
  if (att0) {
27652
+ const swapchainTexture = webGPUContext.context.getCurrentTexture();
27588
27653
  if (renderPassState.multisample > 0) {
27589
- att0.view = renderPassState.multiTexture.createView();
27590
- att0.resolveTarget = webGPUContext.context.getCurrentTexture().createView();
27654
+ let multiView = this.multiTextureViewCache.get(renderPassState.multiTexture);
27655
+ if (!multiView) {
27656
+ multiView = renderPassState.multiTexture.createView();
27657
+ this.multiTextureViewCache.set(renderPassState.multiTexture, multiView);
27658
+ }
27659
+ att0.view = multiView;
27660
+ if (this.swapchainTextureCache.texture !== swapchainTexture) {
27661
+ this.swapchainTextureCache.texture = swapchainTexture;
27662
+ this.swapchainTextureCache.view = swapchainTexture.createView();
27663
+ }
27664
+ att0.resolveTarget = this.swapchainTextureCache.view;
27591
27665
  } else {
27592
- att0.view = webGPUContext.context.getCurrentTexture().createView();
27666
+ if (this.swapchainTextureCache.texture !== swapchainTexture) {
27667
+ this.swapchainTextureCache.texture = swapchainTexture;
27668
+ this.swapchainTextureCache.view = swapchainTexture.createView();
27669
+ }
27670
+ att0.view = this.swapchainTextureCache.view;
27593
27671
  }
27594
27672
  }
27595
27673
  return command.beginRenderPass(renderPassState.renderPassDescriptor);
@@ -42292,7 +42370,7 @@ else if (typeof exports === 'object')
42292
42370
  }
42293
42371
  }
42294
42372
 
42295
- const version = "1.0.42";
42373
+ const version = "1.0.43";
42296
42374
 
42297
42375
  class Engine3D {
42298
42376
  /**
@@ -15,6 +15,8 @@ export declare class GPUContext {
15
15
  static matrixCount: number;
16
16
  static lastRenderPassState: RendererPassState;
17
17
  static LastCommand: GPUCommandEncoder | null;
18
+ private static multiTextureViewCache;
19
+ private static swapchainTextureCache;
18
20
  static bindPipeline(encoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderShader: RenderShaderPass): boolean;
19
21
  static bindCamera(encoder: GPURenderPassEncoder | GPURenderBundleEncoder, camera: Camera3D): void;
20
22
  static bindGeometryBuffer(encoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: GeometryBase): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rings-webgpu/core",
3
- "version": "1.0.42",
3
+ "version": "1.0.44",
4
4
  "description": "Rings webgpu Engine",
5
5
  "main": "index.js",
6
6
  "exports": {