@babylonjs/lite 1.5.0 → 1.6.0
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/index.js +440 -446
- package/dist/index.js.map +1 -1
- package/index.d.ts +90 -46
- package/lib/camera/geospatial-camera-controls.js +22 -0
- package/lib/camera/geospatial-camera-controls.js.map +1 -1
- package/lib/camera/geospatial-camera-fly.js +2 -1
- package/lib/camera/geospatial-camera-fly.js.map +1 -1
- package/lib/effect/effect-renderer.js +1 -1
- package/lib/effect/effect-renderer.js.map +1 -1
- package/lib/engine/engine.js +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/post-process/taa.js +193 -0
- package/lib/post-process/taa.js.map +1 -0
- package/lib/sprite/billboard-custom-shader.js +32 -32
- package/lib/sprite/billboard-custom-shader.js.map +1 -1
- package/lib/sprite/billboard-pipeline.js +54 -56
- package/lib/sprite/billboard-pipeline.js.map +1 -1
- package/lib/sprite/custom-shader-core.js +1 -1
- package/lib/sprite/custom-shader-core.js.map +1 -1
- package/lib/sprite/shared/sprite-atlas.js +2 -2
- package/lib/sprite/shared/sprite-atlas.js.map +1 -1
- package/lib/sprite/sprite-2d-coverage-gamma.js +58 -0
- package/lib/sprite/sprite-2d-coverage-gamma.js.map +1 -0
- package/lib/sprite/sprite-2d-uvscroll.js +39 -0
- package/lib/sprite/sprite-2d-uvscroll.js.map +1 -0
- package/lib/sprite/sprite-2d.js +6 -40
- package/lib/sprite/sprite-2d.js.map +1 -1
- package/lib/sprite/sprite-coverage-gamma-hook.js +10 -0
- package/lib/sprite/sprite-coverage-gamma-hook.js.map +1 -0
- package/lib/sprite/sprite-custom-shader.js +2 -2
- package/lib/sprite/sprite-custom-shader.js.map +1 -1
- package/lib/sprite/sprite-pipeline.js +56 -71
- package/lib/sprite/sprite-pipeline.js.map +1 -1
- package/lib/sprite/sprite-renderable.js +5 -5
- package/lib/sprite/sprite-renderable.js.map +1 -1
- package/lib/sprite/sprite-renderer.js +4 -4
- package/lib/sprite/sprite-renderer.js.map +1 -1
- package/lib/sprite/sprite-scene.js +1 -1
- package/lib/sprite/sprite-scene.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geospatial-camera-fly.js","sources":["../../../src/camera/geospatial-camera-fly.ts"],"sourcesContent":["import type { GeospatialCamera } from \"./geospatial-camera.js\";\nimport { normalizeRadians } from \"./geospatial-camera.js\";\nimport type { SceneContext } from \"./../scene/scene-core.js\";\nimport type { Vec3 } from \"../math/types.js\";\n\n/** Options for {@link flyGeospatialCameraToAsync}. Omitted target fields keep their current value. */\nexport interface GeospatialFlyOptions {\n /** Target yaw (radians). Shortest angular path is taken. */\n yaw?: number;\n /** Target pitch (radians). */\n pitch?: number;\n /** Target radius. */\n radius?: number;\n /** Target centre (ECEF). Animated along a great-circle (slerp). */\n center?: Vec3;\n /** Flight duration in ms. Default 1000. */\n durationMs?: number;\n /** Parabolic \"hop\" height scale for the centre animation (0 = none). */\n centerHopScale?: number;\n}\n\n/** Cubic ease-in-out (matches Babylon.js `CubicEase` with `EASINGMODE_EASEINOUT`). */\nfunction easeInOut(g: number): number {\n if (g >= 0.5) {\n const f = 2 * (1 - g);\n return (1 - f * f * f) * 0.5 + 0.5;\n }\n const f = 2 * g;\n return f * f * f * 0.5;\n}\n\n/** Spherical interpolation of two ECEF positions (great-circle direction + lerped magnitude). */\nfunction slerpEcef(a: Vec3, b: Vec3, t: number, out: Vec3): void {\n const la = Math.hypot(a.x, a.y, a.z) || 1;\n const lb = Math.hypot(b.x, b.y, b.z) || 1;\n const ax = a.x / la;\n const ay = a.y / la;\n const az = a.z / la;\n const bx = b.x / lb;\n const by = b.y / lb;\n const bz = b.z / lb;\n let dot = ax * bx + ay * by + az * bz;\n dot = dot < -1 ? -1 : dot > 1 ? 1 : dot;\n const theta = Math.acos(dot) * t;\n // rel = normalize(b - a*dot)\n let rx = bx - ax * dot;\n let ry = by - ay * dot;\n let rz = bz - az * dot;\n const rlen = Math.hypot(rx, ry, rz);\n if (rlen > 1e-9) {\n rx /= rlen;\n ry /= rlen;\n rz /= rlen;\n }\n const ct = Math.cos(theta);\n const st = Math.sin(theta);\n const len = la + (lb - la) * t;\n out.x = (ax * ct + rx * st) * len;\n out.y = (ay * ct + ry * st) * len;\n out.z = (az * ct + rz * st) * len;\n}\n\n/**\n * Smoothly animate a {@link GeospatialCamera} to new yaw/pitch/radius/centre over\n * `durationMs`, driven by the scene's render loop. Yaw takes the shortest angular\n * path; the centre follows a great-circle (with an optional parabolic hop).\n *\n * The returned promise resolves when the flight completes; it also resolves early\n * if the flight is interrupted (by user input through `attachGeospatialControls`,\n * or by a subsequent `flyGeospatialCameraToAsync` call). Only one flight runs at a time.\n */\nexport function flyGeospatialCameraToAsync(camera: GeospatialCamera, scene: SceneContext, options: GeospatialFlyOptions): Promise<void> {\n // Interrupt any in-flight animation.\n camera._cancelFly?.();\n\n const duration = Math.max(1, options.durationMs ?? 1000);\n const hopScale = options.centerHopScale ?? 0;\n\n const yaw0 = camera.yaw;\n const pitch0 = camera.pitch;\n const radius0 = camera.radius;\n const center0: Vec3 = { x: camera.center.x, y: camera.center.y, z: camera.center.z };\n\n const targetYaw = options.yaw !== undefined ? yaw0 + normalizeRadians(normalizeRadians(options.yaw) - yaw0) : yaw0;\n const targetPitch = options.pitch !== undefined ? normalizeRadians(options.pitch) : pitch0;\n const targetRadius = options.radius ?? radius0;\n const animateCenter = options.center !== undefined;\n const targetCenter: Vec3 = animateCenter ? { x: options.center!.x, y: options.center!.y, z: options.center!.z } : center0;\n const startToEndDist = Math.hypot(targetCenter.x - center0.x, targetCenter.y - center0.y, targetCenter.z - center0.z);\n\n const centerScratch: Vec3 = { x: 0, y: 0, z: 0 };\n let elapsed = 0;\n\n return new Promise<void>((resolve) => {\n const driver = (deltaMs: number): void => {\n elapsed += deltaMs > 0 ? deltaMs : 1000 / 60;\n const g = Math.min(1, elapsed / duration);\n const e = easeInOut(g);\n\n const yaw = yaw0 + (targetYaw - yaw0) * e;\n const pitch = pitch0 + (targetPitch - pitch0) * e;\n const radius = radius0 + (targetRadius - radius0) * e;\n\n let center: Vec3 = center0;\n if (animateCenter) {\n slerpEcef(center0, targetCenter, e, centerScratch);\n if (hopScale > 0) {\n const hopPeak = hopScale * startToEndDist;\n const hop = hopPeak * Math.max(0, (e * e - e) / -0.25);\n const clen = Math.hypot(centerScratch.x, centerScratch.y, centerScratch.z) || 1;\n const k = 1 + hop / clen;\n centerScratch.x *= k;\n centerScratch.y *= k;\n centerScratch.z *= k;\n }\n center = centerScratch;\n }\n\n camera._setOrientation(yaw, pitch, radius, center);\n\n if (g >= 1) {\n finish();\n }\n };\n\n function finish(): void {\n const idx = scene._beforeRender.indexOf(driver);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n if (camera._cancelFly === finish) {\n camera._cancelFly = undefined;\n }\n resolve();\n }\n\n camera._cancelFly = finish;\n scene._beforeRender.push(driver);\n });\n}\n"],"names":["f"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"geospatial-camera-fly.js","sources":["../../../src/camera/geospatial-camera-fly.ts"],"sourcesContent":["import type { GeospatialCamera } from \"./geospatial-camera.js\";\nimport { normalizeRadians } from \"./geospatial-camera.js\";\nimport type { SceneContext } from \"./../scene/scene-core.js\";\nimport type { Vec3 } from \"../math/types.js\";\n\n/** Options for {@link flyGeospatialCameraToAsync}. Omitted target fields keep their current value. */\nexport interface GeospatialFlyOptions {\n /** Target yaw (radians). Shortest angular path is taken. */\n yaw?: number;\n /** Target pitch (radians). */\n pitch?: number;\n /** Target radius. */\n radius?: number;\n /** Target centre (ECEF). Animated along a great-circle (slerp). */\n center?: Vec3;\n /** Flight duration in ms. Default 1000. */\n durationMs?: number;\n /** Parabolic \"hop\" height scale for the centre animation (0 = none). */\n centerHopScale?: number;\n /** Easing applied to the normalized progress `g` ∈ [0,1]. Default cubic ease-in-out. */\n ease?: (g: number) => number;\n}\n\n/** Cubic ease-in-out (matches Babylon.js `CubicEase` with `EASINGMODE_EASEINOUT`). */\nfunction easeInOut(g: number): number {\n if (g >= 0.5) {\n const f = 2 * (1 - g);\n return (1 - f * f * f) * 0.5 + 0.5;\n }\n const f = 2 * g;\n return f * f * f * 0.5;\n}\n\n/** Spherical interpolation of two ECEF positions (great-circle direction + lerped magnitude). */\nfunction slerpEcef(a: Vec3, b: Vec3, t: number, out: Vec3): void {\n const la = Math.hypot(a.x, a.y, a.z) || 1;\n const lb = Math.hypot(b.x, b.y, b.z) || 1;\n const ax = a.x / la;\n const ay = a.y / la;\n const az = a.z / la;\n const bx = b.x / lb;\n const by = b.y / lb;\n const bz = b.z / lb;\n let dot = ax * bx + ay * by + az * bz;\n dot = dot < -1 ? -1 : dot > 1 ? 1 : dot;\n const theta = Math.acos(dot) * t;\n // rel = normalize(b - a*dot)\n let rx = bx - ax * dot;\n let ry = by - ay * dot;\n let rz = bz - az * dot;\n const rlen = Math.hypot(rx, ry, rz);\n if (rlen > 1e-9) {\n rx /= rlen;\n ry /= rlen;\n rz /= rlen;\n }\n const ct = Math.cos(theta);\n const st = Math.sin(theta);\n const len = la + (lb - la) * t;\n out.x = (ax * ct + rx * st) * len;\n out.y = (ay * ct + ry * st) * len;\n out.z = (az * ct + rz * st) * len;\n}\n\n/**\n * Smoothly animate a {@link GeospatialCamera} to new yaw/pitch/radius/centre over\n * `durationMs`, driven by the scene's render loop. Yaw takes the shortest angular\n * path; the centre follows a great-circle (with an optional parabolic hop).\n *\n * The returned promise resolves when the flight completes; it also resolves early\n * if the flight is interrupted (by user input through `attachGeospatialControls`,\n * or by a subsequent `flyGeospatialCameraToAsync` call). Only one flight runs at a time.\n */\nexport function flyGeospatialCameraToAsync(camera: GeospatialCamera, scene: SceneContext, options: GeospatialFlyOptions): Promise<void> {\n // Interrupt any in-flight animation.\n camera._cancelFly?.();\n\n const duration = Math.max(1, options.durationMs ?? 1000);\n const hopScale = options.centerHopScale ?? 0;\n const ease = options.ease ?? easeInOut;\n\n const yaw0 = camera.yaw;\n const pitch0 = camera.pitch;\n const radius0 = camera.radius;\n const center0: Vec3 = { x: camera.center.x, y: camera.center.y, z: camera.center.z };\n\n const targetYaw = options.yaw !== undefined ? yaw0 + normalizeRadians(normalizeRadians(options.yaw) - yaw0) : yaw0;\n const targetPitch = options.pitch !== undefined ? normalizeRadians(options.pitch) : pitch0;\n const targetRadius = options.radius ?? radius0;\n const animateCenter = options.center !== undefined;\n const targetCenter: Vec3 = animateCenter ? { x: options.center!.x, y: options.center!.y, z: options.center!.z } : center0;\n const startToEndDist = Math.hypot(targetCenter.x - center0.x, targetCenter.y - center0.y, targetCenter.z - center0.z);\n\n const centerScratch: Vec3 = { x: 0, y: 0, z: 0 };\n let elapsed = 0;\n\n return new Promise<void>((resolve) => {\n const driver = (deltaMs: number): void => {\n elapsed += deltaMs > 0 ? deltaMs : 1000 / 60;\n const g = Math.min(1, elapsed / duration);\n // Force the final frame to land exactly on the target even if the easing curve\n // does not satisfy ease(1) === 1, so the flight never resolves short of its goal.\n const e = g >= 1 ? 1 : ease(g);\n\n const yaw = yaw0 + (targetYaw - yaw0) * e;\n const pitch = pitch0 + (targetPitch - pitch0) * e;\n const radius = radius0 + (targetRadius - radius0) * e;\n\n let center: Vec3 = center0;\n if (animateCenter) {\n slerpEcef(center0, targetCenter, e, centerScratch);\n if (hopScale > 0) {\n const hopPeak = hopScale * startToEndDist;\n const hop = hopPeak * Math.max(0, (e * e - e) / -0.25);\n const clen = Math.hypot(centerScratch.x, centerScratch.y, centerScratch.z) || 1;\n const k = 1 + hop / clen;\n centerScratch.x *= k;\n centerScratch.y *= k;\n centerScratch.z *= k;\n }\n center = centerScratch;\n }\n\n camera._setOrientation(yaw, pitch, radius, center);\n\n if (g >= 1) {\n finish();\n }\n };\n\n function finish(): void {\n const idx = scene._beforeRender.indexOf(driver);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n if (camera._cancelFly === finish) {\n camera._cancelFly = undefined;\n }\n resolve();\n }\n\n camera._cancelFly = finish;\n scene._beforeRender.push(driver);\n });\n}\n"],"names":["f"],"mappings":"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"}
|
|
@@ -302,7 +302,7 @@ function bindingLayoutEntry(layout) {
|
|
|
302
302
|
return { binding: layout.binding, visibility, buffer: { type: "uniform" } };
|
|
303
303
|
}
|
|
304
304
|
if (layout.kind === "texture") {
|
|
305
|
-
return { binding: layout.binding, visibility, texture: { sampleType: layout.textureSampleType ?? "float" } };
|
|
305
|
+
return { binding: layout.binding, visibility, texture: { sampleType: layout.textureSampleType ?? "float", viewDimension: layout.viewDimension ?? "2d" } };
|
|
306
306
|
}
|
|
307
307
|
return { binding: layout.binding, visibility, sampler: { type: layout.samplerType ?? "filtering" } };
|
|
308
308
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effect-renderer.js","sources":["../../../src/effect/effect-renderer.ts"],"sourcesContent":["import { U8 } from \"../engine/typed-arrays.js\";\nimport { BU, SS } from \"../engine/gpu-flags.js\";\nimport { registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport type { SurfaceContext } from \"../engine/surface.js\";\nimport type { RenderTarget, RenderTargetSignature } from \"../engine/render-target.js\";\nimport { buildRenderTarget, createRenderTarget, disposeRenderTarget, targetSignatureKey } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { Task } from \"../frame-graph/task.js\";\n\nconst DEFAULT_VERTEX_WGSL = `struct EffectVertexOutput{@builtin(position) position:vec4<f32>,@location(0) uv:vec2<f32>};\n@vertex fn effectFullscreenVertex(@builtin(vertex_index) vertexIndex:u32)->EffectVertexOutput{var positions=array<vec2<f32>,3>(vec2<f32>(-1.0,-1.0),vec2<f32>(3.0,-1.0),vec2<f32>(-1.0,3.0));let p=positions[vertexIndex];var out:EffectVertexOutput;out.position=vec4<f32>(p,0.0,1.0);out.uv=p*0.5+vec2<f32>(0.5,0.5);return out;}`;\n\n/** Kind of GPU binding an effect exposes: a uniform buffer, a sampled texture, or a sampler. */\nexport type EffectBindingKind = \"uniform\" | \"texture\" | \"sampler\";\n\n/** Describes a single bind-group entry (binding slot, kind, and type details) for an effect wrapper. */\nexport interface EffectBindingLayout {\n name?: string;\n binding: number;\n kind: EffectBindingKind;\n visibility?: GPUShaderStageFlags;\n uniformByteLength?: number;\n textureSampleType?: GPUTextureSampleType;\n samplerType?: GPUSamplerBindingType;\n textureBinding?: string | number;\n}\n\n/** Configuration for `createEffectWrapper`: the fullscreen fragment shader plus optional vertex shader, bindings, and blend state. */\nexport interface EffectWrapperOptions {\n name?: string;\n fragmentWGSL: string;\n vertexWGSL?: string;\n bindings?: EffectBindingLayout[];\n blend?: GPUBlendState;\n}\n\ninterface EffectUniformSlot {\n readonly layout: EffectBindingLayout;\n buffer: GPUBuffer;\n byteLength: number;\n}\n\ninterface EffectTextureSlot {\n readonly layout: EffectBindingLayout;\n texture: Texture2D | null;\n}\n\n/** A reusable fullscreen effect: owns its shader module, bind-group layout, pipelines, and uniform/texture slots. */\nexport interface EffectWrapper {\n readonly name: string;\n readonly options: EffectWrapperOptions;\n}\n\ninterface EffectWrapperInternal extends EffectWrapper {\n _engine: EngineContext;\n _shader: GPUShaderModule | null;\n _bindGroupLayout: GPUBindGroupLayout | null;\n _pipelineLayout: GPUPipelineLayout | null;\n _bindGroup: GPUBindGroup | null;\n _bindGroupDirty: boolean;\n _pipelines: Map<string, GPURenderPipeline> | null;\n _uniforms: EffectUniformSlot[];\n _textures: EffectTextureSlot[];\n}\n\n/** Configuration for `createEffectRenderTask`: the effect to draw, its render target, and optional clear state. */\nexport interface EffectRenderTaskConfig {\n name: string;\n effect: EffectWrapper;\n target: RenderTarget;\n clear?: boolean;\n clearColor?: GPUColorDict;\n}\n\n/** A frame-graph task that renders an `EffectWrapper` as a fullscreen pass into an offscreen `RenderTarget`. */\nexport interface EffectRenderTask extends Task {\n readonly name: string;\n /** @internal */\n readonly _config: EffectRenderTaskConfig;\n /** @internal */\n readonly _rt: RenderTarget;\n}\n\ninterface EffectRenderTaskInternal extends EffectRenderTask {\n _targetSignature: RenderTargetSignature;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n _pipeline: GPURenderPipeline | null;\n _bindGroup: GPUBindGroup | null;\n}\n\n// ─── Direct swapchain renderer (no scene / frame graph required) ─────────────\n\n/** Options for `createEffectRenderer`. */\nexport interface EffectRendererOptions {\n /** Label for GPU resources. Defaults to the effect's own name. */\n name?: string;\n /** Whether to clear the swapchain before drawing. Defaults to `true`. */\n clear?: boolean;\n /** Clear colour. Defaults to opaque black. */\n clearColor?: GPUColorDict;\n /**\n * Per-frame callback invoked just before the effect is drawn, receiving the\n * frame delta in milliseconds. Use it to update uniforms (e.g. time, animation\n * state). This is the effect-path equivalent of a scene's `onBeforeRender`.\n */\n update?: (deltaMs: number) => void;\n}\n\n/**\n * `EffectRenderer` — a fullscreen-effect `RenderingContext` that draws\n * directly to the swapchain without a `SceneContext` or frame-graph task.\n * Use `registerEffectRenderer` / `unregisterEffectRenderer` to attach it to\n * an engine, then call `startEngine` as usual.\n *\n * For offscreen render-to-texture workflows (effect result consumed by a\n * scene material) continue to use `createEffectRenderTask` inside a scene\n * frame graph.\n */\nexport interface EffectRenderer extends RenderingContext {\n readonly name: string;\n}\n\ninterface EffectRendererInternal extends EffectRenderer {\n _surface: SurfaceContext;\n _effect: EffectWrapperInternal;\n _clear: boolean;\n _rt: RenderTarget;\n _targetSignature: RenderTargetSignature;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n _pipeline: GPURenderPipeline | null;\n _bindGroup: GPUBindGroup | null;\n _disposed: boolean;\n}\n\n/**\n * Create an `EffectWrapper` for the given engine, allocating uniform buffers and\n * texture slots from `options.bindings`.\n * @param engine - The engine that owns the GPU resources.\n * @param options - Shader source and binding layout for the effect.\n * @returns The new effect wrapper.\n */\nexport function createEffectWrapper(engine: EngineContext, options: EffectWrapperOptions): EffectWrapper {\n const eng = engine as EngineContext;\n const wrapper: EffectWrapperInternal = {\n name: options.name ?? \"effect-wrapper\",\n options,\n _engine: eng,\n _shader: null,\n _bindGroupLayout: null,\n _pipelineLayout: null,\n _bindGroup: null,\n _bindGroupDirty: true,\n _pipelines: null,\n _uniforms: [],\n _textures: [],\n };\n createBindingSlots(wrapper);\n return wrapper;\n}\n\n/**\n * Write data into the effect's uniform buffer(s). Pass a single buffer to write the\n * wrapper's only uniform slot, or a record keyed by binding name/index to write specific slots.\n * @param wrapper - The effect wrapper to update.\n * @param data - The uniform bytes, or a map of binding key to uniform bytes.\n */\nexport function setEffectUniforms(wrapper: EffectWrapper, data: ArrayBuffer | ArrayBufferView | Record<string | number, ArrayBuffer | ArrayBufferView>): void {\n const internal = wrapper as EffectWrapperInternal;\n if (isBufferData(data)) {\n const slot = internal._uniforms[0];\n if (!slot) {\n throw new Error(\"setEffectUniforms: wrapper has no uniform binding.\");\n }\n writeUniformSlot(internal, slot, data);\n return;\n }\n for (const key of Object.keys(data)) {\n const slot = findUniformSlot(internal, key);\n if (!slot) {\n throw new Error(`setEffectUniforms: unknown uniform binding \"${key}\".`);\n }\n writeUniformSlot(internal, slot, data[key]!);\n }\n}\n\n/**\n * Bind a texture to one of the effect's texture slots, marking the bind group dirty so it is rebuilt.\n * @param wrapper - The effect wrapper to update.\n * @param bindingNameOrIndex - The texture binding's name or numeric index.\n * @param texture - The texture to bind.\n */\nexport function setEffectTexture(wrapper: EffectWrapper, bindingNameOrIndex: string | number, texture: Texture2D): void {\n const internal = wrapper as EffectWrapperInternal;\n const slot = findTextureSlot(internal, bindingNameOrIndex);\n if (!slot) {\n throw new Error(`setEffectTexture: unknown texture binding \"${String(bindingNameOrIndex)}\".`);\n }\n slot.texture = texture;\n internal._bindGroupDirty = true;\n}\n\n/**\n * Create a frame-graph task that draws an effect as a fullscreen pass into `config.target`.\n * @param config - The effect, target, and clear settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The render task to add to a frame graph.\n */\nexport function createEffectRenderTask(config: EffectRenderTaskConfig, engine: EngineContext, scene?: SceneContext): EffectRenderTask {\n const eng = engine as EngineContext;\n const effect = config.effect as EffectWrapperInternal;\n const rt = config.target;\n config.clearColor ??= { r: 0, g: 0, b: 0, a: 1 };\n const sampleCount = rt._descriptor.samples ?? 1;\n const targetSignature: RenderTargetSignature = {\n _colorFormat: rt._descriptor.format,\n _sampleCount: sampleCount,\n };\n const colorAttachment = { loadOp: \"clear\", storeOp: \"store\" } as GPURenderPassColorAttachment;\n const task: EffectRenderTaskInternal = {\n name: config.name,\n _config: config,\n engine: eng,\n scene,\n _passes: [],\n _rt: rt,\n _targetSignature: targetSignature,\n _renderPassDescriptor: { label: config.name, colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n _pipeline: null,\n _bindGroup: null,\n record(): void {\n buildRenderTarget(rt, eng);\n task._pipeline = getEffectPipeline(effect, task._targetSignature);\n task._bindGroup = getEffectBindGroup(effect);\n },\n execute(): number {\n const pipeline = task._pipeline;\n if (!pipeline) {\n throw new Error(`EffectRenderTask \"${task.name}\" executed before record().`);\n }\n task._bindGroup = getEffectBindGroup(effect);\n applyColorAttachmentState(task._colorAttachment, rt, undefined, task._config.clear !== false, task._config.clearColor!);\n const pass = eng._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n pass.setPipeline(pipeline);\n if (task._bindGroup) {\n pass.setBindGroup(0, task._bindGroup);\n }\n pass.draw(3);\n pass.end();\n return 1;\n },\n dispose(): void {\n task._passes.length = 0;\n disposeRenderTarget(task._rt);\n task._pipeline = null;\n task._bindGroup = null;\n },\n };\n return task;\n}\n\n/** Destroy the uniform buffers and clear the cached pipelines, bind groups, and slots owned by the effect wrapper. */\nexport function disposeEffectWrapper(wrapper: EffectWrapper): void {\n const internal = wrapper as EffectWrapperInternal;\n for (const slot of internal._uniforms) {\n slot.buffer.destroy();\n }\n internal._uniforms.length = 0;\n internal._textures.length = 0;\n internal._pipelines?.clear();\n internal._pipelines = null;\n internal._shader = null;\n internal._bindGroupLayout = null;\n internal._pipelineLayout = null;\n internal._bindGroup = null;\n internal._bindGroupDirty = true;\n}\n\n/**\n * Create an `EffectRenderer` that draws `effect` as a fullscreen pass to the\n * swapchain each frame. The renderer owns a swapchain `RenderTarget` and\n * implements `RenderingContext` directly — no `SceneContext` is needed.\n *\n * Call `registerEffectRenderer` to start rendering, `unregisterEffectRenderer`\n * to pause, and `disposeEffectRenderer` to free GPU resources.\n */\nexport function createEffectRenderer(surface: SurfaceContext, effect: EffectWrapper, options?: EffectRendererOptions): EffectRenderer {\n const eng = surface.engine;\n const ew = effect as EffectWrapperInternal;\n const name = options?.name ?? effect.name;\n const clear = options?.clear !== false;\n const clearColor: GPUColorDict = options?.clearColor ?? { r: 0, g: 0, b: 0, a: 1 };\n const update = options?.update;\n\n // No MSAA → render straight into the single-sample surface scRT; MSAA →\n // render into an MSAA colour RT and resolve into the scRT at end-of-pass.\n const useMsaa = surface.msaaSamples > 1;\n const rt = useMsaa ? createRenderTarget({ lbl: `${name}-msaa`, format: surface.format, samples: surface.msaaSamples, size: surface }) : surface.scRT;\n const resolveRt = useMsaa ? surface.scRT : undefined;\n\n const targetSignature: RenderTargetSignature = {\n _colorFormat: rt._descriptor.format,\n _sampleCount: rt._descriptor.samples ?? 1,\n };\n\n const colorAttachment: GPURenderPassColorAttachment = {\n view: undefined!,\n loadOp: \"clear\",\n storeOp: \"store\",\n };\n const renderPassDescriptor: GPURenderPassDescriptor = { label: name, colorAttachments: [colorAttachment] };\n\n const er: EffectRendererInternal = {\n name,\n clearColor,\n _drawCallsPre: 0,\n _surface: surface,\n _effect: ew,\n _clear: clear,\n _rt: rt,\n _targetSignature: targetSignature,\n _renderPassDescriptor: renderPassDescriptor,\n _colorAttachment: colorAttachment,\n _pipeline: null,\n _bindGroup: null,\n _disposed: false,\n _update(): void {\n update?.(eng._currentDelta);\n },\n _record(): number {\n if (er._disposed) {\n return 0;\n }\n ensureRtCanvasSize(er._rt);\n applyColorAttachmentState(er._colorAttachment, er._rt, resolveRt, er._clear, er.clearColor);\n const encoder = er._surface.engine._currentEncoder;\n if (!encoder) {\n return 0;\n }\n const pipeline = er._pipeline;\n if (!pipeline) {\n throw new Error(`EffectRenderer \"${er.name}\" recorded before registerEffectRenderer().`);\n }\n const pass = encoder.beginRenderPass(er._renderPassDescriptor);\n pass.setPipeline(pipeline);\n if (er._bindGroup) {\n pass.setBindGroup(0, er._bindGroup);\n }\n pass.draw(3);\n pass.end();\n return 1;\n },\n _resize(): void {\n if (er._disposed) {\n return;\n }\n buildRenderTarget(er._rt, er._surface.engine);\n },\n };\n return er;\n}\n\n/** Register the effect renderer with its surface. Idempotent — a second call is a no-op. */\nexport function registerEffectRenderer(er: EffectRenderer): void {\n const internal = er as EffectRendererInternal;\n prepareEffectRenderer(internal);\n registerRenderingContext(internal._surface, er);\n}\n\n/** Unregister the effect renderer from its surface. No-op if not registered. */\nexport function unregisterEffectRenderer(er: EffectRenderer): void {\n unregisterRenderingContext((er as EffectRendererInternal)._surface, er);\n}\n\n/** Unregister and free all GPU resources owned by the renderer. */\nexport function disposeEffectRenderer(er: EffectRenderer): void {\n const internal = er as EffectRendererInternal;\n if (internal._disposed) {\n return;\n }\n unregisterEffectRenderer(er);\n disposeRenderTarget(internal._rt);\n internal._disposed = true;\n}\n\nfunction createBindingSlots(wrapper: EffectWrapperInternal): void {\n const layouts = [...(wrapper.options.bindings ?? [])].sort((a, b) => a.binding - b.binding);\n const seen = new Set<number>();\n for (const layout of layouts) {\n if (seen.has(layout.binding)) {\n throw new Error(`createEffectWrapper: duplicate binding ${layout.binding}.`);\n }\n seen.add(layout.binding);\n if (layout.kind === \"uniform\") {\n const byteLength = align4(layout.uniformByteLength ?? 16);\n const buffer = wrapper._engine._device.createBuffer({\n label: `${wrapper.name}-${layout.name ?? layout.binding}-ubo`,\n size: byteLength,\n usage: BU.UNIFORM | BU.COPY_DST,\n });\n wrapper._uniforms.push({ layout, buffer, byteLength });\n } else if (layout.kind === \"texture\") {\n wrapper._textures.push({ layout, texture: null });\n }\n }\n}\n\nfunction applyColorAttachmentState(att: GPURenderPassColorAttachment, rt: RenderTarget, resolveRt: RenderTarget | undefined, clear: boolean, clearColor: GPUColorDict): void {\n att.clearValue = clearColor;\n att.loadOp = clear ? \"clear\" : \"load\";\n // Re-read each frame so a swapchain target (used as `rt` when single-sample, or as\n // the MSAA `resolveRt`) picks up its fresh per-frame view.\n att.view = rt._colorView!;\n att.resolveTarget = resolveRt?._colorView ?? undefined;\n}\n\nfunction ensureRtCanvasSize(rt: RenderTarget): void {\n const size = rt._descriptor.size;\n if (!(\"canvas\" in size)) {\n return;\n }\n // Surface-sized RT: rebuild when the surface's canvas backing-store has resized.\n const canvas = size.canvas;\n if (rt._width === canvas.width && rt._height === canvas.height) {\n return;\n }\n buildRenderTarget(rt, size.engine);\n}\n\nfunction getEffectPipeline(wrapper: EffectWrapperInternal, targetSignature: RenderTargetSignature): GPURenderPipeline {\n const key = targetSignatureKey(targetSignature);\n if (!wrapper._pipelines) {\n wrapper._pipelines = new Map();\n }\n const hit = wrapper._pipelines.get(key);\n if (hit) {\n return hit;\n }\n const device = wrapper._engine._device;\n const pipeline = device.createRenderPipeline({\n label: `${wrapper.name}-${key}`,\n layout: getPipelineLayout(wrapper),\n vertex: { module: getShaderModule(wrapper), entryPoint: \"effectFullscreenVertex\" },\n fragment: {\n module: getShaderModule(wrapper),\n entryPoint: \"effectFragment\",\n targets: [{ format: targetSignature._colorFormat!, blend: wrapper.options.blend }],\n },\n primitive: { topology: \"triangle-list\" },\n multisample: { count: targetSignature._sampleCount },\n });\n wrapper._pipelines.set(key, pipeline);\n return pipeline;\n}\n\nfunction getShaderModule(wrapper: EffectWrapperInternal): GPUShaderModule {\n if (!wrapper._shader) {\n wrapper._shader = wrapper._engine._device.createShaderModule({\n label: wrapper.name,\n code: `${wrapper.options.vertexWGSL ?? DEFAULT_VERTEX_WGSL}\\n${wrapper.options.fragmentWGSL}`,\n });\n }\n return wrapper._shader;\n}\n\nfunction getPipelineLayout(wrapper: EffectWrapperInternal): GPUPipelineLayout {\n if (!wrapper._pipelineLayout) {\n wrapper._pipelineLayout = wrapper._engine._device.createPipelineLayout({\n label: `${wrapper.name}-pipeline-layout`,\n bindGroupLayouts: [getBindGroupLayout(wrapper)],\n });\n }\n return wrapper._pipelineLayout;\n}\n\nfunction getBindGroupLayout(wrapper: EffectWrapperInternal): GPUBindGroupLayout {\n if (!wrapper._bindGroupLayout) {\n const entries = (wrapper.options.bindings ?? [])\n .slice()\n .sort((a, b) => a.binding - b.binding)\n .map((layout) => bindingLayoutEntry(layout));\n wrapper._bindGroupLayout = wrapper._engine._device.createBindGroupLayout({\n label: `${wrapper.name}-bgl`,\n entries,\n });\n }\n return wrapper._bindGroupLayout;\n}\n\nfunction bindingLayoutEntry(layout: EffectBindingLayout): GPUBindGroupLayoutEntry {\n const visibility = layout.visibility ?? SS.FRAGMENT;\n if (layout.kind === \"uniform\") {\n return { binding: layout.binding, visibility, buffer: { type: \"uniform\" } };\n }\n if (layout.kind === \"texture\") {\n return { binding: layout.binding, visibility, texture: { sampleType: layout.textureSampleType ?? \"float\" } };\n }\n return { binding: layout.binding, visibility, sampler: { type: layout.samplerType ?? \"filtering\" } };\n}\n\nfunction getEffectBindGroup(wrapper: EffectWrapperInternal): GPUBindGroup | null {\n const bindings = wrapper.options.bindings ?? [];\n if (bindings.length === 0) {\n return null;\n }\n if (!wrapper._bindGroupDirty && wrapper._bindGroup) {\n return wrapper._bindGroup;\n }\n const entries = bindings\n .slice()\n .sort((a, b) => a.binding - b.binding)\n .map((layout) => bindGroupEntry(wrapper, layout));\n wrapper._bindGroup = wrapper._engine._device.createBindGroup({\n label: `${wrapper.name}-bg`,\n layout: getBindGroupLayout(wrapper),\n entries,\n });\n wrapper._bindGroupDirty = false;\n return wrapper._bindGroup;\n}\n\nfunction prepareEffectRenderer(er: EffectRendererInternal): void {\n er._pipeline ??= getEffectPipeline(er._effect, er._targetSignature);\n er._bindGroup = getEffectBindGroup(er._effect);\n}\n\nfunction bindGroupEntry(wrapper: EffectWrapperInternal, layout: EffectBindingLayout): GPUBindGroupEntry {\n if (layout.kind === \"uniform\") {\n const slot = findUniformSlot(wrapper, layout.binding);\n if (!slot) {\n throw new Error(`Effect \"${wrapper.name}\" missing uniform binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: { buffer: slot.buffer, size: slot.byteLength } };\n }\n if (layout.kind === \"texture\") {\n const slot = findTextureSlot(wrapper, layout.binding);\n if (!slot?.texture) {\n throw new Error(`Effect \"${wrapper.name}\" missing texture binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: slot.texture.view };\n }\n const textureSlot = layout.textureBinding != null ? findTextureSlot(wrapper, layout.textureBinding) : wrapper._textures[0];\n if (!textureSlot?.texture) {\n throw new Error(`Effect \"${wrapper.name}\" missing texture for sampler binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: textureSlot.texture.sampler };\n}\n\nfunction findUniformSlot(wrapper: EffectWrapperInternal, bindingNameOrIndex: string | number): EffectUniformSlot | undefined {\n return wrapper._uniforms.find((slot) => matchesBinding(slot.layout, bindingNameOrIndex));\n}\n\nfunction findTextureSlot(wrapper: EffectWrapperInternal, bindingNameOrIndex: string | number): EffectTextureSlot | undefined {\n return wrapper._textures.find((slot) => matchesBinding(slot.layout, bindingNameOrIndex));\n}\n\nfunction matchesBinding(layout: EffectBindingLayout, bindingNameOrIndex: string | number): boolean {\n if (typeof bindingNameOrIndex === \"number\") {\n return layout.binding === bindingNameOrIndex;\n }\n return layout.name === bindingNameOrIndex || String(layout.binding) === bindingNameOrIndex;\n}\n\nfunction writeUniformSlot(wrapper: EffectWrapperInternal, slot: EffectUniformSlot, data: ArrayBuffer | ArrayBufferView): void {\n const bytes = toBytes(data);\n if (bytes.byteLength > slot.byteLength) {\n throw new Error(`writeUniformSlot: ${bytes.byteLength} bytes exceeds uniform binding ${slot.layout.binding} size ${slot.byteLength}.`);\n }\n wrapper._engine._device.queue.writeBuffer(slot.buffer, 0, bytes.buffer, bytes.byteOffset, bytes.byteLength);\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n if (data instanceof ArrayBuffer) {\n return new U8(data);\n }\n return new U8(data.buffer, data.byteOffset, data.byteLength);\n}\n\nfunction isBufferData(data: ArrayBuffer | ArrayBufferView | Record<string | number, ArrayBuffer | ArrayBufferView>): data is ArrayBuffer | ArrayBufferView {\n return data instanceof ArrayBuffer || ArrayBuffer.isView(data);\n}\n\nfunction align4(value: number): number {\n return (value + 3) & ~3;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"effect-renderer.js","sources":["../../../src/effect/effect-renderer.ts"],"sourcesContent":["import { U8 } from \"../engine/typed-arrays.js\";\nimport { BU, SS } from \"../engine/gpu-flags.js\";\nimport { registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport type { SurfaceContext } from \"../engine/surface.js\";\nimport type { RenderTarget, RenderTargetSignature } from \"../engine/render-target.js\";\nimport { buildRenderTarget, createRenderTarget, disposeRenderTarget, targetSignatureKey } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { Task } from \"../frame-graph/task.js\";\n\nconst DEFAULT_VERTEX_WGSL = `struct EffectVertexOutput{@builtin(position) position:vec4<f32>,@location(0) uv:vec2<f32>};\n@vertex fn effectFullscreenVertex(@builtin(vertex_index) vertexIndex:u32)->EffectVertexOutput{var positions=array<vec2<f32>,3>(vec2<f32>(-1.0,-1.0),vec2<f32>(3.0,-1.0),vec2<f32>(-1.0,3.0));let p=positions[vertexIndex];var out:EffectVertexOutput;out.position=vec4<f32>(p,0.0,1.0);out.uv=p*0.5+vec2<f32>(0.5,0.5);return out;}`;\n\n/** Kind of GPU binding an effect exposes: a uniform buffer, a sampled texture, or a sampler. */\nexport type EffectBindingKind = \"uniform\" | \"texture\" | \"sampler\";\n\n/** Describes a single bind-group entry (binding slot, kind, and type details) for an effect wrapper. */\nexport interface EffectBindingLayout {\n name?: string;\n binding: number;\n kind: EffectBindingKind;\n visibility?: GPUShaderStageFlags;\n uniformByteLength?: number;\n textureSampleType?: GPUTextureSampleType;\n /** Texture view dimension for a `texture` binding (default `\"2d\"`). Set `\"2d-array\"`/`\"cube\"`/… so a\n * fullscreen effect can sample an array/cube texture (e.g. the CSM cascade depth array). */\n viewDimension?: GPUTextureViewDimension;\n samplerType?: GPUSamplerBindingType;\n textureBinding?: string | number;\n}\n\n/** Configuration for `createEffectWrapper`: the fullscreen fragment shader plus optional vertex shader, bindings, and blend state. */\nexport interface EffectWrapperOptions {\n name?: string;\n fragmentWGSL: string;\n vertexWGSL?: string;\n bindings?: EffectBindingLayout[];\n blend?: GPUBlendState;\n}\n\ninterface EffectUniformSlot {\n readonly layout: EffectBindingLayout;\n buffer: GPUBuffer;\n byteLength: number;\n}\n\ninterface EffectTextureSlot {\n readonly layout: EffectBindingLayout;\n texture: Texture2D | null;\n}\n\n/** A reusable fullscreen effect: owns its shader module, bind-group layout, pipelines, and uniform/texture slots. */\nexport interface EffectWrapper {\n readonly name: string;\n readonly options: EffectWrapperOptions;\n}\n\ninterface EffectWrapperInternal extends EffectWrapper {\n _engine: EngineContext;\n _shader: GPUShaderModule | null;\n _bindGroupLayout: GPUBindGroupLayout | null;\n _pipelineLayout: GPUPipelineLayout | null;\n _bindGroup: GPUBindGroup | null;\n _bindGroupDirty: boolean;\n _pipelines: Map<string, GPURenderPipeline> | null;\n _uniforms: EffectUniformSlot[];\n _textures: EffectTextureSlot[];\n}\n\n/** Configuration for `createEffectRenderTask`: the effect to draw, its render target, and optional clear state. */\nexport interface EffectRenderTaskConfig {\n name: string;\n effect: EffectWrapper;\n target: RenderTarget;\n clear?: boolean;\n clearColor?: GPUColorDict;\n}\n\n/** A frame-graph task that renders an `EffectWrapper` as a fullscreen pass into an offscreen `RenderTarget`. */\nexport interface EffectRenderTask extends Task {\n readonly name: string;\n /** @internal */\n readonly _config: EffectRenderTaskConfig;\n /** @internal */\n readonly _rt: RenderTarget;\n}\n\ninterface EffectRenderTaskInternal extends EffectRenderTask {\n _targetSignature: RenderTargetSignature;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n _pipeline: GPURenderPipeline | null;\n _bindGroup: GPUBindGroup | null;\n}\n\n// ─── Direct swapchain renderer (no scene / frame graph required) ─────────────\n\n/** Options for `createEffectRenderer`. */\nexport interface EffectRendererOptions {\n /** Label for GPU resources. Defaults to the effect's own name. */\n name?: string;\n /** Whether to clear the swapchain before drawing. Defaults to `true`. */\n clear?: boolean;\n /** Clear colour. Defaults to opaque black. */\n clearColor?: GPUColorDict;\n /**\n * Per-frame callback invoked just before the effect is drawn, receiving the\n * frame delta in milliseconds. Use it to update uniforms (e.g. time, animation\n * state). This is the effect-path equivalent of a scene's `onBeforeRender`.\n */\n update?: (deltaMs: number) => void;\n}\n\n/**\n * `EffectRenderer` — a fullscreen-effect `RenderingContext` that draws\n * directly to the swapchain without a `SceneContext` or frame-graph task.\n * Use `registerEffectRenderer` / `unregisterEffectRenderer` to attach it to\n * an engine, then call `startEngine` as usual.\n *\n * For offscreen render-to-texture workflows (effect result consumed by a\n * scene material) continue to use `createEffectRenderTask` inside a scene\n * frame graph.\n */\nexport interface EffectRenderer extends RenderingContext {\n readonly name: string;\n}\n\ninterface EffectRendererInternal extends EffectRenderer {\n _surface: SurfaceContext;\n _effect: EffectWrapperInternal;\n _clear: boolean;\n _rt: RenderTarget;\n _targetSignature: RenderTargetSignature;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n _pipeline: GPURenderPipeline | null;\n _bindGroup: GPUBindGroup | null;\n _disposed: boolean;\n}\n\n/**\n * Create an `EffectWrapper` for the given engine, allocating uniform buffers and\n * texture slots from `options.bindings`.\n * @param engine - The engine that owns the GPU resources.\n * @param options - Shader source and binding layout for the effect.\n * @returns The new effect wrapper.\n */\nexport function createEffectWrapper(engine: EngineContext, options: EffectWrapperOptions): EffectWrapper {\n const eng = engine as EngineContext;\n const wrapper: EffectWrapperInternal = {\n name: options.name ?? \"effect-wrapper\",\n options,\n _engine: eng,\n _shader: null,\n _bindGroupLayout: null,\n _pipelineLayout: null,\n _bindGroup: null,\n _bindGroupDirty: true,\n _pipelines: null,\n _uniforms: [],\n _textures: [],\n };\n createBindingSlots(wrapper);\n return wrapper;\n}\n\n/**\n * Write data into the effect's uniform buffer(s). Pass a single buffer to write the\n * wrapper's only uniform slot, or a record keyed by binding name/index to write specific slots.\n * @param wrapper - The effect wrapper to update.\n * @param data - The uniform bytes, or a map of binding key to uniform bytes.\n */\nexport function setEffectUniforms(wrapper: EffectWrapper, data: ArrayBuffer | ArrayBufferView | Record<string | number, ArrayBuffer | ArrayBufferView>): void {\n const internal = wrapper as EffectWrapperInternal;\n if (isBufferData(data)) {\n const slot = internal._uniforms[0];\n if (!slot) {\n throw new Error(\"setEffectUniforms: wrapper has no uniform binding.\");\n }\n writeUniformSlot(internal, slot, data);\n return;\n }\n for (const key of Object.keys(data)) {\n const slot = findUniformSlot(internal, key);\n if (!slot) {\n throw new Error(`setEffectUniforms: unknown uniform binding \"${key}\".`);\n }\n writeUniformSlot(internal, slot, data[key]!);\n }\n}\n\n/**\n * Bind a texture to one of the effect's texture slots, marking the bind group dirty so it is rebuilt.\n * @param wrapper - The effect wrapper to update.\n * @param bindingNameOrIndex - The texture binding's name or numeric index.\n * @param texture - The texture to bind.\n */\nexport function setEffectTexture(wrapper: EffectWrapper, bindingNameOrIndex: string | number, texture: Texture2D): void {\n const internal = wrapper as EffectWrapperInternal;\n const slot = findTextureSlot(internal, bindingNameOrIndex);\n if (!slot) {\n throw new Error(`setEffectTexture: unknown texture binding \"${String(bindingNameOrIndex)}\".`);\n }\n slot.texture = texture;\n internal._bindGroupDirty = true;\n}\n\n/**\n * Create a frame-graph task that draws an effect as a fullscreen pass into `config.target`.\n * @param config - The effect, target, and clear settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The render task to add to a frame graph.\n */\nexport function createEffectRenderTask(config: EffectRenderTaskConfig, engine: EngineContext, scene?: SceneContext): EffectRenderTask {\n const eng = engine as EngineContext;\n const effect = config.effect as EffectWrapperInternal;\n const rt = config.target;\n config.clearColor ??= { r: 0, g: 0, b: 0, a: 1 };\n const sampleCount = rt._descriptor.samples ?? 1;\n const targetSignature: RenderTargetSignature = {\n _colorFormat: rt._descriptor.format,\n _sampleCount: sampleCount,\n };\n const colorAttachment = { loadOp: \"clear\", storeOp: \"store\" } as GPURenderPassColorAttachment;\n const task: EffectRenderTaskInternal = {\n name: config.name,\n _config: config,\n engine: eng,\n scene,\n _passes: [],\n _rt: rt,\n _targetSignature: targetSignature,\n _renderPassDescriptor: { label: config.name, colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n _pipeline: null,\n _bindGroup: null,\n record(): void {\n buildRenderTarget(rt, eng);\n task._pipeline = getEffectPipeline(effect, task._targetSignature);\n task._bindGroup = getEffectBindGroup(effect);\n },\n execute(): number {\n const pipeline = task._pipeline;\n if (!pipeline) {\n throw new Error(`EffectRenderTask \"${task.name}\" executed before record().`);\n }\n task._bindGroup = getEffectBindGroup(effect);\n applyColorAttachmentState(task._colorAttachment, rt, undefined, task._config.clear !== false, task._config.clearColor!);\n const pass = eng._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n pass.setPipeline(pipeline);\n if (task._bindGroup) {\n pass.setBindGroup(0, task._bindGroup);\n }\n pass.draw(3);\n pass.end();\n return 1;\n },\n dispose(): void {\n task._passes.length = 0;\n disposeRenderTarget(task._rt);\n task._pipeline = null;\n task._bindGroup = null;\n },\n };\n return task;\n}\n\n/** Destroy the uniform buffers and clear the cached pipelines, bind groups, and slots owned by the effect wrapper. */\nexport function disposeEffectWrapper(wrapper: EffectWrapper): void {\n const internal = wrapper as EffectWrapperInternal;\n for (const slot of internal._uniforms) {\n slot.buffer.destroy();\n }\n internal._uniforms.length = 0;\n internal._textures.length = 0;\n internal._pipelines?.clear();\n internal._pipelines = null;\n internal._shader = null;\n internal._bindGroupLayout = null;\n internal._pipelineLayout = null;\n internal._bindGroup = null;\n internal._bindGroupDirty = true;\n}\n\n/**\n * Create an `EffectRenderer` that draws `effect` as a fullscreen pass to the\n * swapchain each frame. The renderer owns a swapchain `RenderTarget` and\n * implements `RenderingContext` directly — no `SceneContext` is needed.\n *\n * Call `registerEffectRenderer` to start rendering, `unregisterEffectRenderer`\n * to pause, and `disposeEffectRenderer` to free GPU resources.\n */\nexport function createEffectRenderer(surface: SurfaceContext, effect: EffectWrapper, options?: EffectRendererOptions): EffectRenderer {\n const eng = surface.engine;\n const ew = effect as EffectWrapperInternal;\n const name = options?.name ?? effect.name;\n const clear = options?.clear !== false;\n const clearColor: GPUColorDict = options?.clearColor ?? { r: 0, g: 0, b: 0, a: 1 };\n const update = options?.update;\n\n // No MSAA → render straight into the single-sample surface scRT; MSAA →\n // render into an MSAA colour RT and resolve into the scRT at end-of-pass.\n const useMsaa = surface.msaaSamples > 1;\n const rt = useMsaa ? createRenderTarget({ lbl: `${name}-msaa`, format: surface.format, samples: surface.msaaSamples, size: surface }) : surface.scRT;\n const resolveRt = useMsaa ? surface.scRT : undefined;\n\n const targetSignature: RenderTargetSignature = {\n _colorFormat: rt._descriptor.format,\n _sampleCount: rt._descriptor.samples ?? 1,\n };\n\n const colorAttachment: GPURenderPassColorAttachment = {\n view: undefined!,\n loadOp: \"clear\",\n storeOp: \"store\",\n };\n const renderPassDescriptor: GPURenderPassDescriptor = { label: name, colorAttachments: [colorAttachment] };\n\n const er: EffectRendererInternal = {\n name,\n clearColor,\n _drawCallsPre: 0,\n _surface: surface,\n _effect: ew,\n _clear: clear,\n _rt: rt,\n _targetSignature: targetSignature,\n _renderPassDescriptor: renderPassDescriptor,\n _colorAttachment: colorAttachment,\n _pipeline: null,\n _bindGroup: null,\n _disposed: false,\n _update(): void {\n update?.(eng._currentDelta);\n },\n _record(): number {\n if (er._disposed) {\n return 0;\n }\n ensureRtCanvasSize(er._rt);\n applyColorAttachmentState(er._colorAttachment, er._rt, resolveRt, er._clear, er.clearColor);\n const encoder = er._surface.engine._currentEncoder;\n if (!encoder) {\n return 0;\n }\n const pipeline = er._pipeline;\n if (!pipeline) {\n throw new Error(`EffectRenderer \"${er.name}\" recorded before registerEffectRenderer().`);\n }\n const pass = encoder.beginRenderPass(er._renderPassDescriptor);\n pass.setPipeline(pipeline);\n if (er._bindGroup) {\n pass.setBindGroup(0, er._bindGroup);\n }\n pass.draw(3);\n pass.end();\n return 1;\n },\n _resize(): void {\n if (er._disposed) {\n return;\n }\n buildRenderTarget(er._rt, er._surface.engine);\n },\n };\n return er;\n}\n\n/** Register the effect renderer with its surface. Idempotent — a second call is a no-op. */\nexport function registerEffectRenderer(er: EffectRenderer): void {\n const internal = er as EffectRendererInternal;\n prepareEffectRenderer(internal);\n registerRenderingContext(internal._surface, er);\n}\n\n/** Unregister the effect renderer from its surface. No-op if not registered. */\nexport function unregisterEffectRenderer(er: EffectRenderer): void {\n unregisterRenderingContext((er as EffectRendererInternal)._surface, er);\n}\n\n/** Unregister and free all GPU resources owned by the renderer. */\nexport function disposeEffectRenderer(er: EffectRenderer): void {\n const internal = er as EffectRendererInternal;\n if (internal._disposed) {\n return;\n }\n unregisterEffectRenderer(er);\n disposeRenderTarget(internal._rt);\n internal._disposed = true;\n}\n\nfunction createBindingSlots(wrapper: EffectWrapperInternal): void {\n const layouts = [...(wrapper.options.bindings ?? [])].sort((a, b) => a.binding - b.binding);\n const seen = new Set<number>();\n for (const layout of layouts) {\n if (seen.has(layout.binding)) {\n throw new Error(`createEffectWrapper: duplicate binding ${layout.binding}.`);\n }\n seen.add(layout.binding);\n if (layout.kind === \"uniform\") {\n const byteLength = align4(layout.uniformByteLength ?? 16);\n const buffer = wrapper._engine._device.createBuffer({\n label: `${wrapper.name}-${layout.name ?? layout.binding}-ubo`,\n size: byteLength,\n usage: BU.UNIFORM | BU.COPY_DST,\n });\n wrapper._uniforms.push({ layout, buffer, byteLength });\n } else if (layout.kind === \"texture\") {\n wrapper._textures.push({ layout, texture: null });\n }\n }\n}\n\nfunction applyColorAttachmentState(att: GPURenderPassColorAttachment, rt: RenderTarget, resolveRt: RenderTarget | undefined, clear: boolean, clearColor: GPUColorDict): void {\n att.clearValue = clearColor;\n att.loadOp = clear ? \"clear\" : \"load\";\n // Re-read each frame so a swapchain target (used as `rt` when single-sample, or as\n // the MSAA `resolveRt`) picks up its fresh per-frame view.\n att.view = rt._colorView!;\n att.resolveTarget = resolveRt?._colorView ?? undefined;\n}\n\nfunction ensureRtCanvasSize(rt: RenderTarget): void {\n const size = rt._descriptor.size;\n if (!(\"canvas\" in size)) {\n return;\n }\n // Surface-sized RT: rebuild when the surface's canvas backing-store has resized.\n const canvas = size.canvas;\n if (rt._width === canvas.width && rt._height === canvas.height) {\n return;\n }\n buildRenderTarget(rt, size.engine);\n}\n\nfunction getEffectPipeline(wrapper: EffectWrapperInternal, targetSignature: RenderTargetSignature): GPURenderPipeline {\n const key = targetSignatureKey(targetSignature);\n if (!wrapper._pipelines) {\n wrapper._pipelines = new Map();\n }\n const hit = wrapper._pipelines.get(key);\n if (hit) {\n return hit;\n }\n const device = wrapper._engine._device;\n const pipeline = device.createRenderPipeline({\n label: `${wrapper.name}-${key}`,\n layout: getPipelineLayout(wrapper),\n vertex: { module: getShaderModule(wrapper), entryPoint: \"effectFullscreenVertex\" },\n fragment: {\n module: getShaderModule(wrapper),\n entryPoint: \"effectFragment\",\n targets: [{ format: targetSignature._colorFormat!, blend: wrapper.options.blend }],\n },\n primitive: { topology: \"triangle-list\" },\n multisample: { count: targetSignature._sampleCount },\n });\n wrapper._pipelines.set(key, pipeline);\n return pipeline;\n}\n\nfunction getShaderModule(wrapper: EffectWrapperInternal): GPUShaderModule {\n if (!wrapper._shader) {\n wrapper._shader = wrapper._engine._device.createShaderModule({\n label: wrapper.name,\n code: `${wrapper.options.vertexWGSL ?? DEFAULT_VERTEX_WGSL}\\n${wrapper.options.fragmentWGSL}`,\n });\n }\n return wrapper._shader;\n}\n\nfunction getPipelineLayout(wrapper: EffectWrapperInternal): GPUPipelineLayout {\n if (!wrapper._pipelineLayout) {\n wrapper._pipelineLayout = wrapper._engine._device.createPipelineLayout({\n label: `${wrapper.name}-pipeline-layout`,\n bindGroupLayouts: [getBindGroupLayout(wrapper)],\n });\n }\n return wrapper._pipelineLayout;\n}\n\nfunction getBindGroupLayout(wrapper: EffectWrapperInternal): GPUBindGroupLayout {\n if (!wrapper._bindGroupLayout) {\n const entries = (wrapper.options.bindings ?? [])\n .slice()\n .sort((a, b) => a.binding - b.binding)\n .map((layout) => bindingLayoutEntry(layout));\n wrapper._bindGroupLayout = wrapper._engine._device.createBindGroupLayout({\n label: `${wrapper.name}-bgl`,\n entries,\n });\n }\n return wrapper._bindGroupLayout;\n}\n\nfunction bindingLayoutEntry(layout: EffectBindingLayout): GPUBindGroupLayoutEntry {\n const visibility = layout.visibility ?? SS.FRAGMENT;\n if (layout.kind === \"uniform\") {\n return { binding: layout.binding, visibility, buffer: { type: \"uniform\" } };\n }\n if (layout.kind === \"texture\") {\n return { binding: layout.binding, visibility, texture: { sampleType: layout.textureSampleType ?? \"float\", viewDimension: layout.viewDimension ?? \"2d\" } };\n }\n return { binding: layout.binding, visibility, sampler: { type: layout.samplerType ?? \"filtering\" } };\n}\n\nfunction getEffectBindGroup(wrapper: EffectWrapperInternal): GPUBindGroup | null {\n const bindings = wrapper.options.bindings ?? [];\n if (bindings.length === 0) {\n return null;\n }\n if (!wrapper._bindGroupDirty && wrapper._bindGroup) {\n return wrapper._bindGroup;\n }\n const entries = bindings\n .slice()\n .sort((a, b) => a.binding - b.binding)\n .map((layout) => bindGroupEntry(wrapper, layout));\n wrapper._bindGroup = wrapper._engine._device.createBindGroup({\n label: `${wrapper.name}-bg`,\n layout: getBindGroupLayout(wrapper),\n entries,\n });\n wrapper._bindGroupDirty = false;\n return wrapper._bindGroup;\n}\n\nfunction prepareEffectRenderer(er: EffectRendererInternal): void {\n er._pipeline ??= getEffectPipeline(er._effect, er._targetSignature);\n er._bindGroup = getEffectBindGroup(er._effect);\n}\n\nfunction bindGroupEntry(wrapper: EffectWrapperInternal, layout: EffectBindingLayout): GPUBindGroupEntry {\n if (layout.kind === \"uniform\") {\n const slot = findUniformSlot(wrapper, layout.binding);\n if (!slot) {\n throw new Error(`Effect \"${wrapper.name}\" missing uniform binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: { buffer: slot.buffer, size: slot.byteLength } };\n }\n if (layout.kind === \"texture\") {\n const slot = findTextureSlot(wrapper, layout.binding);\n if (!slot?.texture) {\n throw new Error(`Effect \"${wrapper.name}\" missing texture binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: slot.texture.view };\n }\n const textureSlot = layout.textureBinding != null ? findTextureSlot(wrapper, layout.textureBinding) : wrapper._textures[0];\n if (!textureSlot?.texture) {\n throw new Error(`Effect \"${wrapper.name}\" missing texture for sampler binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: textureSlot.texture.sampler };\n}\n\nfunction findUniformSlot(wrapper: EffectWrapperInternal, bindingNameOrIndex: string | number): EffectUniformSlot | undefined {\n return wrapper._uniforms.find((slot) => matchesBinding(slot.layout, bindingNameOrIndex));\n}\n\nfunction findTextureSlot(wrapper: EffectWrapperInternal, bindingNameOrIndex: string | number): EffectTextureSlot | undefined {\n return wrapper._textures.find((slot) => matchesBinding(slot.layout, bindingNameOrIndex));\n}\n\nfunction matchesBinding(layout: EffectBindingLayout, bindingNameOrIndex: string | number): boolean {\n if (typeof bindingNameOrIndex === \"number\") {\n return layout.binding === bindingNameOrIndex;\n }\n return layout.name === bindingNameOrIndex || String(layout.binding) === bindingNameOrIndex;\n}\n\nfunction writeUniformSlot(wrapper: EffectWrapperInternal, slot: EffectUniformSlot, data: ArrayBuffer | ArrayBufferView): void {\n const bytes = toBytes(data);\n if (bytes.byteLength > slot.byteLength) {\n throw new Error(`writeUniformSlot: ${bytes.byteLength} bytes exceeds uniform binding ${slot.layout.binding} size ${slot.byteLength}.`);\n }\n wrapper._engine._device.queue.writeBuffer(slot.buffer, 0, bytes.buffer, bytes.byteOffset, bytes.byteLength);\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n if (data instanceof ArrayBuffer) {\n return new U8(data);\n }\n return new U8(data.buffer, data.byteOffset, data.byteLength);\n}\n\nfunction isBufferData(data: ArrayBuffer | ArrayBufferView | Record<string | number, ArrayBuffer | ArrayBufferView>): data is ArrayBuffer | ArrayBufferView {\n return data instanceof ArrayBuffer || ArrayBuffer.isView(data);\n}\n\nfunction align4(value: number): number {\n return (value + 3) & ~3;\n}\n"],"names":[],"mappings":"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"}
|
package/lib/engine/engine.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { _setHpmAllocator } from '../math/_matrix-allocator.js';
|
|
2
2
|
import { isDomCanvas, _buildSurface, resizeSurface, _refreshScRT, setSurfaceSize } from './surface.js';
|
|
3
3
|
|
|
4
|
-
const VERSION = /* @__PURE__ */ (() => "1.
|
|
4
|
+
const VERSION = /* @__PURE__ */ (() => "1.6.0" )();
|
|
5
5
|
let _vis = 0;
|
|
6
6
|
function bumpVisibilityEpoch() {
|
|
7
7
|
_vis = _vis + 1 | 0;
|
package/lib/index.js
CHANGED
|
@@ -30,6 +30,7 @@ export { createChromaticAberrationPostProcessTask } from './post-process/chromat
|
|
|
30
30
|
export { createCircleOfConfusionPostProcessTask } from './post-process/circle-of-confusion.js';
|
|
31
31
|
export { createBloomPostProcessTask } from './post-process/bloom.js';
|
|
32
32
|
export { DepthOfFieldBlurLevel, createDepthOfFieldPostProcessTask } from './post-process/depth-of-field.js';
|
|
33
|
+
export { createTaaPostProcessTask } from './post-process/taa.js';
|
|
33
34
|
export { createArcRotateCamera } from './camera/arc-rotate.js';
|
|
34
35
|
export { attachControl, setCameraLimits } from './camera/arc-rotate-controls.js';
|
|
35
36
|
export { createFreeCamera } from './camera/free-camera.js';
|
|
@@ -163,7 +164,9 @@ export { attachBoundingBoxGizmoToNode, createBoundingBoxGizmo, disposeBoundingBo
|
|
|
163
164
|
export { createGridSpriteAtlas, loadSpriteAtlas } from './sprite/shared/sprite-atlas.js';
|
|
164
165
|
export { appendSpriteAtlasFrames, createSpriteAtlasFromFrames } from './sprite/shared/sprite-atlas-packer.js';
|
|
165
166
|
export { spriteBlendAdditive, spriteBlendAlpha, spriteBlendMultiply, spriteBlendPremultiplied } from './sprite/sprite-blend.js';
|
|
166
|
-
export { addSprite2DIndex, clearSprite2DLayer, createSprite2DLayer, removeSprite2DIndex, setSprite2DFrameIndex, setSprite2DShaderParams,
|
|
167
|
+
export { addSprite2DIndex, clearSprite2DLayer, createSprite2DLayer, removeSprite2DIndex, setSprite2DFrameIndex, setSprite2DShaderParams, updateSprite2DIndex } from './sprite/sprite-2d.js';
|
|
168
|
+
export { setSprite2DCoverageGamma } from './sprite/sprite-2d-coverage-gamma.js';
|
|
169
|
+
export { setSprite2DUvOffset } from './sprite/sprite-2d-uvscroll.js';
|
|
167
170
|
export { createSprite2DCustomShader } from './sprite/sprite-custom-shader.js';
|
|
168
171
|
export { addSprite2D, getSprite2DHandleIndex, isSprite2DHandleAlive, removeSprite2D, setSprite2DFrame, updateSprite2D } from './sprite/sprite-2d-handle.js';
|
|
169
172
|
export { addDepthHostedSpriteLayer } from './sprite/sprite-scene.js';
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { F32 } from '../engine/typed-arrays.js';
|
|
2
|
+
import { createRenderTarget, disposeRenderTarget, buildRenderTarget } from '../engine/render-target.js';
|
|
3
|
+
import { createPostProcessTask } from '../frame-graph/post-process-task.js';
|
|
4
|
+
|
|
5
|
+
const TAA_HISTORY_TEXTURE_WGSL = `@group(0) @binding(2) var taaHistory:texture_2d<f32>;`;
|
|
6
|
+
const TAA_UNIFORM_WGSL = `struct TaaParams{factor:f32,p0:f32,p1:f32,p2:f32}
|
|
7
|
+
@group(0) @binding(3) var<uniform> taaParams:TaaParams;`;
|
|
8
|
+
const TAA_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let h=textureSample(taaHistory,sourceSampler,uv);return mix(h,color,taaParams.factor);}`;
|
|
9
|
+
const TAA_COPY_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{return color;}`;
|
|
10
|
+
function createTaaPostProcessTask(config, engine, scene) {
|
|
11
|
+
const name = config.name ?? "taa";
|
|
12
|
+
const source = config.sourceTexture;
|
|
13
|
+
const target = config.targetTexture ?? null;
|
|
14
|
+
const samples = Math.max(1, Math.floor(config.samples ?? 8));
|
|
15
|
+
const sizeRef = source._descriptor.size;
|
|
16
|
+
const history = createRenderTarget({ lbl: `${name}-history`, format: "rgba16float", samples: 1, size: sizeRef });
|
|
17
|
+
const temp = createRenderTarget({ lbl: `${name}-temp`, format: "rgba16float", samples: 1, size: sizeRef });
|
|
18
|
+
const blend = createPostProcessTask(
|
|
19
|
+
{
|
|
20
|
+
name: `${name}-blend`,
|
|
21
|
+
sourceTexture: source,
|
|
22
|
+
// Nearest sampling reads the exact co-located texel of both the current
|
|
23
|
+
// frame and the history (all three targets share a resolution).
|
|
24
|
+
sourceSamplingMode: "nearest",
|
|
25
|
+
targetTexture: temp,
|
|
26
|
+
_shader: {
|
|
27
|
+
extraTextureWGSL: TAA_HISTORY_TEXTURE_WGSL,
|
|
28
|
+
extraTextures: [history],
|
|
29
|
+
uniformWGSL: TAA_UNIFORM_WGSL,
|
|
30
|
+
uniformBinding: 3,
|
|
31
|
+
uniformByteLength: 16,
|
|
32
|
+
writeUniforms(data) {
|
|
33
|
+
data[0] = task._factor;
|
|
34
|
+
},
|
|
35
|
+
fragmentWGSL: TAA_FRAGMENT_WGSL
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
engine,
|
|
39
|
+
scene
|
|
40
|
+
);
|
|
41
|
+
const present = createPostProcessTask(
|
|
42
|
+
{
|
|
43
|
+
name: `${name}-present`,
|
|
44
|
+
sourceTexture: temp,
|
|
45
|
+
sourceSamplingMode: "nearest",
|
|
46
|
+
targetTexture: target ?? engine.scRT,
|
|
47
|
+
_shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL }
|
|
48
|
+
},
|
|
49
|
+
engine,
|
|
50
|
+
scene
|
|
51
|
+
);
|
|
52
|
+
const historyUpdate = createPostProcessTask(
|
|
53
|
+
{
|
|
54
|
+
name: `${name}-history-update`,
|
|
55
|
+
sourceTexture: temp,
|
|
56
|
+
sourceSamplingMode: "nearest",
|
|
57
|
+
targetTexture: history,
|
|
58
|
+
_shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL }
|
|
59
|
+
},
|
|
60
|
+
engine,
|
|
61
|
+
scene
|
|
62
|
+
);
|
|
63
|
+
const task = {
|
|
64
|
+
name,
|
|
65
|
+
engine,
|
|
66
|
+
scene,
|
|
67
|
+
_passes: [],
|
|
68
|
+
sourceTexture: source,
|
|
69
|
+
targetTexture: target,
|
|
70
|
+
outputTexture: target ?? engine.scRT,
|
|
71
|
+
factor: config.factor ?? 0.05,
|
|
72
|
+
samples,
|
|
73
|
+
disableOnCameraMove: config.disableOnCameraMove ?? true,
|
|
74
|
+
_blend: blend,
|
|
75
|
+
_present: present,
|
|
76
|
+
_historyUpdate: historyUpdate,
|
|
77
|
+
_history: history,
|
|
78
|
+
_temp: temp,
|
|
79
|
+
_sourceRenderTask: config.sourceRenderTask,
|
|
80
|
+
_halton: generateHalton(samples),
|
|
81
|
+
_haltonIndex: 0,
|
|
82
|
+
_jitterScratch: new F32(16),
|
|
83
|
+
_firstUpdate: true,
|
|
84
|
+
_lastCamVer: -1,
|
|
85
|
+
_factor: 1,
|
|
86
|
+
record() {
|
|
87
|
+
const { width: w, height: h } = resolveSourceSize(task.sourceTexture);
|
|
88
|
+
ensurePersistentTarget(history, engine, w, h);
|
|
89
|
+
ensurePersistentTarget(temp, engine, w, h);
|
|
90
|
+
blend.record();
|
|
91
|
+
present.record();
|
|
92
|
+
historyUpdate.record();
|
|
93
|
+
task._firstUpdate = true;
|
|
94
|
+
task._haltonIndex = 0;
|
|
95
|
+
task._lastCamVer = -1;
|
|
96
|
+
},
|
|
97
|
+
execute() {
|
|
98
|
+
const cam = task._sourceRenderTask.scene.camera;
|
|
99
|
+
const camVer = cam ? cam.worldMatrixVersion : 0;
|
|
100
|
+
const moved = camVer !== task._lastCamVer;
|
|
101
|
+
task._lastCamVer = camVer;
|
|
102
|
+
const reset = task._firstUpdate || moved && task.disableOnCameraMove;
|
|
103
|
+
task._factor = reset ? 1 : task.factor;
|
|
104
|
+
blend.updateUniforms();
|
|
105
|
+
let draws = blend.execute?.() ?? 0;
|
|
106
|
+
draws += present.execute?.() ?? 0;
|
|
107
|
+
draws += historyUpdate.execute?.() ?? 0;
|
|
108
|
+
task._firstUpdate = false;
|
|
109
|
+
advanceJitter(task);
|
|
110
|
+
return draws;
|
|
111
|
+
},
|
|
112
|
+
updateUniforms() {
|
|
113
|
+
blend.updateUniforms();
|
|
114
|
+
},
|
|
115
|
+
dispose() {
|
|
116
|
+
task._passes.length = 0;
|
|
117
|
+
blend.dispose();
|
|
118
|
+
present.dispose();
|
|
119
|
+
historyUpdate.dispose();
|
|
120
|
+
history._eager = false;
|
|
121
|
+
temp._eager = false;
|
|
122
|
+
disposeRenderTarget(history);
|
|
123
|
+
disposeRenderTarget(temp);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
return task;
|
|
127
|
+
}
|
|
128
|
+
function ensurePersistentTarget(rt, engine, width, height) {
|
|
129
|
+
if (rt._eager && rt._width === width && rt._height === height) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
rt._eager = false;
|
|
133
|
+
disposeRenderTarget(rt);
|
|
134
|
+
rt._descriptor.size = { width, height };
|
|
135
|
+
buildRenderTarget(rt, engine);
|
|
136
|
+
rt._eager = true;
|
|
137
|
+
}
|
|
138
|
+
function resolveSourceSize(source) {
|
|
139
|
+
if (source._width > 0 && source._height > 0) {
|
|
140
|
+
return { width: source._width, height: source._height };
|
|
141
|
+
}
|
|
142
|
+
const size = source._descriptor.size;
|
|
143
|
+
if ("canvas" in size) {
|
|
144
|
+
return { width: size.canvas.width, height: size.canvas.height };
|
|
145
|
+
}
|
|
146
|
+
return { width: size.width, height: size.height };
|
|
147
|
+
}
|
|
148
|
+
function generateHalton(samples) {
|
|
149
|
+
const seq = new F32(samples * 2);
|
|
150
|
+
for (let i = 1; i <= samples; i++) {
|
|
151
|
+
seq[(i - 1) * 2] = halton(i, 2) - 0.5;
|
|
152
|
+
seq[(i - 1) * 2 + 1] = halton(i, 3) - 0.5;
|
|
153
|
+
}
|
|
154
|
+
return seq;
|
|
155
|
+
}
|
|
156
|
+
function halton(index, base) {
|
|
157
|
+
let fraction = 1;
|
|
158
|
+
let result = 0;
|
|
159
|
+
while (index > 0) {
|
|
160
|
+
fraction /= base;
|
|
161
|
+
result += fraction * (index % base);
|
|
162
|
+
index = Math.floor(index / base);
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
function advanceJitter(task) {
|
|
167
|
+
const src = task._sourceRenderTask;
|
|
168
|
+
const clean = src._suData;
|
|
169
|
+
const w = task.sourceTexture._width;
|
|
170
|
+
const h = task.sourceTexture._height;
|
|
171
|
+
if (w <= 0 || h <= 0) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const jx = task._halton[task._haltonIndex] / (w / 2);
|
|
175
|
+
const jy = task._halton[task._haltonIndex + 1] / (h / 2);
|
|
176
|
+
task._haltonIndex += 2;
|
|
177
|
+
if (task._haltonIndex >= task._halton.length) {
|
|
178
|
+
task._haltonIndex = 0;
|
|
179
|
+
}
|
|
180
|
+
const out = task._jitterScratch;
|
|
181
|
+
for (let c = 0; c < 4; c++) {
|
|
182
|
+
const b = c * 4;
|
|
183
|
+
const w3 = clean[b + 3];
|
|
184
|
+
out[b] = clean[b] + jx * w3;
|
|
185
|
+
out[b + 1] = clean[b + 1] + jy * w3;
|
|
186
|
+
out[b + 2] = clean[b + 2];
|
|
187
|
+
out[b + 3] = w3;
|
|
188
|
+
}
|
|
189
|
+
task.engine._device.queue.writeBuffer(src._sceneUBO, 0, out);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export { createTaaPostProcessTask };
|
|
193
|
+
//# sourceMappingURL=taa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taa.js","sources":["../../../src/post-process/taa.ts"],"sourcesContent":["// Temporal Anti-Aliasing (TAA) — a frame-graph post-process task.\n//\n// TAA jitters the camera projection by a sub-pixel Halton offset every frame and\n// accumulates a moving average of consecutive (jittered) frames. Spreading the\n// supersampling over time yields high-quality edge anti-aliasing without rendering\n// the scene multiple times per frame. The accumulated history converges to a\n// supersampled image after a few dozen frames.\n//\n// This task is a pure frame-graph node: add it at the END of a chain whose source\n// render task draws the scene into `sourceTexture`. Each frame it:\n// 1. blend : temp = mix(history, current, factor) (history bound as extra)\n// 2. present : temp -> targetTexture (e.g. the swapchain)\n// 3. historyUpd : temp -> history (becomes next frame's history)\n// 4. advances the Halton sequence and writes the jittered viewProjection into the\n// *source render task's* scene UBO so the NEXT frame renders sub-pixel shifted.\n//\n// `factor` is the blend weight of the current frame (BJS default 0.05). On the first\n// frame and on a camera-move reset it is forced to 1 (output == current) so no stale\n// history bleeds in.\n//\n// The jitter is injected by overwriting only the viewProjection slice (bytes 0..63)\n// of the source task's already-packed scene UBO. The source task's UBO write is\n// cached on the camera's worldMatrixVersion, so with a static camera our jittered\n// matrix survives each frame; when the camera moves the source re-packs a clean\n// matrix (a natural reset) and we set factor=1 for that frame. This needs zero\n// changes to the shared camera / scene-uniform hot path — so scenes that do not use\n// TAA pay nothing.\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport { buildRenderTarget, createRenderTarget, disposeRenderTarget } from \"../engine/render-target.js\";\nimport { createPostProcessTask, type PostProcessTask, type PostProcessTaskSettings } from \"../frame-graph/post-process-task.js\";\nimport type { RenderTask } from \"../frame-graph/render-task.js\";\nimport type { Task } from \"../frame-graph/task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\n/** Configuration for `createTaaPostProcessTask`. */\nexport interface TaaPostProcessTaskConfig extends PostProcessTaskSettings {\n /** The render task that draws the scene into `sourceTexture`. TAA jitters this\n * task's camera projection each frame (mirrors BJS `FrameGraphTAATask.objectRendererTask`). */\n sourceRenderTask: RenderTask;\n /** Blend weight of the current frame against the accumulated history (default: 0.05). */\n factor?: number;\n /** Number of jitter samples in the Halton sequence (default: 8). */\n samples?: number;\n /** Force a one-frame reset (output == current) whenever the camera moves (default: true).\n * Avoids ghosting while the view changes. */\n disableOnCameraMove?: boolean;\n}\n\n/** A Temporal Anti-Aliasing post-process task: accumulates jittered frames into an\n * anti-aliased image. Inject at the end of a frame-graph chain. */\nexport interface TaaPostProcessTask extends Task, PostProcessTaskSettings {\n readonly name: string;\n sourceTexture: RenderTarget;\n targetTexture: RenderTarget | null;\n outputTexture: RenderTarget;\n /** Blend weight of the current frame (smaller = smoother / slower convergence). */\n factor: number;\n /** Number of Halton jitter samples. */\n readonly samples: number;\n /** Reset to the current frame whenever the camera moves. */\n disableOnCameraMove: boolean;\n /** Recompute and upload the blend pass uniforms from current settings. */\n updateUniforms(): void;\n}\n\ninterface TaaTaskInternal extends TaaPostProcessTask {\n _blend: PostProcessTask;\n _present: PostProcessTask;\n _historyUpdate: PostProcessTask;\n _history: RenderTarget;\n _temp: RenderTarget;\n _sourceRenderTask: RenderTask;\n /** Raw Halton offsets in [-0.5, 0.5): [x0,y0, x1,y1, ...]. Scaled per-frame by source size. */\n _halton: Float32Array;\n _haltonIndex: number;\n _jitterScratch: Float32Array;\n _firstUpdate: boolean;\n _lastCamVer: number;\n _factor: number;\n}\n\nconst TAA_HISTORY_TEXTURE_WGSL = `@group(0) @binding(2) var taaHistory:texture_2d<f32>;`;\n\nconst TAA_UNIFORM_WGSL = `struct TaaParams{factor:f32,p0:f32,p1:f32,p2:f32}\n@group(0) @binding(3) var<uniform> taaParams:TaaParams;`;\n\n// mix(history, current, factor): factor=1 -> current only (first frame / reset).\nconst TAA_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let h=textureSample(taaHistory,sourceSampler,uv);return mix(h,color,taaParams.factor);}`;\n\n// Identity passthrough used by the present + history-update copies.\nconst TAA_COPY_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{return color;}`;\n\n/**\n * Create a Temporal Anti-Aliasing post-process task.\n * @param config - Source texture + source render task, blend factor, sample count.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene.\n * @returns The TAA post-process task. Add it at the end of the frame-graph chain.\n */\nexport function createTaaPostProcessTask(config: TaaPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): TaaPostProcessTask {\n const name = config.name ?? \"taa\";\n const source = config.sourceTexture;\n const target = config.targetTexture ?? null;\n // Clamp to >= 1: a zero/negative sample count would make `generateHalton` return an\n // empty sequence and `advanceJitter` write NaN jitter offsets into the source UBO.\n const samples = Math.max(1, Math.floor(config.samples ?? 8));\n const sizeRef = source._descriptor.size;\n\n // History accumulates at RGBA16F so the 0.05 moving average does not band on\n // an 8-bit buffer (matches BJS half-float history).\n const history = createRenderTarget({ lbl: `${name}-history`, format: \"rgba16float\", samples: 1, size: sizeRef });\n const temp = createRenderTarget({ lbl: `${name}-temp`, format: \"rgba16float\", samples: 1, size: sizeRef });\n\n const blend = createPostProcessTask(\n {\n name: `${name}-blend`,\n sourceTexture: source,\n // Nearest sampling reads the exact co-located texel of both the current\n // frame and the history (all three targets share a resolution).\n sourceSamplingMode: \"nearest\",\n targetTexture: temp,\n _shader: {\n extraTextureWGSL: TAA_HISTORY_TEXTURE_WGSL,\n extraTextures: [history],\n uniformWGSL: TAA_UNIFORM_WGSL,\n uniformBinding: 3,\n uniformByteLength: 16,\n writeUniforms(data) {\n data[0] = task._factor;\n },\n fragmentWGSL: TAA_FRAGMENT_WGSL,\n },\n },\n engine,\n scene\n );\n const present = createPostProcessTask(\n {\n name: `${name}-present`,\n sourceTexture: temp,\n sourceSamplingMode: \"nearest\",\n targetTexture: target ?? engine.scRT,\n _shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL },\n },\n engine,\n scene\n );\n const historyUpdate = createPostProcessTask(\n {\n name: `${name}-history-update`,\n sourceTexture: temp,\n sourceSamplingMode: \"nearest\",\n targetTexture: history,\n _shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL },\n },\n engine,\n scene\n );\n\n const task: TaaTaskInternal = {\n name,\n engine,\n scene,\n _passes: [],\n sourceTexture: source,\n targetTexture: target,\n outputTexture: target ?? engine.scRT,\n factor: config.factor ?? 0.05,\n samples,\n disableOnCameraMove: config.disableOnCameraMove ?? true,\n _blend: blend,\n _present: present,\n _historyUpdate: historyUpdate,\n _history: history,\n _temp: temp,\n _sourceRenderTask: config.sourceRenderTask,\n _halton: generateHalton(samples),\n _haltonIndex: 0,\n _jitterScratch: new F32(16),\n _firstUpdate: true,\n _lastCamVer: -1,\n _factor: 1,\n record(): void {\n // History + temp are persistent ping-pong buffers: allocate them once\n // (eager), sized to the source, and only reallocate on a real size change.\n // Marking them eager makes the sub-tasks' internal `buildRenderTarget`\n // no-op on them — critical because `historyUpdate` targets `history`, and a\n // rebuild there would destroy the texture `blend`'s bind group references.\n const { width: w, height: h } = resolveSourceSize(task.sourceTexture);\n ensurePersistentTarget(history, engine, w, h);\n ensurePersistentTarget(temp, engine, w, h);\n blend.record();\n present.record();\n historyUpdate.record();\n task._firstUpdate = true;\n task._haltonIndex = 0;\n task._lastCamVer = -1;\n },\n execute(): number {\n const cam = task._sourceRenderTask.scene.camera;\n const camVer = cam ? cam.worldMatrixVersion : 0;\n const moved = camVer !== task._lastCamVer;\n task._lastCamVer = camVer;\n\n // factor=1 on the first frame and on camera-move reset: take the current\n // (un-jittered) frame verbatim, discarding stale history.\n const reset = task._firstUpdate || (moved && task.disableOnCameraMove);\n task._factor = reset ? 1 : task.factor;\n blend.updateUniforms();\n\n let draws = blend.execute?.() ?? 0;\n draws += present.execute?.() ?? 0;\n draws += historyUpdate.execute?.() ?? 0;\n\n task._firstUpdate = false;\n\n // Prepare the NEXT frame's jitter: advance the Halton sequence and write the\n // jittered viewProjection into the source task's UBO. Always done — even on a\n // reset frame — so accumulation starts immediately on the following frame.\n // The blend `factor` reset already prevents stale-history bleed, and a still-\n // moving camera re-packs a clean matrix next frame anyway (overwriting this).\n advanceJitter(task);\n return draws;\n },\n updateUniforms(): void {\n blend.updateUniforms();\n },\n dispose(): void {\n task._passes.length = 0;\n blend.dispose();\n present.dispose();\n historyUpdate.dispose();\n // Clear the eager flag so the persistent buffers are actually freed.\n history._eager = false;\n temp._eager = false;\n disposeRenderTarget(history);\n disposeRenderTarget(temp);\n },\n };\n return task;\n}\n\n/** Allocate (or, on a size change, reallocate) a persistent ping-pong target sized\n * `width`×`height`. The target is marked `_eager` so the post-process sub-tasks'\n * internal `buildRenderTarget` no-ops on it, keeping accumulated history alive across\n * frames and preventing a rebuild from destroying a texture still bound elsewhere. */\nfunction ensurePersistentTarget(rt: RenderTarget, engine: EngineContext, width: number, height: number): void {\n if (rt._eager && rt._width === width && rt._height === height) {\n return;\n }\n rt._eager = false;\n disposeRenderTarget(rt);\n rt._descriptor.size = { width, height };\n buildRenderTarget(rt, engine);\n rt._eager = true;\n}\n\n/** Resolve a render target's pixel size: prefer its allocated dimensions, falling back\n * to the descriptor's surface (multi-surface safe — does not assume the engine canvas)\n * or explicit pixel size before the target has been built. */\nfunction resolveSourceSize(source: RenderTarget): { width: number; height: number } {\n if (source._width > 0 && source._height > 0) {\n return { width: source._width, height: source._height };\n }\n const size = source._descriptor.size;\n if (\"canvas\" in size) {\n return { width: size.canvas.width, height: size.canvas.height };\n }\n return { width: size.width, height: size.height };\n}\n\n/** Generate `samples` 2D Halton offsets (base 2 / base 3) centered on [-0.5, 0.5). */\nfunction generateHalton(samples: number): Float32Array {\n const seq = new F32(samples * 2);\n for (let i = 1; i <= samples; i++) {\n seq[(i - 1) * 2] = halton(i, 2) - 0.5;\n seq[(i - 1) * 2 + 1] = halton(i, 3) - 0.5;\n }\n return seq;\n}\n\nfunction halton(index: number, base: number): number {\n let fraction = 1;\n let result = 0;\n while (index > 0) {\n fraction /= base;\n result += fraction * (index % base);\n index = Math.floor(index / base);\n }\n return result;\n}\n\n/** Advance the Halton sequence and overwrite the source task's viewProjection\n * (column-major bytes 0..63 of its scene UBO) with a sub-pixel jittered matrix. */\nfunction advanceJitter(task: TaaTaskInternal): void {\n const src = task._sourceRenderTask;\n const clean = src._suData;\n const w = task.sourceTexture._width;\n const h = task.sourceTexture._height;\n if (w <= 0 || h <= 0) {\n return;\n }\n\n // NDC sub-pixel offset: one pixel spans 2/size in NDC, so size/2 is the denominator.\n const jx = task._halton[task._haltonIndex]! / (w / 2);\n const jy = task._halton[task._haltonIndex + 1]! / (h / 2);\n task._haltonIndex += 2;\n if (task._haltonIndex >= task._halton.length) {\n task._haltonIndex = 0;\n }\n\n // Translate the projected image by (jx, jy) in NDC: clip.xy += (jx,jy)*clip.w.\n // Column-major: row r, col c lives at c*4+r. Add j*row3 to row0 / row1.\n const out = task._jitterScratch;\n for (let c = 0; c < 4; c++) {\n const b = c * 4;\n const w3 = clean[b + 3]!;\n out[b] = clean[b]! + jx * w3;\n out[b + 1] = clean[b + 1]! + jy * w3;\n out[b + 2] = clean[b + 2]!;\n out[b + 3] = w3;\n }\n task.engine._device.queue.writeBuffer(src._sceneUBO, 0, out as Float32Array<ArrayBuffer>);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -6,52 +6,52 @@ import { _registerBillboardFxHook } from './sprite-fx-hook.js';
|
|
|
6
6
|
function makeCustomBillboardWgsl(orientation, extraTextures, fragment) {
|
|
7
7
|
const fxBinding = 3 + extraTextures.length * 2;
|
|
8
8
|
return `${SCENE_UBO_WGSL}
|
|
9
|
-
struct
|
|
10
|
-
opacityMul:
|
|
11
|
-
axisAndCutoff:
|
|
9
|
+
struct S {
|
|
10
|
+
opacityMul: vec4f,
|
|
11
|
+
axisAndCutoff: vec4f,
|
|
12
12
|
};
|
|
13
|
-
@group(1) @binding(0) var<uniform> billboards:
|
|
13
|
+
@group(1) @binding(0) var<uniform> billboards: S;
|
|
14
14
|
@group(1) @binding(1) var atlasTex: texture_2d<f32>;
|
|
15
15
|
@group(1) @binding(2) var atlasSamp: sampler;
|
|
16
16
|
${makeExtraBindingsWgsl(1, 3, extraTextures)}${makeFxStructWgsl(1, fxBinding)}
|
|
17
17
|
${makeBillboardBasisWgsl(orientation)}
|
|
18
|
-
struct
|
|
18
|
+
struct I {
|
|
19
19
|
@builtin(vertex_index) vid: u32,
|
|
20
|
-
@location(0)
|
|
21
|
-
@location(1)
|
|
22
|
-
@location(2)
|
|
23
|
-
@location(3)
|
|
24
|
-
@location(4)
|
|
25
|
-
@location(5)
|
|
26
|
-
@location(6)
|
|
20
|
+
@location(0) p: vec3f,
|
|
21
|
+
@location(1) s: vec2f,
|
|
22
|
+
@location(2) a: vec2f,
|
|
23
|
+
@location(3) b: vec2f,
|
|
24
|
+
@location(4) r: f32,
|
|
25
|
+
@location(5) o: vec2f,
|
|
26
|
+
@location(6) c: vec4f,
|
|
27
27
|
};
|
|
28
|
-
struct
|
|
29
|
-
@builtin(position)
|
|
30
|
-
@location(0) uv:
|
|
31
|
-
@location(1) tint:
|
|
28
|
+
struct O {
|
|
29
|
+
@builtin(position) p: vec4f,
|
|
30
|
+
@location(0) uv: vec2f,
|
|
31
|
+
@location(1) tint: vec4f,
|
|
32
32
|
@location(2) viewDist: f32,
|
|
33
|
-
@location(3) vWorldPos:
|
|
33
|
+
@location(3) vWorldPos: vec3f,
|
|
34
34
|
};
|
|
35
35
|
@vertex
|
|
36
|
-
fn vs(in:
|
|
37
|
-
let
|
|
38
|
-
let
|
|
39
|
-
let
|
|
40
|
-
let
|
|
41
|
-
let
|
|
42
|
-
let
|
|
43
|
-
let
|
|
44
|
-
var out:
|
|
45
|
-
out.
|
|
46
|
-
out.uv = mix(in.
|
|
47
|
-
out.tint = in.
|
|
48
|
-
let viewCenter = scene.view *
|
|
36
|
+
fn vs(in: I) -> O {
|
|
37
|
+
let q = vec2f(select(0.0, 1.0, in.vid == 1u || in.vid == 2u), select(0.0, 1.0, in.vid >= 2u));
|
|
38
|
+
let l = (q - in.o) * in.s;
|
|
39
|
+
let cr = cos(in.r);
|
|
40
|
+
let sr = sin(in.r);
|
|
41
|
+
let r = vec2f(l.x * cr - l.y * sr, l.x * sr + l.y * cr);
|
|
42
|
+
let b = basis(in.p);
|
|
43
|
+
let wp = in.p + b.r * r.x + b.u * r.y;
|
|
44
|
+
var out: O;
|
|
45
|
+
out.p = scene.viewProjection * vec4f(wp, 1);
|
|
46
|
+
out.uv = mix(in.a, in.b, q);
|
|
47
|
+
out.tint = in.c;
|
|
48
|
+
let viewCenter = scene.view * vec4f(in.p, 1);
|
|
49
49
|
out.viewDist = length(viewCenter.xyz);
|
|
50
|
-
out.vWorldPos =
|
|
50
|
+
out.vWorldPos = wp;
|
|
51
51
|
return out;
|
|
52
52
|
}
|
|
53
53
|
@fragment
|
|
54
|
-
fn fs(in:
|
|
54
|
+
fn fs(in: O) -> @location(0) vec4f {
|
|
55
55
|
${fragment}
|
|
56
56
|
}`;
|
|
57
57
|
}
|