@babylonjs/viewer
Version:
The Babylon Viewer aims to simplify a specific but common Babylon.js use case: loading, viewing, and interacting with a 3D model.
667 lines (663 loc) • 22.6 kB
JavaScript
import { ai as U32, F as F32, r as retireGpuResources, aH as bumpVisibilityEpoch, B as BU, aI as getViewProjectionMatrix, T as ThrowLiteError } from './index-By0tcgYN.esm.js';
import { syncThinInstanceGpuData } from './thin-instance-gpu-Cg2wPFiI.esm.js';
const WORKGROUP_SIZE = 64;
const PARAM_BYTES = 192;
const LOD_PARAM_BYTES = 224;
const COUNT_U32_OFFSET = 44;
const MESH_WORLD_FLOAT_OFFSET = 24;
const LOCAL_SPHERE_FLOAT_OFFSET = 40;
const BOUNDS_PAD_F32_OFFSET = 45;
const CAM_POS_DIST_F32_OFFSET = 48;
const LOD_BAND_F32_OFFSET = 52;
const INDIRECT_ARGS_BYTES = 20;
const CULL_WGSL_NO_COLOR = (
/* wgsl */
`
struct CullParams{planes:array<vec4<f32>,6>,meshWorld:mat4x4<f32>,localSphere:vec4<f32>,count:u32,boundsPad:f32};
var<storage,read> srcMatrices:array<mat4x4<f32>>;
var<storage,read_write> dstMatrices:array<mat4x4<f32>>;
var<storage,read_write> args:array<atomic<u32>>;
var<uniform> params:CullParams;
fn visible(world:mat4x4<f32>)->bool{
let center=(world*vec4<f32>(params.localSphere.xyz,1.0)).xyz;
let sx=length(world[0].xyz);
let sy=length(world[1].xyz);
let sz=length(world[2].xyz);
let radius=params.localSphere.w*max(max(sx,sy),sz)+params.boundsPad+0.0001;
for(var i=0u;i<6u;i++){
let p=params.planes[i];
if(dot(p.xyz,center)+p.w < -radius){return false;}
}
return true;
}
fn main( gid:vec3<u32>){
let i=gid.x;
if(i>=params.count){return;}
let world=params.meshWorld*srcMatrices[i];
if(!visible(world)){return;}
let outIndex=atomicAdd(&args[1],1u);
dstMatrices[outIndex]=srcMatrices[i];
}`
);
const CULL_WGSL_COLOR = `${CULL_WGSL_NO_COLOR}
var<storage,read> srcColors:array<vec4<f32>>;
var<storage,read_write> dstColors:array<vec4<f32>>;
fn mainColor( gid:vec3<u32>){
let i=gid.x;
if(i>=params.count){return;}
let world=params.meshWorld*srcMatrices[i];
if(!visible(world)){return;}
let outIndex=atomicAdd(&args[1],1u);
dstMatrices[outIndex]=srcMatrices[i];
dstColors[outIndex]=srcColors[i];
}`;
const CULL_WGSL_LOD_NO_COLOR = (
/* wgsl */
`
struct CullParams{planes:array<vec4<f32>,6>,meshWorld:mat4x4<f32>,localSphere:vec4<f32>,count:u32,boundsPad:f32,camPosDist:vec4<f32>,lodBand:f32};
var<storage,read> srcMatrices:array<mat4x4<f32>>;
var<storage,read_write> dstMatrices:array<mat4x4<f32>>;
var<storage,read_write> args:array<atomic<u32>>;
var<uniform> params:CullParams;
var<storage,read_write> lodMatrices:array<mat4x4<f32>>;
var<storage,read_write> lodArgs:array<atomic<u32>>;
fn visible(world:mat4x4<f32>)->bool{
let center=(world*vec4<f32>(params.localSphere.xyz,1.0)).xyz;
let sx=length(world[0].xyz);
let sy=length(world[1].xyz);
let sz=length(world[2].xyz);
let radius=params.localSphere.w*max(max(sx,sy),sz)+params.boundsPad+0.0001;
for(var i=0u;i<6u;i++){
let p=params.planes[i];
if(dot(p.xyz,center)+p.w < -radius){return false;}
}
return true;
}
fn isNear(world:mat4x4<f32>,i:u32)->bool{
let center=(world*vec4<f32>(params.localSphere.xyz,1.0)).xyz;
var h=i*747796405u+2891336453u;
h=((h>>((h>>28u)+4u))^h)*277803737u;
h=(h>>22u)^h;
let dither=(f32(h)*(1.0/4294967295.0)-0.5)*params.lodBand;
return distance(center,params.camPosDist.xyz)<params.camPosDist.w+dither;
}
fn mainLod( gid:vec3<u32>){
let i=gid.x;
if(i>=params.count){return;}
let world=params.meshWorld*srcMatrices[i];
if(!visible(world)){return;}
if(isNear(world,i)){
let outIndex=atomicAdd(&args[1],1u);
dstMatrices[outIndex]=srcMatrices[i];
}else{
let outIndex=atomicAdd(&lodArgs[1],1u);
lodMatrices[outIndex]=srcMatrices[i];
}
}`
);
const CULL_WGSL_LOD_COLOR = `${CULL_WGSL_LOD_NO_COLOR}
var<storage,read> srcColors:array<vec4<f32>>;
var<storage,read_write> dstColors:array<vec4<f32>>;
var<storage,read_write> lodColors:array<vec4<f32>>;
fn mainLodColor( gid:vec3<u32>){
let i=gid.x;
if(i>=params.count){return;}
let world=params.meshWorld*srcMatrices[i];
if(!visible(world)){return;}
if(isNear(world,i)){
let outIndex=atomicAdd(&args[1],1u);
dstMatrices[outIndex]=srcMatrices[i];
dstColors[outIndex]=srcColors[i];
}else{
let outIndex=atomicAdd(&lodArgs[1],1u);
lodMatrices[outIndex]=srcMatrices[i];
lodColors[outIndex]=srcColors[i];
}
}`;
let _cachedDevice = null;
let _pipelineNoColor = null;
let _pipelineColor = null;
let _pipelineLodNoColor = null;
let _pipelineLodColor = null;
let _dispatchBatches = null;
function getComputeDispatchBatch(signature) {
_dispatchBatches ??= /* @__PURE__ */ new WeakMap();
let batch = _dispatchBatches.get(signature);
if (batch) {
return batch;
}
const dispatches = [];
let count = 0;
batch = {
reset() {
count = 0;
},
flush(engine) {
if (count === 0) {
return;
}
const pass = engine._currentEncoder.beginComputePass();
let lastPipeline = null;
for (let i = 0; i < count; i++) {
const dispatch = dispatches[i];
if (dispatch.pipeline !== lastPipeline) {
pass.setPipeline(dispatch.pipeline);
lastPipeline = dispatch.pipeline;
}
pass.setBindGroup(0, dispatch.bindGroup);
pass.dispatchWorkgroups(dispatch.workgroupsX);
}
pass.end();
},
destroy() {
dispatches.length = 0;
count = 0;
_dispatchBatches?.delete(signature);
},
queue(dispatch) {
dispatches[count++] = dispatch;
}
};
_dispatchBatches.set(signature, batch);
return batch;
}
function createTiCullState() {
const paramsBytes = new ArrayBuffer(LOD_PARAM_BYTES);
return {
_capacity: 0,
_visibleMatrixBuffer: null,
_visibleColorBuffer: null,
_argsBuffer: null,
_paramsBuffer: null,
_bindGroup: null,
_srcMatrixBuffer: null,
_srcColorBuffer: null,
_hasColor: false,
_localSphereReady: false,
_localSphere: new F32(4),
_paramsBytes: paramsBytes,
_paramsF32: new F32(paramsBytes),
_paramsU32: new U32(paramsBytes),
_argsData: new U32(5),
_drawBuffers: null,
_indexCount: -1,
_active: false,
_lodActive: false,
_lodMatrixBuffer: null,
_lodColorBuffer: null,
_lodArgsBuffer: null,
_lodIndexCount: -1,
_lodArgsZeroed: false
};
}
function destroyTiCullState(state) {
state._visibleMatrixBuffer?.destroy();
state._visibleColorBuffer?.destroy();
state._argsBuffer?.destroy();
state._paramsBuffer?.destroy();
state._lodMatrixBuffer?.destroy();
state._lodColorBuffer?.destroy();
state._lodArgsBuffer?.destroy();
state._visibleMatrixBuffer = null;
state._visibleColorBuffer = null;
state._argsBuffer = null;
state._paramsBuffer = null;
state._lodMatrixBuffer = null;
state._lodColorBuffer = null;
state._lodArgsBuffer = null;
state._bindGroup = null;
state._drawBuffers = null;
}
function prepareTiCull(engine, state, mesh, gpu, ti, hasColor, context, dispatchBatch, lodMesh) {
const camera = context._camera;
if (!ti._gpuCullingEnabled || !camera || mesh.visible === false || ti.count === 0) {
return cullFallback(engine, state);
}
if (hasColor && !ti.colors) {
return cullFallback(engine, state);
}
const positions = mesh._cpuPositions;
if (!state._localSphereReady || state._localPositions !== positions || state._localBoundMin !== mesh.boundMin || state._localBoundMax !== mesh.boundMax) {
if (!computeLocalSphere(mesh, state._localSphere)) {
return cullFallback(engine, state);
}
state._localSphereReady = true;
state._localPositions = positions;
state._localBoundMin = mesh.boundMin;
state._localBoundMax = mesh.boundMax;
}
syncThinInstanceGpuData(engine, ti, hasColor);
const sourceMatrixBuffer = ti._gpuBuffer;
const sourceColorBuffer = hasColor ? ti._colorGpuBuffer : null;
if (!sourceMatrixBuffer || hasColor && !sourceColorBuffer) {
return cullFallback(engine, state);
}
const lod = lodMesh ?? null;
ensureCullBuffers(engine, state, ti._capacity, hasColor, lod !== null);
const visibleMatrixBuffer = state._visibleMatrixBuffer;
const visibleColorBuffer = hasColor ? state._visibleColorBuffer : null;
const argsBuffer = state._argsBuffer;
const paramsBuffer = state._paramsBuffer;
const pipeline = getCullPipeline(engine, hasColor, lod !== null);
if (state._bindGroup === null || state._srcMatrixBuffer !== sourceMatrixBuffer || state._srcColorBuffer !== sourceColorBuffer || state._hasColor !== hasColor) {
const entries = [
{ binding: 0, resource: { buffer: sourceMatrixBuffer } },
{ binding: 1, resource: { buffer: visibleMatrixBuffer } },
{ binding: 2, resource: { buffer: argsBuffer } },
{ binding: 3, resource: { buffer: paramsBuffer } }
];
if (hasColor) {
entries.push({ binding: 4, resource: { buffer: sourceColorBuffer } }, { binding: 5, resource: { buffer: visibleColorBuffer } });
}
if (lod) {
entries.push({ binding: 6, resource: { buffer: state._lodMatrixBuffer } }, { binding: 7, resource: { buffer: state._lodArgsBuffer } });
if (hasColor) {
entries.push({ binding: 8, resource: { buffer: state._lodColorBuffer } });
}
}
state._bindGroup = engine._device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries });
state._srcMatrixBuffer = sourceMatrixBuffer;
state._srcColorBuffer = sourceColorBuffer;
state._hasColor = hasColor;
}
const v = camera.viewport;
const aspect = context.targetWidth / context.targetHeight * (v ? v.width / v.height : 1);
writeCullParams(engine, state, mesh, gpu.indexCount, ti.count, camera, aspect, lod);
const dispatch = {
pipeline,
bindGroup: state._bindGroup,
workgroupsX: Math.ceil(ti.count / WORKGROUP_SIZE)
};
if (dispatchBatch) {
dispatchBatch.queue(dispatch);
} else {
const pass = engine._currentEncoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, state._bindGroup);
pass.dispatchWorkgroups(dispatch.workgroupsX);
pass.end();
}
state._drawBuffers = { matrixBuffer: visibleMatrixBuffer, colorBuffer: visibleColorBuffer };
setCullActive(state, true);
if (lod) {
return {
drawBuffers: state._drawBuffers,
argsBuffer,
lodDrawBuffers: { matrixBuffer: state._lodMatrixBuffer, colorBuffer: hasColor ? state._lodColorBuffer : null },
lodArgsBuffer: state._lodArgsBuffer
};
}
return { drawBuffers: state._drawBuffers, argsBuffer };
}
function cullFallback(engine, state) {
if (state._lodArgsBuffer && !state._lodArgsZeroed) {
engine._currentEncoder.clearBuffer(state._lodArgsBuffer, 4, 4);
state._lodArgsZeroed = true;
}
setCullActive(state, false);
state._drawBuffers = null;
return null;
}
function publishTiLodBucket(ti, signature, result) {
const lodDrawBuffers = result?.lodDrawBuffers;
const lodArgsBuffer = result?.lodArgsBuffer;
const buckets = ti._lodBuckets;
if (lodDrawBuffers && lodArgsBuffer && buckets) {
let bucket2 = buckets.get(signature);
if (!bucket2) {
bucket2 = { matrixBuffer: lodDrawBuffers.matrixBuffer, colorBuffer: lodDrawBuffers.colorBuffer, argsBuffer: lodArgsBuffer, active: true };
buckets.set(signature, bucket2);
return;
}
bucket2.matrixBuffer = lodDrawBuffers.matrixBuffer;
bucket2.colorBuffer = lodDrawBuffers.colorBuffer;
bucket2.argsBuffer = lodArgsBuffer;
bucket2.active = true;
return;
}
const bucket = ti._lodBuckets?.get(signature);
if (bucket) {
bucket.active = false;
}
}
function ensureCullBuffers(engine, state, capacity, hasColor, lod) {
const device = engine._device;
if (state._lodActive !== lod) {
state._paramsBuffer?.destroy();
state._paramsBuffer = null;
state._bindGroup = null;
if (!lod) {
const lodMat = state._lodMatrixBuffer;
const lodCol = state._lodColorBuffer;
const lodArgs = state._lodArgsBuffer;
if (lodArgs && !state._lodArgsZeroed) {
engine._currentEncoder.clearBuffer(lodArgs, 4, 4);
}
if (lodMat || lodArgs) {
retireGpuResources(engine, () => {
lodMat?.destroy();
lodCol?.destroy();
lodArgs?.destroy();
});
}
state._lodMatrixBuffer = null;
state._lodColorBuffer = null;
state._lodArgsBuffer = null;
state._lodIndexCount = -1;
state._lodArgsZeroed = false;
}
state._lodActive = lod;
bumpVisibilityEpoch();
}
if (state._capacity < capacity) {
state._visibleMatrixBuffer?.destroy();
state._visibleColorBuffer?.destroy();
state._visibleMatrixBuffer = device.createBuffer({
size: Math.max(capacity * 64, 4),
usage: BU.VERTEX | BU.STORAGE
});
state._visibleColorBuffer = hasColor ? device.createBuffer({
size: Math.max(capacity * 16, 4),
usage: BU.VERTEX | BU.STORAGE
}) : null;
state._capacity = capacity;
state._bindGroup = null;
state._drawBuffers = null;
bumpVisibilityEpoch();
} else if (hasColor && !state._visibleColorBuffer) {
state._visibleColorBuffer = device.createBuffer({
size: Math.max(state._capacity * 16, 4),
usage: BU.VERTEX | BU.STORAGE
});
state._bindGroup = null;
state._drawBuffers = null;
bumpVisibilityEpoch();
}
if (lod && (!state._lodMatrixBuffer || state._lodMatrixBuffer.size < state._capacity * 64 || hasColor && !state._lodColorBuffer)) {
const oldMat = state._lodMatrixBuffer;
const oldCol = state._lodColorBuffer;
if (oldMat) {
retireGpuResources(engine, () => {
oldMat.destroy();
oldCol?.destroy();
});
}
state._lodMatrixBuffer = device.createBuffer({
size: Math.max(state._capacity * 64, 4),
usage: BU.VERTEX | BU.STORAGE
});
state._lodColorBuffer = hasColor ? device.createBuffer({
size: Math.max(state._capacity * 16, 4),
usage: BU.VERTEX | BU.STORAGE
}) : null;
state._bindGroup = null;
bumpVisibilityEpoch();
}
if (lod && !state._lodArgsBuffer) {
state._lodArgsBuffer = device.createBuffer({
size: INDIRECT_ARGS_BYTES,
usage: BU.INDIRECT | BU.STORAGE | BU.COPY_DST
});
state._lodIndexCount = -1;
state._lodArgsZeroed = false;
}
if (!state._argsBuffer) {
state._argsBuffer = device.createBuffer({
size: INDIRECT_ARGS_BYTES,
usage: BU.INDIRECT | BU.STORAGE | BU.COPY_DST
});
}
if (!state._paramsBuffer) {
state._paramsBuffer = device.createBuffer({
size: lod ? LOD_PARAM_BYTES : PARAM_BYTES,
usage: BU.UNIFORM | BU.COPY_DST
});
}
}
function getCullPipeline(engine, hasColor, lod) {
const device = engine._device;
if (_cachedDevice !== device) {
_cachedDevice = device;
_pipelineNoColor = null;
_pipelineColor = null;
_pipelineLodNoColor = null;
_pipelineLodColor = null;
}
if (lod) {
if (hasColor) {
_pipelineLodColor ??= device.createComputePipeline({
layout: "auto",
compute: { module: device.createShaderModule({ code: CULL_WGSL_LOD_COLOR }), entryPoint: "mainLodColor" }
});
return _pipelineLodColor;
}
_pipelineLodNoColor ??= device.createComputePipeline({
layout: "auto",
compute: { module: device.createShaderModule({ code: CULL_WGSL_LOD_NO_COLOR }), entryPoint: "mainLod" }
});
return _pipelineLodNoColor;
}
if (hasColor) {
_pipelineColor ??= device.createComputePipeline({
layout: "auto",
compute: { module: device.createShaderModule({ code: CULL_WGSL_COLOR }), entryPoint: "mainColor" }
});
return _pipelineColor;
}
_pipelineNoColor ??= device.createComputePipeline({
layout: "auto",
compute: { module: device.createShaderModule({ code: CULL_WGSL_NO_COLOR }), entryPoint: "main" }
});
return _pipelineNoColor;
}
function writeCullParams(engine, state, mesh, indexCount, instanceCount, camera, aspect, lodMesh) {
const params = state._paramsF32;
const viewProjection = getViewProjectionMatrix(camera, aspect);
writeFrustumPlanes(params, viewProjection);
params.set(mesh.worldMatrix, MESH_WORLD_FLOAT_OFFSET);
params.set(state._localSphere, LOCAL_SPHERE_FLOAT_OFFSET);
state._paramsU32[COUNT_U32_OFFSET] = instanceCount;
params[BOUNDS_PAD_F32_OFFSET] = mesh.thinInstances?._cullBoundsPad ?? 0;
if (lodMesh) {
const cw = camera.worldMatrix;
params[CAM_POS_DIST_F32_OFFSET] = cw[12];
params[CAM_POS_DIST_F32_OFFSET + 1] = cw[13];
params[CAM_POS_DIST_F32_OFFSET + 2] = cw[14];
params[CAM_POS_DIST_F32_OFFSET + 3] = mesh.thinInstances?._lodDistance ?? 0;
params[LOD_BAND_F32_OFFSET] = mesh.thinInstances?._lodBand ?? 0;
}
if (state._indexCount !== indexCount) {
const args = state._argsData;
args[0] = indexCount;
args[1] = 0;
args[2] = 0;
args[3] = 0;
args[4] = 0;
engine._device.queue.writeBuffer(state._argsBuffer, 0, args.buffer, args.byteOffset, args.byteLength);
state._indexCount = indexCount;
} else {
engine._currentEncoder.clearBuffer(state._argsBuffer, 4, 4);
}
if (lodMesh) {
const lodGpu = lodMesh._gpu;
const lodIndexCount = lodGpu ? lodGpu.indexCount : 0;
if (state._lodIndexCount !== lodIndexCount) {
const args = state._argsData;
args[0] = lodIndexCount;
args[1] = 0;
args[2] = 0;
args[3] = 0;
args[4] = 0;
engine._device.queue.writeBuffer(state._lodArgsBuffer, 0, args.buffer, args.byteOffset, args.byteLength);
state._lodIndexCount = lodIndexCount;
} else {
engine._currentEncoder.clearBuffer(state._lodArgsBuffer, 4, 4);
}
state._lodArgsZeroed = false;
}
engine._device.queue.writeBuffer(state._paramsBuffer, 0, state._paramsBytes, 0, lodMesh ? LOD_PARAM_BYTES : PARAM_BYTES);
}
function setCullActive(state, active) {
if (state._active !== active) {
state._active = active;
bumpVisibilityEpoch();
}
}
function writeFrustumPlanes(out, m) {
writePlane(out, 0, m[3] + m[0], m[7] + m[4], m[11] + m[8], m[15] + m[12]);
writePlane(out, 4, m[3] - m[0], m[7] - m[4], m[11] - m[8], m[15] - m[12]);
writePlane(out, 8, m[3] + m[1], m[7] + m[5], m[11] + m[9], m[15] + m[13]);
writePlane(out, 12, m[3] - m[1], m[7] - m[5], m[11] - m[9], m[15] - m[13]);
writePlane(out, 16, m[2], m[6], m[10], m[14]);
writePlane(out, 20, m[3] - m[2], m[7] - m[6], m[11] - m[10], m[15] - m[14]);
}
function writePlane(out, offset, x, y, z, w) {
const invLen = 1 / Math.hypot(x, y, z);
out[offset] = x * invLen;
out[offset + 1] = y * invLen;
out[offset + 2] = z * invLen;
out[offset + 3] = w * invLen;
}
function computeLocalSphere(mesh, out) {
const positions = mesh._cpuPositions;
if (!positions || positions.length < 3) {
return false;
}
let minX = Infinity, minY = Infinity, minZ = Infinity;
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
for (let i = 0; i < positions.length; i += 3) {
const x = positions[i];
const y = positions[i + 1];
const z = positions[i + 2];
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
if (z < minZ) {
minZ = z;
}
if (z > maxZ) {
maxZ = z;
}
}
if (!isFinite(minX)) {
return false;
}
const cx = (minX + maxX) * 0.5;
const cy = (minY + maxY) * 0.5;
const cz = (minZ + maxZ) * 0.5;
const dx = maxX - cx;
const dy = maxY - cy;
const dz = maxZ - cz;
out[0] = cx;
out[1] = cy;
out[2] = cz;
out[3] = Math.hypot(dx, dy, dz);
return true;
}
function tryBind(renderable, scene, mesh, engine, hasColor, excluded, baseUpdate, signature) {
const ti = mesh.thinInstances;
if (!ti) {
return void 0;
}
if (ti._lodSource) {
if (excluded) {
ThrowLiteError(272);
}
renderable._direct = true;
return bindLodPartner(ti, signature, hasColor, baseUpdate);
}
if (excluded || !ti._gpuCullingEnabled) {
return void 0;
}
const holder = renderable;
const cache = holder._tiCullStates ??= /* @__PURE__ */ new WeakMap();
let state = cache.get(signature);
if (!state) {
state = createTiCullState();
cache.set(signature, state);
const owned = state;
scene._meshDisposables.get(mesh)?.push(() => {
destroyTiCullState(owned);
});
} else {
state._localSphereReady = false;
}
const updateBatch = getComputeDispatchBatch(signature);
const binding = {
cullDrawBufs: null,
_args: null,
_updateBatch: updateBatch,
update(context) {
baseUpdate?.(context);
const partner = ti._lodPartner ?? null;
const res = prepareTiCull(engine, state, mesh, mesh._gpu, ti, hasColor, context, updateBatch, partner);
binding.cullDrawBufs = res?.drawBuffers ?? null;
binding._args = res?.argsBuffer ?? null;
if (ti._lodBuckets) {
publishTiLodBucket(ti, signature, res);
}
},
draw(pass, indexCount, instanceCount) {
if (binding._args) {
pass.drawIndexedIndirect(binding._args, 0);
} else if (ti._drawArgsBuffer) {
pass.drawIndexedIndirect(ti._drawArgsBuffer, 0);
} else {
pass.drawIndexed(indexCount, instanceCount);
}
}
};
return binding;
}
function bindLodPartner(ti, signature, hasColor, baseUpdate) {
const currentBucket = () => {
const bucket = ti._lodBuckets?.get(signature);
if (!bucket?.active) {
return null;
}
if (hasColor && !bucket.colorBuffer) {
ThrowLiteError(273);
}
return bucket;
};
const binding = {
get cullDrawBufs() {
return currentBucket();
},
get _args() {
return currentBucket()?.argsBuffer ?? null;
},
_updateBatch: getComputeDispatchBatch(signature),
update(context) {
baseUpdate?.(context);
},
draw(pass, indexCount, instanceCount) {
const bucket = currentBucket();
if (bucket) {
pass.drawIndexedIndirect(bucket.argsBuffer, 0);
} else if (!ti._lodSource) {
if (ti._drawArgsBuffer) {
pass.drawIndexedIndirect(ti._drawArgsBuffer, 0);
} else {
pass.drawIndexed(indexCount, instanceCount);
}
}
}
};
return binding;
}
export { tryBind };
//# sourceMappingURL=thin-instance-cull-binding-CWoyR4dA.esm.js.map