UNPKG

@itwin/frontend-devtools

Version:

Debug menu and supporting UI widgets

105 lines (103 loc) 4.86 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Effects */ import { assert } from "@itwin/core-bentley"; import { Tool, UniformType, VaryingType } from "@itwin/core-frontend"; import { AddEffectTool, refreshViewportsForEffect } from "./EffectTools"; import { parseArgs } from "../tools/parseArgs"; /** Adds a screen-space effect to the selected [[Viewport]] to simulate the lens distortion produced by real-world cameras with very wide fields of view. * Based on https://www.decarpentier.nl/lens-distortion * The effect is improved considerably by enabling anti-aliasing (e.g., via [RenderSystem.Options.antialiasSamples]($frontend) at startup, or using the `fdt aasamples` key-in`). * @note Because this effect applies a non-linear transform to each pixel, operations like snapping to geometry will not work properly. Element locate will work however - @see [ScreenSpaceEffectSource.sampleSourcePixel]($frontend). * @beta */ export class LensDistortionEffect extends AddEffectTool { static toolId = "LensDistortionEffect"; get effectName() { return "lensdistortion"; } get textureCoordFromPosition() { return true; } get source() { return { vertex: ` void effectMain(vec4 position) { vec2 uv = textureCoordFromPosition(position); float scaledHeight = strength * height; float cylAspectRatio = aspectRatio * cylindricalRatio; float aspectDiagSq = aspectRatio * aspectRatio + 1.0; float diagSq = scaledHeight * scaledHeight * aspectDiagSq; vec2 signedUV = (2.0 * uv + vec2(-1.0, -1.0)); float z = 0.5 * sqrt(diagSq + 1.0) + 0.5; float ny = (z - 1.0) / (cylAspectRatio * cylAspectRatio + 1.0); vUVDot = sqrt(ny) * vec2(cylAspectRatio, 1.0) * signedUV; vUV = vec3(0.5, 0.5, 1.0) * z + vec3(-0.5, -0.5, 0.0); vUV.xy += uv; }`, // We simply shift pixels - we don't alter their colors. fragment: ` vec4 effectMain() { return sampleSourcePixel(); }`, // Because we're moving pixels around, we must tell the render system where the source pixel was originally located - otherwise // element locate will not work correctly. sampleSourcePixel: ` vec3 uv = dot(vUVDot, vUVDot) * vec3(-0.5, -0.5, -1.0) + vUV; return TEXTURE_PROJ(u_diffuse, uv); `, }; } defineEffect(builder) { // Lens distortion is only applicable to views with the camera enabled. builder.shouldApply = (context) => context.viewport.isCameraOn; builder.addVarying("vUV", VaryingType.Vec3); builder.addVarying("vUVDot", VaryingType.Vec2); builder.addUniform({ name: "strength", type: UniformType.Float, bind: (uniform) => uniform.setUniform1f(LensDistortionConfig.strength), }); builder.addUniform({ name: "cylindricalRatio", type: UniformType.Float, bind: (uniform) => uniform.setUniform1f(LensDistortionConfig.cylindricalRatio), }); builder.addUniform({ name: "aspectRatio", type: UniformType.Float, bind: (uniform, context) => uniform.setUniform1f(context.viewport.viewRect.aspect), }); builder.addUniform({ name: "height", type: UniformType.Float, bind: (uniform, context) => { assert(context.viewport.view.is3d() && context.viewport.view.isCameraOn); const fov = context.viewport.view.camera.lens.radians; const height = Math.tan(fov / 2) / context.viewport.viewRect.aspect; uniform.setUniform1f(height); }, }); } } /** Configures the [[LensDistortionEffect]]. * @beta */ export class LensDistortionConfig extends Tool { static toolId = "LensDistortionConfig"; static get minArgs() { return 0; } static get maxArgs() { return 2; } static strength = 0.5; static cylindricalRatio = 0.5; async run(strength, ratio) { LensDistortionConfig.strength = strength ?? 0.5; LensDistortionConfig.cylindricalRatio = ratio ?? 0.5; refreshViewportsForEffect("fdt lensdistortion"); return true; } async parseAndRun(...input) { const args = parseArgs(input); return this.run(args.getFloat("s"), args.getFloat("r")); } } //# sourceMappingURL=LensDistortion.js.map