@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.
191 lines (186 loc) • 7.67 kB
JavaScript
import { T as ThrowLiteError, S as SS } from './index-By0tcgYN.esm.js';
function _getStorageBufferHandle(engine, buffer) {
if (buffer._destroyed || !buffer._data) {
ThrowLiteError(315);
}
if (buffer._engine !== engine) {
ThrowLiteError(316);
}
if (!engine._storageBuffers?.has(buffer)) {
ThrowLiteError(317);
}
return buffer._buffer;
}
const VAT_HELPERS = `struct vatUniforms {
params: vec4<f32>,
clock: vec4<f32>,
}
fn readMatrixFromVat(smp: texture_2d<f32>, index: f32, row: i32) -> mat4x4<f32> {
let o = i32(index) * 4;
let m0 = textureLoad(smp, vec2<i32>(o + 0, row), 0);
let m1 = textureLoad(smp, vec2<i32>(o + 1, row), 0);
let m2 = textureLoad(smp, vec2<i32>(o + 2, row), 0);
let m3 = textureLoad(smp, vec2<i32>(o + 3, row), 0);
return mat4x4f(m0, m1, m2, m3);
}
fn vatFrameRow(p: vec4<f32>, t: f32) -> i32 {
let span = max(1.0, p.y - p.x + 1.0);
let raw = p.z + t * p.w;
let wrapped = raw - floor(raw / span) * span;
return i32(p.x + wrapped);
}`;
function vatSkinSum(dest, row, has8Bones) {
let s = `var ${dest}: mat4x4<f32> = readMatrixFromVat(vatSampler, f32(joints[0]), ${row}) * weights[0];
${dest} = ${dest} + readMatrixFromVat(vatSampler, f32(joints[1]), ${row}) * weights[1];
${dest} = ${dest} + readMatrixFromVat(vatSampler, f32(joints[2]), ${row}) * weights[2];
${dest} = ${dest} + readMatrixFromVat(vatSampler, f32(joints[3]), ${row}) * weights[3];`;
if (has8Bones) {
s += `
${dest} = ${dest} + readMatrixFromVat(vatSampler, f32(joints1[0]), ${row}) * weights1[0];
${dest} = ${dest} + readMatrixFromVat(vatSampler, f32(joints1[1]), ${row}) * weights1[1];
${dest} = ${dest} + readMatrixFromVat(vatSampler, f32(joints1[2]), ${row}) * weights1[2];
${dest} = ${dest} + readMatrixFromVat(vatSampler, f32(joints1[3]), ${row}) * weights1[3];`;
}
return s;
}
function vatRegularInfluence(has8Bones) {
return `let vatRow = vatFrameRow(vat.params, vat.clock.x);
${vatSkinSum("influence", "vatRow", has8Bones)}`;
}
function vatInstancedInfluence(has8Bones, instanceIndex, storage = false) {
const reads = storage ? `let vatIdx = ${instanceIndex} * 2u;
let vatA = vatInstanceStorage[vatIdx];
let vatB = vatInstanceStorage[vatIdx + 1u];` : `let vatIdx = i32(${instanceIndex}) * 2;
let vatA = textureLoad(vatInstanceTex, vec2<i32>(vatIdx, 0), 0);
let vatB = textureLoad(vatInstanceTex, vec2<i32>(vatIdx + 1, 0), 0);`;
return `${reads}
let rowA = vatFrameRow(vatA, vat.clock.x);
let rowB = vatFrameRow(vec4f(vatB.x, vatB.y, vatA.z, vatB.w), vat.clock.x);
${vatSkinSum("infA", "rowA", has8Bones)}
${vatSkinSum("infB", "rowB", has8Bones)}
var influence: mat4x4f = infA * (1.0 - vatB.z) + infB * vatB.z;`;
}
function createVatPickProjectionWgsl(has8Bones, instanceStorage = false) {
return {
helpers: VAT_HELPERS,
regularBody: `${vatRegularInfluence(has8Bones)}
let projectedTransform = mesh.world * influence;
let projectedWorld = (projectedTransform * vec4f(position, 1.0)).xyz;`,
thinBody: `${vatInstancedInfluence(has8Bones, "instanceIndex", instanceStorage)}
let projectedTransform = instanceWorld * tiMesh.world * influence;
let projectedWorld = (projectedTransform * vec4f(position, 1.0)).xyz;`
};
}
let _device = null;
let _projections = null;
function skinInputs(has8Bones) {
return `, @location(1) joints: vec4<u32>, @location(2) weights: vec4<f32>${has8Bones ? ", @location(3) joints1: vec4<u32>, @location(4) weights1: vec4<f32>" : ""}`;
}
function skinLayouts(has8Bones) {
const layouts = [
{ arrayStride: 16, attributes: [{ shaderLocation: 1, offset: 0, format: "uint32x4" }] },
{ arrayStride: 16, attributes: [{ shaderLocation: 2, offset: 0, format: "float32x4" }] }
];
if (has8Bones) {
layouts.push(
{ arrayStride: 16, attributes: [{ shaderLocation: 3, offset: 0, format: "uint32x4" }] },
{ arrayStride: 16, attributes: [{ shaderLocation: 4, offset: 0, format: "float32x4" }] }
);
}
return layouts;
}
function createProjection(engine, has8Bones, instanceStorage) {
const device = engine._device;
const source = createVatPickProjectionWgsl(has8Bones, instanceStorage);
const regularBGL = device.createBindGroupLayout({
label: `picking-vat-${has8Bones ? 8 : 4}-regular-bgl`,
entries: [
{ binding: 0, visibility: SS.VERTEX, texture: { sampleType: "unfilterable-float" } },
{ binding: 1, visibility: SS.VERTEX, buffer: { type: "uniform" } }
]
});
const thinBGL = device.createBindGroupLayout({
label: `picking-vat-${has8Bones ? 8 : 4}-thin-bgl`,
entries: [
{ binding: 0, visibility: SS.VERTEX, texture: { sampleType: "unfilterable-float" } },
{ binding: 1, visibility: SS.VERTEX, buffer: { type: "uniform" } },
instanceStorage ? { binding: 2, visibility: SS.VERTEX, buffer: { type: "read-only-storage" } } : { binding: 2, visibility: SS.VERTEX, texture: { sampleType: "unfilterable-float" } }
]
});
const commonDeclarations = `${source.helpers}
@group(3) @binding(0) var vatSampler: texture_2d<f32>;
@group(3) @binding(1) var<uniform> vat: vatUniforms;`;
return {
key: `vat-${has8Bones ? 8 : 4}-${instanceStorage ? "storage" : "texture"}`,
shader: {
regularDeclarations: commonDeclarations,
thinDeclarations: `${commonDeclarations}
@group(3) @binding(2) ${instanceStorage ? "var<storage, read> vatInstanceStorage: array<vec4<f32>>;" : "var vatInstanceTex: texture_2d<f32>;"}`,
regularInputs: skinInputs(has8Bones),
thinInputs: skinInputs(has8Bones),
regularBody: source.regularBody,
thinBody: source.thinBody
},
vertexBuffers: skinLayouts(has8Bones),
regularBGL,
thinBGL
};
}
function projectionFor(engine, has8Bones, instanceStorage) {
if (_device !== engine._device) {
_device = engine._device;
_projections = null;
}
const key = `${has8Bones ? 8 : 4}-${instanceStorage ? "storage" : "texture"}`;
const projections = _projections ??= /* @__PURE__ */ new Map();
let projection = projections.get(key);
if (!projection) {
projection = createProjection(engine, has8Bones, instanceStorage);
projections.set(key, projection);
}
return projection;
}
function getVatPickingProjection(engine, mesh) {
const vat = mesh.vat;
const instanceStorage = !!vat?._instanceStorage;
if (!vat || mesh.thinInstances && !instanceStorage && !vat.instanceTexture) {
return null;
}
return projectionFor(engine, vat.joints1Buffer !== null && vat.weights1Buffer !== null, instanceStorage);
}
function bindVatPickingProjection(engine, pass, pipeline, mesh, thin, firstVertexSlot) {
const vat = mesh.vat;
if (!vat) {
return;
}
const entries = [
{ binding: 0, resource: vat.texture.createView() },
{ binding: 1, resource: { buffer: vat.settingsBuffer } }
];
if (thin) {
if (vat._instanceStorage) {
entries.push({ binding: 2, resource: { buffer: _getStorageBufferHandle(engine, vat._instanceStorage) } });
} else if (vat.instanceTexture) {
entries.push({ binding: 2, resource: vat.instanceTexture.createView() });
} else {
return;
}
}
pass.setBindGroup(
3,
engine._device.createBindGroup({
label: `picking-vat-${thin ? "thin" : "regular"}-bg`,
layout: pipeline.getBindGroupLayout(3),
entries
})
);
let slot = firstVertexSlot;
pass.setVertexBuffer(slot++, vat.jointsBuffer);
pass.setVertexBuffer(slot++, vat.weightsBuffer);
if (vat.joints1Buffer && vat.weights1Buffer) {
pass.setVertexBuffer(slot++, vat.joints1Buffer);
pass.setVertexBuffer(slot, vat.weights1Buffer);
}
}
export { bindVatPickingProjection, getVatPickingProjection };
//# sourceMappingURL=vat-picking-pipeline-C0gkoqbF.esm.js.map