@rings-webgpu/core 1.0.42 → 1.0.43
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/rings.es.js +50 -22
- package/dist/rings.es.js.map +3 -3
- package/dist/rings.es.max.js +115 -36
- package/dist/rings.umd.js +49 -21
- package/dist/rings.umd.js.map +3 -3
- package/dist/rings.umd.max.js +115 -36
- package/dist/types/gfx/renderJob/GPUContext.d.ts +2 -0
- package/package.json +1 -1
package/dist/rings.es.max.js
CHANGED
|
@@ -1679,21 +1679,47 @@ class Context3D extends CEventDispatcher {
|
|
|
1679
1679
|
this.adapter = await navigator.gpu.requestAdapter({
|
|
1680
1680
|
powerPreference: "high-performance"
|
|
1681
1681
|
// 或 low-power
|
|
1682
|
+
// xrCompatible: canvasConfig?.xrCompatible, // 可选:如果需要 XR 支持
|
|
1682
1683
|
});
|
|
1683
1684
|
if (this.adapter == null) {
|
|
1684
1685
|
throw new Error("Your browser does not support WebGPU!");
|
|
1685
1686
|
}
|
|
1687
|
+
const requiredFeatures = [];
|
|
1688
|
+
const requireFeature = (feature) => {
|
|
1689
|
+
const supported = this.adapter.features.has(feature);
|
|
1690
|
+
if (supported) {
|
|
1691
|
+
requiredFeatures.push(feature);
|
|
1692
|
+
}
|
|
1693
|
+
return supported;
|
|
1694
|
+
};
|
|
1695
|
+
requireFeature("bgra8unorm-storage");
|
|
1696
|
+
requireFeature("depth-clip-control");
|
|
1697
|
+
requireFeature("depth32float-stencil8");
|
|
1698
|
+
requireFeature("indirect-first-instance");
|
|
1699
|
+
requireFeature("rg11b10ufloat-renderable");
|
|
1700
|
+
requireFeature("float32-filterable");
|
|
1701
|
+
requireFeature("float32-blendable");
|
|
1702
|
+
requireFeature("timestamp-query");
|
|
1703
|
+
requireFeature("shader-f16");
|
|
1704
|
+
requireFeature("clip-distances");
|
|
1705
|
+
requireFeature("texture-compression-bc");
|
|
1706
|
+
requireFeature("texture-compression-etc2");
|
|
1707
|
+
requireFeature("texture-compression-astc");
|
|
1708
|
+
const adapterLimits = this.adapter?.limits;
|
|
1709
|
+
const requiredLimits = {};
|
|
1710
|
+
if (adapterLimits) {
|
|
1711
|
+
for (const limitName in adapterLimits) {
|
|
1712
|
+
if (limitName === "minSubgroupSize" || limitName === "maxSubgroupSize") {
|
|
1713
|
+
continue;
|
|
1714
|
+
}
|
|
1715
|
+
requiredLimits[limitName] = adapterLimits[limitName];
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1686
1718
|
this.device = await this.adapter.requestDevice({
|
|
1687
|
-
requiredFeatures
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
"
|
|
1691
|
-
"indirect-first-instance",
|
|
1692
|
-
"rg11b10ufloat-renderable"
|
|
1693
|
-
],
|
|
1694
|
-
requiredLimits: {
|
|
1695
|
-
minUniformBufferOffsetAlignment: 256,
|
|
1696
|
-
maxStorageBufferBindingSize: this.adapter.limits.maxStorageBufferBindingSize
|
|
1719
|
+
requiredFeatures,
|
|
1720
|
+
requiredLimits,
|
|
1721
|
+
defaultQueue: {
|
|
1722
|
+
label: "RingsDefaultQueue"
|
|
1697
1723
|
}
|
|
1698
1724
|
});
|
|
1699
1725
|
if (this.device == null) {
|
|
@@ -1701,15 +1727,18 @@ class Context3D extends CEventDispatcher {
|
|
|
1701
1727
|
}
|
|
1702
1728
|
this._pixelRatio = this.canvasConfig?.devicePixelRatio || window.devicePixelRatio || 1;
|
|
1703
1729
|
this._pixelRatio = Math.min(this._pixelRatio, 2);
|
|
1704
|
-
this.device.label = "
|
|
1730
|
+
this.device.label = "RingsWebGPUDevice";
|
|
1705
1731
|
this.presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
1706
1732
|
this.context = this.canvas.getContext("webgpu");
|
|
1707
1733
|
this.context.configure({
|
|
1708
1734
|
device: this.device,
|
|
1709
1735
|
format: this.presentationFormat,
|
|
1710
|
-
|
|
1736
|
+
// RENDER_ATTACHMENT is required, COPY_SRC allows scene grab/copy operations
|
|
1737
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
|
|
1711
1738
|
alphaMode: "premultiplied",
|
|
1712
|
-
colorSpace:
|
|
1739
|
+
colorSpace: "srgb"
|
|
1740
|
+
// Optional: viewFormats can be added here if needed for SRGB views
|
|
1741
|
+
// viewFormats: [this.presentationFormat + '-srgb']
|
|
1713
1742
|
});
|
|
1714
1743
|
this._resizeEvent = new CResizeEvent(CResizeEvent.RESIZE, {
|
|
1715
1744
|
width: this.windowWidth,
|
|
@@ -22879,11 +22908,23 @@ const GSplat_VS = (
|
|
|
22879
22908
|
let radius = length(vec2f((diagonal1 - diagonal2) * 0.5, offDiagonal));
|
|
22880
22909
|
let lambda1 = mid + radius;
|
|
22881
22910
|
let lambda2 = max(mid - radius, MIN_LAMBDA);
|
|
22911
|
+
|
|
22912
|
+
let vmin = min(MAX_SPLAT_SIZE, min(viewport.x, viewport.y));
|
|
22913
|
+
let l1 = 2.0 * min(sqrt(2.0 * lambda1), vmin);
|
|
22914
|
+
let l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);
|
|
22915
|
+
|
|
22916
|
+
// if (l1 < 2.0 && l2 < 2.0) {
|
|
22917
|
+
// return discardSplat();
|
|
22918
|
+
// }
|
|
22919
|
+
|
|
22920
|
+
let centerProj = projMat * vec4f(splat_cam, 1.0);
|
|
22921
|
+
let c = centerProj.ww * vec2f(1.0 / viewport.x, 1.0 / viewport.y);
|
|
22922
|
+
|
|
22882
22923
|
let diagonalVector = normalize(vec2f(offDiagonal, lambda1 - diagonal1));
|
|
22883
22924
|
|
|
22884
22925
|
// Calculate axis vectors with size clamping
|
|
22885
|
-
let v1 =
|
|
22886
|
-
let v2 =
|
|
22926
|
+
let v1 = l1 * diagonalVector;
|
|
22927
|
+
let v2 = l2 * vec2f(diagonalVector.y, -diagonalVector.x);
|
|
22887
22928
|
|
|
22888
22929
|
// WebGPU Y-axis flip: WebGPU NDC Y goes from top(-1) to bottom(1), opposite of WebGL
|
|
22889
22930
|
return vec4f(v1.x, -v1.y, v2.x, -v2.y);
|
|
@@ -22949,11 +22990,13 @@ const GSplat_VS = (
|
|
|
22949
22990
|
let v1v2 = calcV1V2(splat_cam.xyz, splatData.covA, splatData.covB, W, viewport, matrix_projection);
|
|
22950
22991
|
|
|
22951
22992
|
// Calculate scale based on alpha (optimized formula)
|
|
22952
|
-
let
|
|
22993
|
+
let t = pow(splat_cam.z + 0.5, 5);
|
|
22994
|
+
let scale = min(1.0, sqrt(-log(1.0 / (255.0 * color.a))) / 2.0);
|
|
22953
22995
|
|
|
22954
22996
|
// Apply visBoost (size multiplier)
|
|
22955
22997
|
let visBoost = materialUniform.tex_params.w;
|
|
22956
|
-
let
|
|
22998
|
+
let expt = exp(-1.0 / t);
|
|
22999
|
+
let v1v2_scaled = v1v2 * (scale * visBoost * expt);
|
|
22957
23000
|
|
|
22958
23001
|
// Pixel coverage culling (vectorized squared length calculation)
|
|
22959
23002
|
let v1v2_sq = v1v2_scaled * v1v2_scaled;
|
|
@@ -22987,7 +23030,7 @@ const GSplat_VS = (
|
|
|
22987
23030
|
|
|
22988
23031
|
var o: VSOut;
|
|
22989
23032
|
o.member = splat_proj + vec4f(offset, 0.0, 0.0);
|
|
22990
|
-
o.vTexCoord = vertex_pos * (scale
|
|
23033
|
+
o.vTexCoord = vertex_pos * (scale);
|
|
22991
23034
|
o.vColor = color;
|
|
22992
23035
|
|
|
22993
23036
|
return o;
|
|
@@ -23001,16 +23044,30 @@ const GSplat_FS = (
|
|
|
23001
23044
|
|
|
23002
23045
|
// Constants
|
|
23003
23046
|
const ALPHA_THRESHOLD: f32 = 0.00392156863; // 1.0 / 255.0
|
|
23004
|
-
const GAUSSIAN_SCALE: f32 = 4.0;
|
|
23047
|
+
// const GAUSSIAN_SCALE: f32 = 4.0;
|
|
23048
|
+
const EXP4 = exp(-4.0);
|
|
23049
|
+
const INV_EXP4 = 1.0 / (1.0 - EXP4);
|
|
23050
|
+
|
|
23051
|
+
fn normExp(x: f32) -> f32 {
|
|
23052
|
+
return (exp(x * -4.0) - EXP4) * INV_EXP4;
|
|
23053
|
+
}
|
|
23005
23054
|
|
|
23006
23055
|
// === evalSplat() - optimized gaussian evaluation ===
|
|
23007
23056
|
fn evalSplat(texCoord: vec2f, color: vec4f) -> vec4f {
|
|
23008
23057
|
let A = dot(texCoord, texCoord);
|
|
23058
|
+
|
|
23059
|
+
if (A > 1.0) {
|
|
23060
|
+
discard;
|
|
23061
|
+
// return vec4f(1.0, 0.0, 0.0, 0.5);
|
|
23062
|
+
}
|
|
23009
23063
|
|
|
23010
23064
|
// Branch-less optimization using select
|
|
23011
|
-
|
|
23012
|
-
|
|
23013
|
-
|
|
23065
|
+
var alpha = normExp(A) * color.a;
|
|
23066
|
+
|
|
23067
|
+
if (alpha < ALPHA_THRESHOLD) {
|
|
23068
|
+
discard;
|
|
23069
|
+
// alpha = 0.5;
|
|
23070
|
+
}
|
|
23014
23071
|
return vec4f(color.rgb, alpha);
|
|
23015
23072
|
}
|
|
23016
23073
|
|
|
@@ -23257,8 +23314,9 @@ let GSplatShader = class extends Shader {
|
|
|
23257
23314
|
pass.cullMode = GPUCullMode.none;
|
|
23258
23315
|
pass.shaderState.transparent = true;
|
|
23259
23316
|
pass.shaderState.blendMode = BlendMode.NORMAL;
|
|
23260
|
-
pass.shaderState.writeMasks = [15,
|
|
23317
|
+
pass.shaderState.writeMasks = [15, 0];
|
|
23261
23318
|
pass.shaderState.castReflection = false;
|
|
23319
|
+
pass.shaderState.depthCompare = GPUCompareFunction.less;
|
|
23262
23320
|
this.addRenderPass(pass);
|
|
23263
23321
|
this.setDefault();
|
|
23264
23322
|
}
|
|
@@ -24007,17 +24065,17 @@ class GSplatGeometry extends GeometryBase {
|
|
|
24007
24065
|
const meshPositions = new Float32Array(12 * batchSize);
|
|
24008
24066
|
for (let i = 0; i < batchSize; ++i) {
|
|
24009
24067
|
meshPositions.set([
|
|
24010
|
-
-
|
|
24011
|
-
-
|
|
24068
|
+
-1,
|
|
24069
|
+
-1,
|
|
24012
24070
|
i,
|
|
24013
|
-
|
|
24014
|
-
-
|
|
24071
|
+
1,
|
|
24072
|
+
-1,
|
|
24015
24073
|
i,
|
|
24016
|
-
|
|
24017
|
-
|
|
24074
|
+
1,
|
|
24075
|
+
1,
|
|
24018
24076
|
i,
|
|
24019
|
-
-
|
|
24020
|
-
|
|
24077
|
+
-1,
|
|
24078
|
+
1,
|
|
24021
24079
|
i
|
|
24022
24080
|
], i * 12);
|
|
24023
24081
|
}
|
|
@@ -27481,6 +27539,8 @@ class GPUContext {
|
|
|
27481
27539
|
static matrixCount = 0;
|
|
27482
27540
|
static lastRenderPassState;
|
|
27483
27541
|
static LastCommand;
|
|
27542
|
+
static multiTextureViewCache = /* @__PURE__ */ new WeakMap();
|
|
27543
|
+
static swapchainTextureCache = { texture: null, view: null };
|
|
27484
27544
|
static bindPipeline(encoder, renderShader) {
|
|
27485
27545
|
if (GPUContext.lastShader != renderShader) {
|
|
27486
27546
|
GPUContext.lastShader = renderShader;
|
|
@@ -27568,21 +27628,40 @@ class GPUContext {
|
|
|
27568
27628
|
const renderTarget = renderPassState.renderTargets[i];
|
|
27569
27629
|
let att = renderPassState.renderPassDescriptor.colorAttachments[i];
|
|
27570
27630
|
if (renderPassState.multisample > 0 && renderPassState.renderTargets.length == 1) {
|
|
27571
|
-
|
|
27631
|
+
let multiView = this.multiTextureViewCache.get(renderPassState.multiTexture);
|
|
27632
|
+
if (!multiView) {
|
|
27633
|
+
multiView = renderPassState.multiTexture.createView();
|
|
27634
|
+
this.multiTextureViewCache.set(renderPassState.multiTexture, multiView);
|
|
27635
|
+
}
|
|
27636
|
+
att.view = multiView;
|
|
27572
27637
|
att.resolveTarget = renderTarget.getGPUView();
|
|
27573
27638
|
} else {
|
|
27574
|
-
att.view = renderTarget.
|
|
27639
|
+
att.view = renderTarget.getGPUView();
|
|
27575
27640
|
}
|
|
27576
27641
|
}
|
|
27577
27642
|
return command.beginRenderPass(renderPassState.renderPassDescriptor);
|
|
27578
27643
|
} else {
|
|
27579
27644
|
let att0 = renderPassState.renderPassDescriptor.colorAttachments[0];
|
|
27580
27645
|
if (att0) {
|
|
27646
|
+
const swapchainTexture = webGPUContext.context.getCurrentTexture();
|
|
27581
27647
|
if (renderPassState.multisample > 0) {
|
|
27582
|
-
|
|
27583
|
-
|
|
27648
|
+
let multiView = this.multiTextureViewCache.get(renderPassState.multiTexture);
|
|
27649
|
+
if (!multiView) {
|
|
27650
|
+
multiView = renderPassState.multiTexture.createView();
|
|
27651
|
+
this.multiTextureViewCache.set(renderPassState.multiTexture, multiView);
|
|
27652
|
+
}
|
|
27653
|
+
att0.view = multiView;
|
|
27654
|
+
if (this.swapchainTextureCache.texture !== swapchainTexture) {
|
|
27655
|
+
this.swapchainTextureCache.texture = swapchainTexture;
|
|
27656
|
+
this.swapchainTextureCache.view = swapchainTexture.createView();
|
|
27657
|
+
}
|
|
27658
|
+
att0.resolveTarget = this.swapchainTextureCache.view;
|
|
27584
27659
|
} else {
|
|
27585
|
-
|
|
27660
|
+
if (this.swapchainTextureCache.texture !== swapchainTexture) {
|
|
27661
|
+
this.swapchainTextureCache.texture = swapchainTexture;
|
|
27662
|
+
this.swapchainTextureCache.view = swapchainTexture.createView();
|
|
27663
|
+
}
|
|
27664
|
+
att0.view = this.swapchainTextureCache.view;
|
|
27586
27665
|
}
|
|
27587
27666
|
}
|
|
27588
27667
|
return command.beginRenderPass(renderPassState.renderPassDescriptor);
|