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.

161 lines (157 loc) 4.65 kB
import { S as SS, aw as getPickingSceneBGL, h as createSingleUniformBGL } from './index-By0tcgYN.esm.js'; const PICK_INPUT = ( /* wgsl */ ` struct PickDiscardInput { worldPos: vec3f, fragmentCoord: vec2f, pickId: u32, thinInstanceIndex: u32, hasThinInstance: u32, instanceExtras: vec4f, }; ` ); const DEFAULT_DISCARD = ( /* wgsl */ ` fn shouldDiscardPick(input: PickDiscardInput) -> bool { return false; } ` ); function storageDecls(opts) { const storage = opts?.storage; return storage?.length ? storage.map((s, binding) => `@group(2) @binding(${binding}) var<storage, read> ${s.name}: ${s.type};`).join("\n") : ""; } const SCENE = ( /* wgsl */ ` struct SceneUniforms { viewProjection: mat4x4f, fragmentCoord: vec2f, }; @group(0) @binding(0) var<uniform> scene: SceneUniforms; ` ); const FRAGMENT = ( /* wgsl */ ` struct VsOut { @builtin(position) p: vec4f, @location(0) @interpolate(flat) pickId: u32, @location(1) worldPos: vec3f, @location(2) @interpolate(flat) thinInstanceIndex: u32, @location(3) @interpolate(flat) hasThinInstance: u32, @location(4) @interpolate(flat) instanceExtras: vec4f, }; struct FsOut { @location(0) color: vec4f, @location(1) depth: f32 }; @fragment fn fs(input: VsOut) -> FsOut { if (shouldDiscardPick(PickDiscardInput(input.worldPos, scene.fragmentCoord, input.pickId, input.thinInstanceIndex, input.hasThinInstance, input.instanceExtras))) { discard; } let id = input.pickId; let r = f32((id >> 16u) & 0xFFu) / 255.0; let g = f32((id >> 8u) & 0xFFu) / 255.0; let b = f32(id & 0xFFu) / 255.0; return FsOut(vec4f(r, g, b, 1.0), input.p.z); } ` ); function pickingShaderSource(opts) { return ( /* wgsl */ ` ${SCENE} struct MeshUniforms { world: mat4x4f, pickId: u32, }; @group(1) @binding(0) var<uniform> mesh: MeshUniforms; ${PICK_INPUT} ${storageDecls(opts)} ${opts?.discardWgsl ?? DEFAULT_DISCARD} ${FRAGMENT} @vertex fn vs(@location(0) position: vec3f) -> VsOut { var out: VsOut; let wp = (mesh.world * vec4f(position, 1.0)).xyz; out.p = scene.viewProjection * vec4f(wp, 1.0); out.pickId = mesh.pickId; out.worldPos = wp; out.thinInstanceIndex = 0xffffffffu; out.hasThinInstance = 0u; out.instanceExtras = vec4f(0.0); return out; } ` ); } let _device = null; let _meshBGL = null; let _sets = null; function invalidate(engine) { if (_device === engine._device) { return; } _device = engine._device; _meshBGL = null; _sets = null; } function meshBGL(engine) { invalidate(engine); return _meshBGL ??= createSingleUniformBGL(engine, "picking-mesh-bgl", SS.VERTEX | SS.FRAGMENT); } function discardBGL(engine, discard) { return engine._device.createBindGroupLayout({ label: `picking-discard-${discard.key}-bgl`, entries: (discard.storage ?? []).map((_, binding) => ({ binding, visibility: SS.FRAGMENT, buffer: { type: "read-only-storage" } })) }); } const POSITION = { arrayStride: 12, attributes: [{ shaderLocation: 0, offset: 0, format: "float32x3" }] }; function pipeline(engine, discard, group2, label) { const device = engine._device; const module = device.createShaderModule({ label: `${label}-shader`, code: pickingShaderSource(discard ? { discardWgsl: discard.wgsl, storage: discard.storage } : void 0) }); const group1 = meshBGL(engine); const layout = device.createPipelineLayout({ label: `${label}-pipeline-layout`, bindGroupLayouts: group2 ? [getPickingSceneBGL(engine), group1, group2] : [getPickingSceneBGL(engine), group1] }); return device.createRenderPipeline({ label: `${label}-pipeline`, layout, vertex: { module, entryPoint: "vs", buffers: [POSITION] }, fragment: { module, entryPoint: "fs", targets: [{ format: "rgba8unorm" }, { format: "r32float" }] }, depthStencil: { format: "depth24plus", depthCompare: "greater", depthWriteEnabled: true }, primitive: { topology: "triangle-list", cullMode: "none" }, multisample: { count: 1 } }); } function getPickingPipelineSet(engine, discard) { invalidate(engine); const key = discard ? `discard:${discard.key}` : "default"; const sets = _sets ??= /* @__PURE__ */ new Map(); const cached = sets.get(key); if (cached) { return cached; } const active = discard ?? null; const group2 = active?.storage?.length ? discardBGL(engine, active) : null; const regularPipeline = pipeline(engine, active, group2, active ? `picking-${active.key}` : "picking"); const set = { regularPipeline, thinInstancePipeline: regularPipeline, discardBGL: group2 }; sets.set(key, set); return set; } export { getPickingPipelineSet }; //# sourceMappingURL=picking-pipeline-CuZudL2f.esm.js.map