@lightningjs/renderer
Version:
Lightning 3 Renderer
376 lines (375 loc) • 13.2 kB
TypeScript
import type { ShaderMap } from '../core/CoreShaderManager.js';
import type { ExtractProps, TextureMap, TextureOptions } from '../core/CoreTextureManager.js';
import type { INode, INodeWritableProps, ITextNode, ITextNodeWritableProps } from './INode.js';
import type { ICoreDriver } from './ICoreDriver.js';
import { type ManualCountTextureUsageTrackerOptions } from './texture-usage-trackers/ManualCountTextureUsageTracker.js';
import type { TextureUsageTracker } from './texture-usage-trackers/TextureUsageTracker.js';
import { EventEmitter } from '../common/EventEmitter.js';
import type { IShaderController } from './IShaderController.js';
/**
* An immutable reference to a specific Texture type
*
* @remarks
* See {@link TextureRef} for more details.
*/
export interface SpecificTextureRef<TxType extends keyof TextureMap> {
readonly descType: 'texture';
readonly txType: TxType;
readonly props: ExtractProps<TextureMap[TxType]>;
readonly options?: Readonly<TextureOptions>;
}
type MapTextureRefs<TxType extends keyof TextureMap> = TxType extends keyof TextureMap ? SpecificTextureRef<TxType> : never;
/**
* An immutable reference to a Texture
*
* @remarks
* This structure should only be created by the RendererMain's `createTexture`
* method. The structure is immutable and should not be modified once created.
*
* A `TextureRef` exists in the Main API Space and is used to point to an actual
* `Texture` instance in the Core API Space. The `TextureRef` is used to
* communicate with the Core API Space to create, load, and destroy the
* `Texture` instance.
*
* This type is technically a discriminated union of all possible texture types.
* If you'd like to represent a specific texture type, you can use the
* `SpecificTextureRef` generic type.
*/
export type TextureRef = MapTextureRefs<keyof TextureMap>;
/**
* An immutable reference to a specific Shader type
*
* @remarks
* See {@link ShaderRef} for more details.
*/
export interface SpecificShaderRef<ShType extends keyof ShaderMap> {
readonly descType: 'shader';
readonly shType: ShType;
readonly props: ExtractProps<ShaderMap[ShType]>;
}
type MapShaderRefs<ShType extends keyof ShaderMap> = ShType extends keyof ShaderMap ? SpecificShaderRef<ShType> : never;
/**
* An immutable reference to a Shader
*
* @remarks
* This structure should only be created by the RendererMain's `createShader`
* method. The structure is immutable and should not be modified once created.
*
* A `ShaderRef` exists in the Main API Space and is used to point to an actual
* `Shader` instance in the Core API Space. The `ShaderRef` is used to
* communicate with the Core API Space to create, load, and destroy the
* `Shader` instance.
*
* This type is technically a discriminated union of all possible shader types.
* If you'd like to represent a specific shader type, you can use the
* `SpecificShaderRef` generic type.
*/
export type ShaderRef = MapShaderRefs<keyof ShaderMap>;
/**
* Configuration settings for {@link RendererMain}
*/
export interface RendererMainSettings {
/**
* Authored logical pixel width of the application
*
* @defaultValue `1920`
*/
appWidth?: number;
/**
* Authored logical pixel height of the application
*
* @defaultValue `1080`
*/
appHeight?: number;
/**
* Texture Memory Byte Threshold
*
* @remarks
* When the amount of GPU VRAM used by textures exceeds this threshold,
* the Renderer will free up all the textures that are current not visible
* within the configured `boundsMargin`.
*
* When set to `0`, the threshold-based texture memory manager is disabled.
*/
txMemByteThreshold?: number;
/**
* Bounds margin to extend the boundary in which a CoreNode is added as Quad.
*/
boundsMargin?: number | [number, number, number, number];
/**
* Factor to convert app-authored logical coorindates to device logical coordinates
*
* @remarks
* This value allows auto-scaling to support larger/small resolutions than the
* app was authored for.
*
* If the app was authored for 1920x1080 and this value is 2, the app's canvas
* will be rendered at 3840x2160 logical pixels.
*
* Likewise, if the app was authored for 1920x1080 and this value is 0.66667,
* the app's canvas will be rendered at 1280x720 logical pixels.
*
* @defaultValue `1`
*/
deviceLogicalPixelRatio?: number;
/**
* Factor to convert device logical coordinates to device physical coordinates
*
* @remarks
* This value allows auto-scaling to support devices with different pixel densities.
*
* This controls the number of physical pixels that are used to render each logical
* pixel. For example, if the device has a pixel density of 2, each logical pixel
* will be rendered using 2x2 physical pixels.
*
* By default, it will be set to `window.devicePixelRatio` which is the pixel
* density of the device the app is running on reported by the browser.
*
* @defaultValue `window.devicePixelRatio`
*/
devicePhysicalPixelRatio?: number;
/**
* RGBA encoded number of the background to use
*
* @defaultValue `0x00000000`
*/
clearColor?: number;
/**
* Path to a custom core module to use
*
* @defaultValue `null`
*/
coreExtensionModule?: string | null;
/**
* Enable experimental FinalizationRegistry-based texture usage tracking
* for texture garbage collection
*
* @remarks
* By default, the Renderer uses a manual reference counting system to track
* texture usage. Textures are eventually released from the Core Texture
* Manager's Usage Cache when they are no longer referenced by any Nodes (or
* SubTextures that are referenced by nodes). This works well enough, but has
* the consequence of textures being removed from Usage Cache even if their
* references are still alive in memory. This can require a texture to be
* reloaded from the source when it is used again after being removed from
* cache.
*
* This is an experimental feature that uses a FinalizationRegistry to track
* texture usage. This causes textures to be removed from the Usage Cache only
* when their references are no longer alive in memory. Meaning a loaded texture
* will remain in the Usage Cache until it's reference is garbage collected.
*
* This feature is not enabled by default because browser support for the
* FinalizationRegistry is limited. It should NOT be enabled in production apps
* as this behavior is not guaranteed to be supported in the future. Developer
* feedback on this feature, however, is welcome.
*
* @defaultValue `false`
*/
experimental_FinalizationRegistryTextureUsageTracker?: boolean;
textureCleanupOptions?: ManualCountTextureUsageTrackerOptions;
/**
* Interval in milliseconds to receive FPS updates
*
* @remarks
* If set to `0`, FPS updates will be disabled.
*
* @defaultValue `0` (disabled)
*/
fpsUpdateInterval?: number;
/**
* Include context call (i.e. WebGL) information in FPS updates
*
* @remarks
* When enabled the number of calls to each context method over the
* `fpsUpdateInterval` will be included in the FPS update payload's
* `contextSpyData` property.
*
* Enabling the context spy has a serious impact on performance so only use it
* when you need to extract context call information.
*
* @defaultValue `false` (disabled)
*/
enableContextSpy?: boolean;
/**
* Number or Image Workers to use
*
* @remarks
* On devices with multiple cores, this can be used to improve image loading
* as well as reduce the impact of image loading on the main thread.
* Set to 0 to disable image workers.
*
* @defaultValue `2`
*/
numImageWorkers?: number;
/**
* Enable inspector
*
* @remarks
* When enabled the renderer will spawn a inspector. The inspector will
* replicate the state of the Nodes created in the renderer and allow
* inspection of the state of the nodes.
*
* @defaultValue `false` (disabled)
*/
enableInspector?: boolean;
}
/**
* The Renderer Main API
*
* @remarks
* This is the primary class used to configure and operate the Renderer.
*
* It is used to create and destroy Nodes, as well as Texture and Shader
* references.
*
* Example:
* ```ts
* import { RendererMain, MainCoreDriver } from '@lightningjs/renderer';
*
* // Initialize the Renderer
* const renderer = new RendererMain(
* {
* appWidth: 1920,
* appHeight: 1080
* },
* 'app',
* new MainCoreDriver(),
* );
* ```
*/
export declare class RendererMain extends EventEmitter {
readonly root: INode | null;
readonly driver: ICoreDriver;
readonly canvas: HTMLCanvasElement;
readonly settings: Readonly<Required<RendererMainSettings>>;
private inspector;
private nodes;
private nextTextureId;
/**
* Texture Usage Tracker for Usage Based Texture Garbage Collection
*
* @remarks
* For internal use only. DO NOT ACCESS.
*/
textureTracker: TextureUsageTracker;
/**
* Constructs a new Renderer instance
*
* @param settings Renderer settings
* @param target Element ID or HTMLElement to insert the canvas into
* @param driver Core Driver to use
*/
constructor(settings: RendererMainSettings, target: string | HTMLElement, driver: ICoreDriver);
/**
* Initialize the renderer
*
* @remarks
* This method must be called and resolved asyncronously before any other
* methods are called.
*/
init(): Promise<void>;
/**
* Create a new scene graph node
*
* @remarks
* A node is the main graphical building block of the Renderer scene graph. It
* can be a container for other nodes, or it can be a leaf node that renders a
* solid color, gradient, image, or specific texture, using a specific shader.
*
* To create a text node, see {@link createTextNode}.
*
* See {@link INode} for more details.
*
* @param props
* @returns
*/
createNode(props: Partial<INodeWritableProps>): INode;
/**
* Create a new scene graph text node
*
* @remarks
* A text node is the second graphical building block of the Renderer scene
* graph. It renders text using a specific text renderer that is automatically
* chosen based on the font requested and what type of fonts are installed
* into an app via a CoreExtension.
*
* See {@link ITextNode} for more details.
*
* @param props
* @returns
*/
createTextNode(props: Partial<ITextNodeWritableProps>): ITextNode;
/**
* Resolves the default property values for a Node
*
* @remarks
* This method is used internally by the RendererMain to resolve the default
* property values for a Node. It is exposed publicly so that it can be used
* by Core Driver implementations.
*
* @param props
* @returns
*/
resolveNodeDefaults(props: Partial<INodeWritableProps>): INodeWritableProps;
/**
* Destroy a node
*
* @remarks
* This method destroys a node but does not destroy its children.
*
* @param node
* @returns
*/
destroyNode(node: INode): void;
/**
* Create a new texture reference
*
* @remarks
* This method creates a new reference to a texture. The texture is not
* loaded until it is used on a node.
*
* It can be assigned to a node's `texture` property, or it can be used
* when creating a SubTexture.
*
* @param textureType
* @param props
* @param options
* @returns
*/
createTexture<TxType extends keyof TextureMap>(textureType: TxType, props: SpecificTextureRef<TxType>['props'], options?: TextureOptions): SpecificTextureRef<TxType>;
/**
* Create a new shader reference
*
* @remarks
* This method creates a new reference to a shader. The shader is not
* loaded until it is used on a Node.
*
* It can be assigned to a Node's `shader` property.
*
* @param shaderType
* @param props
* @returns
*/
createShader<ShType extends keyof ShaderMap>(shaderType: ShType, props?: SpecificShaderRef<ShType>['props']): IShaderController;
/**
* Get a Node by its ID
*
* @param id
* @returns
*/
getNodeById(id: number): INode | null;
toggleFreeze(): void;
advanceFrame(): void;
/**
* Re-render the current frame without advancing any running animations.
*
* @remarks
* Any state changes will be reflected in the re-rendered frame. Useful for
* debugging.
*
* May not do anything if the render loop is running on a separate worker.
*/
rerender(): void;
}
export {};