UNPKG

@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
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