import Notifier from './core/Notifier'; import Material from './Material'; import Vector2 from './math/Vector2'; import type Renderable from './Renderable'; import type FrameBuffer from './FrameBuffer'; import type Scene from './Scene'; import { Color, GLEnum } from './core/type'; import type Camera from './Camera'; import type ClayNode from './Node'; import GLPipeline, { ExtendedRenderableObject, GLRenderableObject, GLRenderHooks } from './gl/GLPipeline'; import Texture from './Texture'; import InstancedMesh from './InstancedMesh'; import GeometryBase from './GeometryBase'; interface ExtendedWebGL2RenderingContext extends WebGL2RenderingContext { targetRenderer: Renderer; } export type RenderableObject = GLRenderableObject; export type RenderHooks = GLRenderHooks & { /** * Do preparation like color clear before render and after framebuffer bound. */ prepare?(gl: WebGL2RenderingContext): void; /** * Do cleanup like restore gl state after pass rendered, before framebuffer unbound. */ cleanup?(gl: WebGL2RenderingContext): void; }; export interface RendererViewport { x: number; y: number; width: number; height: number; pixelRatio: number; } export interface RendererOpts { canvas: HTMLCanvasElement | OffscreenCanvas | null; /** * Canvas width */ width: number; /** * Canvas width */ height: number; /** * Device pixel ratio, set by setPixelRatio method * Specially for high defination display * @see http://www.khronos.org/webgl/wiki/HandlingHighDPI * @type {number} * @private */ pixelRatio: number; /** * Clear color */ clearColor: Color; /** * Default: * _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT | _gl.STENCIL_BUFFER_BIT */ clearBit: GLEnum; /** * If enable log depth buffer */ logDepthBuffer: boolean; /** * If enable alpha, default true */ alpha: boolean; /** * If enable depth buffer, default true */ depth: boolean; /** * If enable stencil buffer, default false */ stencil: boolean; /** * If enable antialias, default true */ antialias: boolean; /** * If enable premultiplied alpha, default true */ premultipliedAlpha: boolean; /** * If preserve drawing buffer, default false */ preserveDrawingBuffer: boolean; /** * Power preference */ powerPreference: 'high-performance' | 'low-power' | 'default'; /** * If throw context error, usually turned on in debug mode */ throwError: boolean; /** * If use parallel shader compile. * We still need to set shader.parallelCompile to true * to enable the specified shader manually */ parallelShaderCompile: boolean; } interface Renderer extends Pick { } /** * @constructor clay.Renderer * @extends clay.core.Base */ declare class Renderer extends Notifier { uid: number; canvas: HTMLCanvasElement | OffscreenCanvas; /** * Canvas width, set by resize method */ private _width; /** * Canvas width, set by resize method */ private _height; /** * Device pixel ratio, set by setPixelRatio method * Specially for high defination display * @see http://www.khronos.org/webgl/wiki/HandlingHighDPI * @type {number} * @private */ private _pixelRatio; /** * WebGL Context created from given canvas */ readonly gl: ExtendedWebGL2RenderingContext; /** * Renderer viewport, read-only, can be set by setViewport method * @type {Object} */ viewport: RendererViewport; private _viewportStack; private _clearStack; private _prezMaterial?; private _glPipeline; constructor(opts?: Partial); getGLPipeline(): GLPipeline; /** * Resize the canvas * @param {number} width * @param {number} height */ resize(width?: number, height?: number, pixelRatio?: number): void; /** * Get renderer width * @return {number} */ getWidth(): number; /** * Get renderer height * @return {number} */ getHeight(): number; /** * Get viewport aspect, * @return {number} */ getViewportAspect(): number; /** * Set pixelRatio * @param {number} pixelRatio */ setPixelRatio(pixelRatio: number): void; /** * Get pixelRatio * @param {number} pixelRatio */ getPixelRatio(): number; /** * Set rendering viewport * @param {number|Object} x * @param {number} [y] * @param {number} [width] * @param {number} [height] * @param {number} [pixelRatio] * Defaultly use the renderere pixelRatio * It needs to be 1 when setViewport is called by frameBuffer * * @example * setViewport(0,0,width,height,1) * setViewport({ * x: 0, * y: 0, * width: width, * height: height, * pixelRatio: 1 * }) */ setViewport(x: RendererViewport): void; setViewport(x: number, y: number, width: number, height: number, dpr?: number): void; /** * Push current viewport into a stack */ saveViewport(): void; /** * Pop viewport from stack, restore in the renderer */ restoreViewport(): void; /** * Push current clear into a stack */ saveClear(): void; /** * Pop clear from stack, restore in the renderer */ restoreClear(): void; getWebGLExtension(name: string): any; isAllProgramCompiled(): boolean; /** * Render the scene in camera to the screen or binded offline framebuffer */ render(scene: Scene, camera: Camera, frameBuffer?: FrameBuffer, opts?: { /** * If not call the scene.update methods in the rendering */ notUpdateScene?: boolean; /** * Global material that override the scene material and renderable material. */ globalMaterial?: Material; /** * If use preZ optimization */ preZ?: boolean; /** * Filter the renderable */ filter?: (renderable: Renderable) => boolean; /** * If waiting for all shaders compiled. Available when parallelShaderCompile is true. * Default to be false, it will render the meshes that has finishing compiling shader eargerly. */ waitForAllShadersCompiled?: boolean; }): boolean | undefined; /** * Render a single pass. * * CAUTION: * You must execute gl.clear or other gl commands in the prepare methods. * If you are using framebuffer. executing theme before the renderPass will not affect on the framebuffer. */ renderPass(list: GLRenderableObject[], camera?: Camera, frameBuffer?: FrameBuffer, renderHooks?: RenderHooks, scene?: Scene, opts?: { waitForAllShadersCompiled?: boolean; }): boolean; /** * Bind frame buffer manually. * Use #bindFrameBuffer(null) to unbind */ bindFrameBuffer(frameBuffer?: FrameBuffer | null): void; private _bindFrameBuffer; private _renderPass; getMaxJointNumber(): number; setMaxJointNumber(val: number): void; renderPreZ(list: GLRenderableObject[], camera: Camera, frameBuffer?: FrameBuffer, opts?: { waitForAllShadersCompiled?: boolean; }): void; /** * Dispose given scene, including all geometris, textures and shaders in the scene * @param {clay.Scene} scene */ disposeScene(scene: Scene): void; /** * Dispose given node, including all geometries, textures and shaders attached on it or its descendant * @param {clay.Node} node * @param {boolean} [disposeGeometry=false] If dispose the geometries used in the descendant mesh * @param {boolean} [disposeTexture=false] If dispose the textures used in the descendant mesh */ disposeNode(root: ClayNode, disposeGeometry?: boolean, disposeTexture?: boolean): void; disposeTexture(texture: Texture): void; disposeGeometry(geometry: GeometryBase): void; disposeFrameBuffer(frameBuffer: FrameBuffer): void; disposeInstancedMesh(mesh: InstancedMesh): void; /** * Dispose renderer */ dispose(): void; /** * Convert screen coords to normalized device coordinates(NDC) * Screen coords can get from mouse event, it is positioned relative to canvas element * NDC can be used in ray casting with Camera.prototype.castRay methods * * @param {number} x * @param {number} y * @param {clay.Vector2} [out] * @return {clay.Vector2} */ screenToNDC(x: number, y: number, out?: Vector2): Vector2; /** * Opaque renderables compare function * @param {clay.Renderable} x * @param {clay.Renderable} y * @return {boolean} * @static */ static opaqueSortCompare(x: ExtendedRenderableObject, y: ExtendedRenderableObject): number; /** * Transparent renderables compare function * @param {clay.Renderable} a * @param {clay.Renderable} b * @return {boolean} * @static */ static transparentSortCompare(x: ExtendedRenderableObject, y: ExtendedRenderableObject): number; static COLOR_BUFFER_BIT: number; static DEPTH_BUFFER_BIT: number; static STENCIL_BUFFER_BIT: number; } export default Renderer;