import { WebGPURenderer } from 'three/webgpu'; import { DIVEScene } from '../scene/Scene.ts'; import { DIVECameraComponent } from '../../components/camera/CameraComponent.ts'; import { DIVEEnvironment } from '../environment/Environment.ts'; export type DIVERendererSettings = { /** * The canvas to render to. When undefined, the canvas will be created automatically and reachable via the `diveInstance.canvas` property. * * @default undefined */ canvas: HTMLCanvasElement | undefined; /** * Whether to enable antialiasing * * @default true */ antialias: boolean; /** Whether to enable alpha channel */ alpha: boolean; /** * Power preference for the WebGL context * * @default 'high-performance' */ powerPreference: 'high-performance' | 'low-power'; /** * Precision of the shader * * @default 'highp' */ precision: 'highp' | 'mediump' | 'lowp'; /** * Whether to enable stencil buffer * * @default false */ stencil: boolean; /** * Whether to enable depth buffer * * @default true */ depth: boolean; /** * Whether to use logarithmic depth buffer * * Off, and {@link reversedDepthBuffer} on in its place: both answer the same * question, and only one of them answers it in the projection. A logarithmic * buffer has every fragment shader write its own depth, which costs early-z * and makes every rasterizer-level depth bias a no-op -- `polygonOffset` * included, which is how coplanar surfaces are normally settled. * * @default false */ logarithmicDepthBuffer: boolean; /** * Whether to use a reversed depth buffer * * Floating point depth is near-uniform in its exponent, and a reversed range * lines that up with where a perspective divide puts its precision. That is * what makes a near plane of a millimeter and a far plane of a kilometer * survivable without writing depth per fragment. * * The WebGL backend needs `EXT_clip_control` for it; three warns and falls * back to a plain depth buffer where the extension is missing. * * @default true */ reversedDepthBuffer: boolean; /** * Whether to enable shadows * * @default true */ shadows: boolean; /** * The quality of the shadows * * @default 'high' */ shadowQuality: 'high' | 'medium' | 'low'; }; export declare const DIVERendererDefaultSettings: Required; /** * A changed version of the WebGLRenderer. * * Has to be started manually by calling StartRenderer(). * * @module */ export declare class DIVERenderer { private _scene; readonly isDIVERenderer: true; private _webgpurenderer; private _environment; private _baker; /** the light's texture at the last bake, `null` for none */ private _bakedLightTexture; private _initPromise; private _settings; /** * Whose eyes the next frame is drawn through. * * The component, not the bare camera: a camera is reached through the * component that owns it everywhere else, and taking the camera here would * make the renderer the one place holding a handle that cannot be asked for * its layers or resized. `tick` reads `.camera` off it per frame, so a * component that swaps its camera is followed rather than remembered wrongly. * * Settable rather than fixed at construction: cameras are nodes now, so a * caller may want to render through a camera entity or a preview and back * again. Welding one in meant rebuilding the renderer -- and with it the WebGPU * context -- to look somewhere else. */ activeCamera: DIVECameraComponent; constructor(_scene: DIVEScene, camera: DIVECameraComponent, settings?: Partial); get webgpurenderer(): WebGPURenderer; /** * @deprecated Use `scene.setImageBasedLight` and `scene.setBackground`. */ get environment(): DIVEEnvironment; get canvas(): HTMLCanvasElement; get initialized(): boolean; initAsync(): Promise; tick(): void; /** * Puts the scene's image based light on the scene for this frame. * * Bakes only when the image changed since the last bake, so several * changes within one frame cost one bake. Rotation and intensity are * evaluated per frame by three and never cost one. */ private _applyImageBasedLight; onResize(width: number, height: number): void; dispose(): void; setCanvas(canvas: HTMLCanvasElement): void; /** takes the bake off the scene, so the next tick bakes afresh */ private _releaseBake; /** * Stops a `dispose` from ending the canvas's WebGL context. * * `WebGLBackend.dispose()` finishes with `WEBGL_lose_context.loseContext()`, * which kills the context of the *canvas*, not of the renderer. A canvas is * only ever given one context per type, so once it is lost * `getContext('webgl2')` keeps handing back the dead one -- and the next * renderer on it reads `getParameter(VIEWPORT)`, gets `null`, and throws. That * made a canvas unusable after the first teardown, which is not something DIVE * may do to an element a caller passed in and still has in their document. * * Skipping it is only safe because {@link DIVEScene.dispose} releases the GPU * resources itself, through the `dispose` listeners three puts on every * geometry, material and texture -- and `DIVE.disposeAsync` runs it before the * views, while this renderer is still there to hear it. * * `WebGLExtensions.get` returns whatever its cache holds unless that is * `undefined`, so seeding the entry with `null` makes the lookup in `dispose` * come up empty. Everything else `dispose` does still runs. * * Warns rather than throws if three's internals have moved: the canvas is then * lost again, which is bad, but not worth failing a teardown over. * * @param renderer - The renderer about to be disposed. */ private _keepCanvasUsable; private _createWebGPURenderer; }