UNPKG

gsots3d

Version:

Getting S**t On The Screen in 3D. A library for doing 3D graphics in the browser.

1,308 lines (1,292 loc) 55.9 kB
import { mat4, vec3, quat } from 'gl-matrix'; import log from 'loglevel'; import * as CANNON from 'cannon-es'; import * as twgl from 'twgl.js'; import { ProgramInfo, TextureOptions as TextureOptions$1 } from 'twgl.js'; import { M as MtlMaterial } from './mtl-parser-Cw8gA4Aw.js'; /** A map of uniforms that can be used when WebGL rendering, typically applied with twlg.setUniforms() */ type UniformSet = { [key: string]: number | number[] | mat4 | WebGLTexture | null; }; /** This type https://twgljs.org/docs/module-twgl.html#.TextureOptions without exposing twgl types directly */ type TextureOptions = { [key: string]: number | string | boolean | number[]; }; /** * Get the WebGL2 context, if it doesn't exist it will be created for the provided canvas element, and memoized * @returns {WebGL2RenderingContext} - Global WebGL2 context * @param {boolean} aa - Enable antialiasing * @param {string} selector - CSS selector for locating the canvas element */ declare function getGl(selector?: string, aa?: boolean): WebGL2RenderingContext | undefined; /** A simple 3D position or vector tuple */ type XYZ = [number, number, number]; /** A simple 4D position or vector tuple */ type XYZW = [number, number, number, number]; /** A simple RGB colour tuple */ type RGB = [number, number, number]; /** A simple RGBA colour tuple */ type RGBA = [number, number, number, number]; /** * Normalizes a 3-tuple to a unit vector. * @param tuple The tuple to normalize */ declare function normalize(tuple: XYZ | RGB | number[]): XYZ; /** * Scales a 3-tuple by a scalar. * @param tuple The tuple to scale * @param scale The scalar to scale by */ declare function scale(tuple: XYZ | RGB | RGBA | number[], amount: number): XYZ; /** * Scales a 3-tuple by a scalar, clamping the result to 0-1. * @param tuple The tuple to scale * @param scale The scalar to scale by */ declare function scaleClamped(colour: RGB | RGBA, amount: number): RGB | RGBA; /** * Converts a 3-tuple to a gl-matrix vec3 * @param tuple The tuple to convert */ declare function toVec3(tuple: XYZ): vec3; /** * Calculates the distance between two 3-tuples * @param a First tuple * @param b Second tuple */ declare function distance(a: XYZ, b: XYZ): number; declare function add(a: XYZ, b: XYZ): XYZ; /** * Converts a Cannon.js vector or quaternion to a tuple * @param value The Cannon.js vector or quaternion to convert */ declare function fromCannon(value: CANNON.Vec3 | CANNON.Quaternion): XYZ | XYZW; /** * Creates a RGB 3-tuple from 0-255 values. * @param r Red value (0-255) * @param g Green value (0-255) * @param b Blue value (0-255) */ declare function rgbColour255(r: number, g: number, b: number): RGB; /** * Converts a hex string to an RGB 3-tuple. * @param hexString */ declare function rgbColourHex(hexString: string): RGB; /** * A set of common colours as RGB tuples */ declare const Colours: { RED: RGB; GREEN: RGB; BLUE: RGB; YELLOW: RGB; CYAN: RGB; MAGENTA: RGB; BLACK: RGB; WHITE: RGB; }; declare const Tuples: { normalize: typeof normalize; scale: typeof scale; scaleClamped: typeof scaleClamped; rgbColour255: typeof rgbColour255; rgbColourHex: typeof rgbColourHex; toVec3: typeof toVec3; distance: typeof distance; fromCannon: typeof fromCannon; add: typeof add; }; declare enum CameraType { PERSPECTIVE = 0, ORTHOGRAPHIC = 1 } declare class Camera { /** Camera position */ position: XYZ; /** Camera look at point, default: [0, 0, 0] */ lookAt: XYZ; /** Field of view in degrees, default: 45 */ fov: number; /** Near clipping plane, default: 0.1 */ near: number; /** Far clipping plane, default: 100 */ far: number; /** Camera up vector, default: [0, 1, 0] */ up: XYZ; /** Change camera projection, default: CameraType.PERSPECTIVE */ type: CameraType; /** Is this camera active, default: true */ active: boolean; /** Orthographic zoom level, only used when type is orthographic, default: 20 */ orthoZoom: number; /** Is this camera used for a dynamic environment map, default: false */ usedForEnvMap: boolean; /** Is this camera used for a shadow map, default: false */ usedForShadowMap: boolean; /** Aspect ratio of the camera, default: 1 */ aspectRatio: number; private fpAngleY; private fpAngleX; private fpMode; private fpHandlersAdded; private fpTurnSpeed; fpMoveSpeed: number; private fpFly; private maxAngleUp; private maxAngleDown; private keysDown; private touches; /** * Create a new default camera */ constructor(type?: CameraType, aspectRatio?: number); /** * Get the current view matrix for the camera */ get matrix(): mat4; /** * Get the projection matrix for this camera * @param aspectRatio Aspect ratio of the canvas */ get projectionMatrix(): mat4; /** * Get the center of the camera view frustum * @param scale how much to scale the frustum towards the far plane, default: 1 * @returns Point in world space */ getFrustumCenter(scaleFar?: number): XYZ; /** * Get the corners of the view frustum for this camera in world space * @param scaleFar Scale the far plane to bring the frustum closer, default: 1 */ frustumCornersWorld(scaleFar?: number): { nearTopLeftWorld: vec3; nearTopRightWorld: vec3; nearBottomLeftWorld: vec3; nearBottomRightWorld: vec3; farTopLeftWorld: vec3; farTopRightWorld: vec3; farBottomLeftWorld: vec3; farBottomRightWorld: vec3; center: vec3; }; /** * Get the camera position as a string for debugging */ toString(): string; /** * Switches the camera to first person mode, where the camera is controlled by * the mouse and keyboard. The mouse controls look direction and the keyboard * controls movement. * @param angleY Starting look up/down angle in radians, default 0 * @param angleX Starting look left/right angle in radians, default 0 * @param turnSpeed Speed of looking in radians, default 0.001 * @param moveSpeed Speed of moving in units, default 1.0 */ enableFPControls(angleY?: number, angleX?: number, turnSpeed?: number, moveSpeed?: number, fly?: boolean): void; /** * Disable FP mode */ disableFPControls(): void; /** * Get FP mode state */ get fpModeEnabled(): boolean; /** * Called every frame to update the camera, currently only used for movement in FP mode */ update(): void; } /** * Options to configure how shadows are calculated & rendered */ type ShadowOptions = { /** Size of the shadow map texture. Default: 512 */ mapSize: number; /** Zoom level of the shadow map camera, larger will cover more of the scene, but results in more blocky shadows. Default 120 */ zoom: number; /** Far clipping pane of shadow map camera, default 1000 */ distance: number; /** Blur the edges of shadows, higher values them more random, default 0.2 */ /** Offset used to reduce shadow acne especially when self shadowing */ polygonOffset: number; }; /** * A directional light source, typically global with the context having only a single instance * Having multiple directional lights is not supported */ declare class LightDirectional { private _direction; private _shadowMapProgram?; private _shadowMapFB?; private _shadowMapTex?; private _shadowOptions?; /** Colour of the light, used for both diffuse and specular. Default: [0, 0, 0] */ colour: RGB; /** Ambient colour of the light. Default: [0, 0, 0] */ ambient: RGB; /** Is this light enabled. Default: true */ enabled: boolean; /** Create a default directional light, pointing downward */ constructor(); /** * Set the direction of the light ensuring it is normalized * @param direction - Direction vector */ set direction(direction: XYZ); /** * Get the direction of the light */ get direction(): XYZ; /** * Convenience method allows setting the direction as a point relative to the world origin * Values are always converted to a normalized unit direction vector * @param x - X position * @param y - Y position * @param z - Z position */ setAsPosition(x: number, y: number, z: number): void; /** * Return the base set of uniforms for this light */ get uniforms(): UniformSet; /** * Enable shadows for this light, this will create a shadow map texture and framebuffer * There is no way to disabled shadows once enabled * @param options A set of ShadowOptions to configure how shadows are calculated */ enableShadows(options?: ShadowOptions): void; /** * Get a virtual camera that can be used to render a shadow map for this light * @param viewCam - The main camera used to view the scene, needed to get a good shadow view */ getShadowCamera(viewCam: Camera): Camera | undefined; /** * Get the forward view matrix for the virtual camera used to render the shadow map. * Returns undefined if shadows are not enabled * @param viewCam - The main camera used to view the scene, needed to get a good shadow view */ getShadowMatrix(viewCam: Camera): mat4 | undefined; /** * Are shadows enabled for this light? */ get shadowsEnabled(): boolean; /** * Get the shadow map program, will be undefined if shadows are not enabled */ get shadowMapProgram(): twgl.ProgramInfo | undefined; /** * Get the shadow map framebuffer, will be undefined if shadows are not enabled */ get shadowMapFrameBufffer(): twgl.FramebufferInfo | undefined; /** * Get the shadow map texture, will be undefined if shadows are not enabled */ get shadowMapTexture(): WebGLTexture | undefined; /** * Get the shadow map options, will be undefined if shadows are not enabled */ get shadowMapOptions(): ShadowOptions | undefined; } declare class LightPoint { /** Position of the light in world space. */ position: XYZ; /** Colour of the light. Default: [1, 1, 1] */ colour: RGB; /** Ambient colour of the light. Normally none for point lights. Default [0, 0, 0] */ ambient: RGB; /** Light attenuation parameter for constant drop off rate. Default: 0.5 */ constant: number; /** Light attenuation parameter for linear drop off rate. Default: 0.018 */ linear: number; /** Light attenuation parameter for quadratic drop off rate. Default: 0.0003 */ quad: number; /** Is this light enabled? Default: true */ enabled: boolean; /** Metadata is a key/value store for any extra data you want to store on a node */ metadata: Record<string, string | number | boolean>; /** * Create a default point light, positioned at the world origin * @param position - Position of the light in world space * @param colour - Colour of the light * @param constant - Attenuation constant drop off rate, default 0.5 * @param linear - Attenuation linear drop off rate, default 0.018 * @param quad - Attenuation quadratic drop off rate, default 0.0003 */ constructor(position: XYZ, colour: RGB, constant?: number, linear?: number, quad?: number); /** * Return the base set of uniforms for this light */ get uniforms(): UniformSet; } declare class Material { /** * Ambient colour will be multiplied with the ambient light level & colour */ ambient: RGB; /** * Diffuse colour will be multiplied with the diffuse texture * @default [1, 1, 1] */ diffuse: RGB; /** * Specular colour will be multiplied with the specular texture * @default [0, 0, 0] */ specular: RGB; /** * Emissive colour will be added to the final colour, use for glowing materials */ emissive: RGB; /** * Shininess, for size of specular highlights * @default 20 */ shininess: number; /** * Opacity, 0.0 to 1.0 * @default 1.0 */ opacity: number; /** * Reflectivity, 0.0 to 1.0 * @default 0.0 */ reflectivity: number; /** * Diffuse texture map * @default "1 pixel white texture" */ diffuseTex?: WebGLTexture; /** * Specular texture map * @default "1 pixel white texture" */ specularTex?: WebGLTexture; /** * Normal texture map * @default "1 pixel white texture" */ normalTex?: WebGLTexture; /** * Transparency threshold, pixels with alpha below this value will be discarded * @default 0.0 */ alphaCutoff: number; additiveBlend: boolean; /** * Create a new default material with diffuse white colour, all all default properties */ constructor(); /** * Create a new material from a raw MTL material. Users are not expected to call this directly as it is used internally by the OBJ parser * @param rawMtl Raw MTL material * @param basePath Base path for locating & loading textures in MTL file * @param filter Apply texture filtering to textures, default: true * @param flipY Flip the Y axis of textures, default: false */ static fromMtl(rawMtl: MtlMaterial, basePath: string, filter?: boolean, flipY?: boolean): Material; /** * Create a basic Material with a solid/flat diffuse colour * @param r Red component, 0.0 to 1.0 * @param g Green component, 0.0 to 1.0 * @param b Blue component, 0.0 to 1.0 */ static createSolidColour(r: number, g: number, b: number): Material; /** * Create a new Material with a texture map loaded from a URL/filepath or Buffer * @param src URL or filename path of texture image, or ArrayBufferView holding texture * @param filter Enable texture filtering and mipmaps (default true) * @param flipY Flip the texture vertically (default false) * @param extraOptions Extra options to pass to twgl.createTexture, see https://twgljs.org/docs/module-twgl.html#.TextureOptions */ static createBasicTexture(src: string | ArrayBufferView, filter?: boolean, flipY?: boolean, extraOptions?: TextureOptions): Material; /** * Add a specular texture map to existing material, probably created with createBasicTexture * @param url * @param filter */ addSpecularTexture(url: string, filter?: boolean, flipY?: boolean): void; /** * Add a normal texture map to existing material, probably created with createBasicTexture * @param url * @param filter */ addNormalTexture(url: string, filter?: boolean, flipY?: boolean): void; /** Create a simple diffuse red Material */ static get RED(): Material; /** Create a simple diffuse green Material */ static get GREEN(): Material; /** Create a simple diffuse blue Material */ static get BLUE(): Material; /** Create a simple diffuse white Material */ static get WHITE(): Material; /** Create a simple diffuse black Material */ static get BLACK(): Material; /** Create a simple diffuse yellow Material */ static get YELLOW(): Material; /** Create a simple diffuse magenta Material */ static get MAGENTA(): Material; /** Create a simple diffuse cyan Material */ static get CYAN(): Material; /** * Adds this material to a program, as a set of uniforms * @param programInfo ProgramInfo object to update with uniforms * @param uniformSuffix Optional suffix to add to uniform names */ apply(programInfo: twgl.ProgramInfo, uniformSuffix?: string): void; /** * Return the base set of uniforms for this material * @returns UniformSet object with all material properties */ get uniforms(): UniformSet; /** * Clone this material, returns a new material with the same properties */ clone(): Material; } declare class EnvironmentMap { private programInfo; private gl; private _texture; private cube; /** * Render the environment map as a background, like a skybox */ renderAsBackground: boolean; /** * Create a new environment map with 6 textures for each side * @param gl GL context * @param textureURLs Array of 6 texture URLs, in order: +x, -x, +y, -y, +z, -z */ constructor(gl: WebGL2RenderingContext, textureURLs: string[]); /** * Render this envmap as a cube around the given camera & matrices * This is used for rendering the envmap as a background and skybox around the scene * @param viewMatrix View matrix * @param projMatrix Projection matrix * @param camera Camera */ render(viewMatrix: mat4, projMatrix: mat4, camera: Camera): void; get texture(): WebGLTexture; } /** * Used for rendering a dynamic environment map, to create realtime reflections * For performance reasons, there is only one dynamic envmap per scene context */ declare class DynamicEnvironmentMap { private _texture; private facings; private camera; /** * Create a new dynamic environment map * @param gl GL context * @param size Size of each face of the cube map * @param position Position of the center of the cube map, reflections will be rendered from here */ constructor(gl: WebGL2RenderingContext, size: number, position: XYZ, far: number); /** Get the texture of the environment cubemap */ get texture(): WebGLTexture; /** * This is used to position the camera for creating the reflection map * @param position Position of the center of the cube map */ set position(pos: XYZ); /** * Update the environment map, by rendering the scene from the given position into the cubemap texture * @param ctx GSOTS Context */ update(gl: WebGL2RenderingContext, ctx: Context): void; } /** * Models and primitives implement this interface to be rendered */ interface Renderable { /** Called to render this render-able thing */ render(gl: WebGL2RenderingContext, uniforms: UniformSet, materialOverride?: Material, programOverride?: ProgramInfo): void; } /** Event triggered when a node position, rotation or scale changes */ type NodeEvent = { position: XYZ; rotation: XYZW; scale: XYZ; nodeId: string; }; /** * A Node with position, rotation, scale, all Instances extend this class. * But Nodes also be created to group instances and simplify transformations. */ declare class Node { /** Unique ID for this node */ readonly id: string; /** Position of this Node in world space, relative to any parent nodes (if any) */ position: XYZ; /** Scale of this Node in world space, relative to any parent nodes (if any) */ scale: XYZ; /** Rotation quaternion of this Node in world space, relative to any parent nodes (if any) */ quaternion: quat; /** Metadata is a key/value store for any extra data you want to store on a node */ metadata: Record<string, string | number | boolean>; private _receiveShadow; private _castShadow; private _enabled; private _parent?; private _children; private _physicsBody?; private eventHandlers; /** Create a default node, at origin with scale of [1,1,1] and no rotation */ constructor(); /** Rotate this instance around the X, Y and Z axis in radians */ rotate(ax: number, ay: number, az: number): void; /** Rotate this instance around the X axis*/ rotateX(angle: number): void; /** Rotate this instance around the Y axis*/ rotateY(angle: number): void; /** Rotate this instance around the Z axis, in radians*/ rotateZ(angle: number): void; /** Rotate this instance around the X axis by a given angle in degrees */ rotateZDeg(angle: number): void; /** Rotate this instance around the Y axis by a given angle in degrees */ rotateYDeg(angle: number): void; /** Rotate this instance around the Z axis by a given angle in degrees */ rotateXDeg(angle: number): void; /** Set the rotation quaternion directly, normally users should use the rotate methods. * This method is for advanced uses, like integration with an external physics system */ setQuaternion(quatArray: XYZW): void; /** Get the rotation quaternion as a XYZW 4-tuple */ getQuaternion(): XYZW; /** * Return the world or model matrix for this node, this is the matrix that places this node in the world. * This will be in relation to the parent node, if there is one. */ get modelMatrix(): mat4; /** Convenience method to make another Node a child of this one */ addChild(node: Node): void; /** Convenience method to remove a child Node */ removeChild(node: Node): void; /** Convenience method to remove all child Nodes */ removeAllChildren(): void; /** Sets the parent this Node, to the provided Node */ set parent(node: Node | undefined); /** Fetch all child Nodes of this Node */ get children(): Node[]; /** Get current parent of this Node */ get parent(): Node | undefined; /** Is this Node enabled. Disabled nodes will not be rendered */ get enabled(): boolean; /** Set enabled state of this Node, this will also set all child nodes */ set enabled(enabled: boolean); /** Does this Node cast shadows, default true */ get castShadow(): boolean; /** Set will this Node cast shadows, this will also set all child nodes */ set castShadow(value: boolean); /** Does this Node receive shadows, default true */ get receiveShadow(): boolean; /** Set will this Node receive shadows, this will also set all child nodes */ set receiveShadow(value: boolean); /** Get the physics body for this Node, if there is one */ get physicsBody(): CANNON.Body | undefined; /** Set the physics body for this Node */ set physicsBody(body: CANNON.Body | undefined); /** * Updates the position & rotation of this node to match it's linked physics Body * This is called automatically by the engine, but can be called manually if needed */ updateFromPhysicsBody(): void; /** * Add an event handler to listen for node changes * @param event NodeEvent type, one of 'position', 'rotation', 'scale' * @param handler Function to call when event is triggered */ addEventHandler(event: string, handler: (event: NodeEvent) => void): void; } /** * An instance of thing in the world to be rendered, with position, rotation, scale etc */ declare class Instance extends Node { /** Main renderable thing this instance represents */ readonly renderable: Renderable | undefined; /** Flip all textures on this instance on the X axis */ flipTextureX: boolean; /** Flip all textures on this instance on the Y axis */ flipTextureY: boolean; /** Material override. This will override the renderable's material. * This is only useful on simple models that probably consist of one surface */ material?: Material; /** Inject additional uniforms to the shader for this instance. * Prefix with `u_mat.` e.g. `u_mat.diffuse` to change material properties for a single instance. * Warning an advanced feature! */ uniformOverrides?: UniformSet; /** Very advanced feature, set this to plugin a custom shader program * Use ProgramCache.compileShader to create a named program */ customProgramName?: string; /** * Create a new instance of a renderable thing * @param {Renderable} renderable - Renderable to use for this instance */ constructor(renderable: Renderable); setPosition(x: number | XYZ, y?: number, z?: number): void; /** * Render this instance in the world, called internally by the context when rendering * @param {WebGL2RenderingContext} gl - WebGL context to render into * @param {UniformSet} uniforms - Map of uniforms to pass to shader */ render(gl: WebGL2RenderingContext, uniforms: UniformSet, programOverride?: ProgramInfo): void; } /** Billboarding modes, most things will ue NONE */ declare enum BillboardType { SPHERICAL = 0, CYLINDRICAL = 1 } /** * A simple 2D billboard, like a tree or grass. These are square by default, but can be scaled XY if needed. * Both cylindrical and spherical billboards are supported. You must assign material with a texture * to be rendered as a sprite on the billboard * @see http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/ */ declare class Billboard implements Renderable { protected bufferInfo: twgl.BufferInfo; private programInfo; material: Material; type: BillboardType; /** Creates a square billboard */ constructor(gl: WebGL2RenderingContext, type: BillboardType, material: Material, size: number); /** * Render is used draw this billboard, this is called from the Instance that wraps * this renderable */ render(gl: WebGL2RenderingContext, uniforms: UniformSet, materialOverride?: Material): void; } /** * Particle system, uses transform feedback on the GPU to update particles * and VAO instancing to render them */ declare class ParticleSystem implements Renderable { private progInfoUpdate; private progInfoRender; private inputBuffInfo; private outputBuffInfo; private outputVAO; /** When enabled, particles will be spawned and emitted */ enabled: boolean; /** Texture to use for particles */ texture: WebGLTexture; /** Emission rate, number of particles per frame */ emitRate: number; /** Min lifetime of particles in seconds */ minLifetime: number; /** Max lifetime of particles in seconds */ maxLifetime: number; /** Gravity vector. Default: [0, -9.81, 0] */ gravity: XYZ; /** Min power (speed) of particles, this is multiplied by the direction vector */ minPower: number; /** Max power (speed) of particles, this is multiplied by the direction vector */ maxPower: number; /** Particles will randomly emit in a direction between this vector and direction2 */ direction1: XYZ; /** Particles will randomly emit in a direction between this vector and direction1 */ direction2: XYZ; /** Particles are spawned in a bounding box, defined by this vector as one corner */ emitterBoxMin: XYZ; /** Particles are spawned in a bounding box, defined by this vector as one corner */ emitterBoxMax: XYZ; /** Speed up or slow down time */ timeScale: number; /** Change colour and alpha as particle reaches it's lifetime. Default: [0,0,0,1] */ ageColour: RGBA; /** Min random size of particles */ minSize: number; /** Max random size of particles */ maxSize: number; /** Min initial random rotation of particles in radians */ minInitialRotation: number; /** Max initial random rotation of particles in radians */ maxInitialRotation: number; /** Min random rotation speed of particles in radians per second */ minRotationSpeed: number; /** Max random rotation speed of particles in radians per second */ maxRotationSpeed: number; /** Duration of particle system in frames, -1 = forever. Default: -1 */ duration: number; /** Acceleration or deceleration multiplier, default 1.0. Applied every frame, so keep values *very* close to 1.0 */ acceleration: number; /** Blend source mode, default: 'SRC_ALPHA', leave alone unless you know what you are doing */ blendSource: number; /** Blend destination mode, default: 'ONE', leave alone unless you know what you are doing */ blendDest: number; /** Colour multiplier pre-applied to particle texture before ageing */ preColour: RGBA; /** Age power curve */ agePower: number; /** Particles transformed fixed to local coordinate space, generally leave as false */ localSpace: boolean; /** * Create a new particle system * @param gl WebGL2 rendering context * @param maxParticles Maximum number of particles in the system * @param baseSize Size of the particle quad */ constructor(gl: WebGL2RenderingContext, maxParticles: number, baseSize: number); /** * Render the particle system and implement the renderable interface * @param gl WebGL2 rendering context * @param uniforms Uniforms to pass to the shaders */ render(gl: WebGL2RenderingContext, uniforms: UniformSet): void; /** * Update the particles positions and velocities */ private updateParticles; /** * Render the particles to the world */ private renderParticles; } declare class HUD { private hud; private canvas; private debugDiv; private loadingDiv; debug: boolean; constructor(canvas: HTMLCanvasElement); /** * Update the HUD position and size to match the canvas */ private updateWithCanvas; /** * Add a HTML element to the HUD * @param item HTML element to add */ addHUDItem(item: HTMLElement): void; /** * Render the HUD, called once per frame */ render(debug: boolean | undefined, camera: Camera): void; /** * Hide the loading message, this is called by the engine */ hideLoading(): void; } /** * A builder for creating multi-part models from triangle meshes * Use in conjunction Model.parseFromBuilder * * Example usage: * ```typescript * const builder = new ModelBuilder() * const part = builder.newPart('foo' Material.RED) * builder.addTriangle([1, -1, 1], [1, 1, 1], [-1, 1, 1]) * Model.parseFromBuilder(builder, 'myModel') * ``` */ declare class ModelBuilder { readonly parts: Map<string, BuilderPart>; constructor(); /** * Create and add a 'part', each part should have a unique name, and material to apply to it * Vertex mesh data is then added to the part, with addQuad and addTriangle * @param name Name of this part, just a string can be anything * @param material Material to attach and apply to all surfaces in this part */ newPart(name: string, material: Material): BuilderPart; } type extraAttributes = { [key: string]: { numComponents: number; data: number[]; }; }; /** * Manage parts or sections to be built into a model */ declare class BuilderPart { private vertexData; private vertexCount; private indexData; private indexCount; private normalData; private texcoordData; private _boundingBox; material: Material; readonly name: string; /** * This is an *extremely* advanced feature, and allows you to add custom attributes to the part * You will need to understand how to use twgl.js to use this feature at the createBufferInfoFromArrays function */ extraAttributes?: extraAttributes; get boundingBox(): number[]; private _triCount; get triangleCount(): number; private _customArrayData; constructor(name: string, mat: Material); private addVertex; private addIndex; private addNormal; /** * Add a triangle to the renderable part * Each triangle must be defined by 3 vertices and will get a normal calculated * Each triangle will get a unique normal, so no smooth shading * @param v1 Vertex 1 of the triangle * @param v2 Vertex 2 of the triangle * @param v3 Vertex 3 of the triangle * @param tc1 Texture coordinate for vertex 1 * @param tc2 Texture coordinate for vertex 2 * @param tc3 Texture coordinate for vertex 3 */ addTriangle(v1: XYZ, v2: XYZ, v3: XYZ, tc1?: number[], tc2?: number[], tc3?: number[]): void; /** * Add a two triangle quad to the renderable part * Each quad must be defined by 4 vertices and will get a normal calculated * Each quad will get a unique normal, so no smooth shading * @param v1 Vertex 1 of the quad * @param v2 Vertex 2 of the quad * @param v3 Vertex 3 of the quad * @param v4 Vertex 4 of the quad * @param tc1 UV texture coordinate for vertex 1 * @param tc2 UV texture coordinate for vertex 2 * @param tc3 UV texture coordinate for vertex 3 * @param tc4 UV texture coordinate for vertex 4 */ addQuad(v1: XYZ, v2: XYZ, v3: XYZ, v4: XYZ, tc1?: number[], tc2?: number[], tc3?: number[], tc4?: number[]): void; /** * This is a very advanced feature, and allows you to provide your own twgl.Arrays * This is useful for creating custom renderables from existing data * @param array The twgl.Arrays to use for the renderable */ set customArrayData(array: twgl.Arrays); /** * Build the part from the data added and turn into a twgl.BufferInfo * @param gl A WebGL2 rendering context * @returns BufferInfo used by twgl */ build(gl: WebGL2RenderingContext): twgl.BufferInfo | null; } /** * The main rendering context. This is the effectively main entry point for the library. * Typically you will create a single instance of this class using init() and use it to render your scene. */ declare class Context { private gl; private started; private instances; private instancesTrans; private instancesParticles; private cameras; private activeCameraName; private _envmap?; private dynamicEnvMap?; private renderPass; /** Global directional light */ globalLight: LightDirectional; /** All the dynamic point lights in the scene */ lights: LightPoint[]; /** Main camera for this context */ private _camera; /** Show extra debug details on the canvas */ debug: boolean; /** Optional post effects filter to apply to the output image */ private postEffects?; /** * The pre-render update function, called every frame. * Hook in your custom logic and processing here */ update: (delta: number, now?: number) => void; /** A HUD you can use to render HTML elements over the canvas */ readonly hud?: HUD; /** Gamma correction value, default 1.0 */ gamma: number; /** * Integration with cannon-es for physics, set the CANNON.World you are using here. * When set, world stepping will be called for you in the core rendering loop */ physicsWorld?: CANNON.World; /** Set the fixed time step for physics stepping, only used when physicsWorld is set */ physicsTimeStep: number; /** Backface culling */ disableCulling: boolean; /** * Blend mode for non-opaque instances * 'NORMAL' is the default, 'ADDITIVE' is useful for particles and glowing effects */ blendMode: 'NORMAL' | 'ADDITIVE'; version: string; /** Get the active camera */ get camera(): Camera; /** Get the name of the active camera */ get cameraName(): string; /** Get the current EnvironmentMap for the scene */ get envmap(): EnvironmentMap | undefined; /** Constructor is private, use init() to create a new context */ private constructor(); /** * Create & initialize a new Context which will render into provided canvas. This is where you start when using the library. * @param canvasSelector CSS selector for canvas element, default is 'canvas' * @param antiAlias Enable anti-aliasing in the renderer, default is true */ static init(canvasSelector?: string, antiAlias?: boolean, noHud?: boolean): Promise<Context>; /** * Main render loop, called every frame by the context when started * @param now Current time in milliseconds */ private render; /** * Render the scene from the given camera, used internally for rendering both the main view, * but also shadow maps and dynamic env maps * @param camera */ renderWithCamera(camera: Camera, programOverride?: twgl.ProgramInfo): void; /** * Start the rendering loop, without calling this nothing will render */ start(): void; /** * Stop the rendering loop */ stop(): void; /** * Set the log level for the library * @param level - Log level to set, default is 'info' */ setLogLevel(level: log.LogLevelNames): void; /** * Resize the canvas & viewport to match the size of the HTML element that contains it * @param viewportOnly - Only resize the GL viewport, not the canvas, default false */ resize(viewportOnly?: boolean): void; /** * Internal function to add an instance to the scene */ private addInstance; /** * Model loader, loads an OBJ model from a file via URL or path and adds it to the cache * This is preferred over calling Model.parse() directly * @param path Base path to the model file, e.g. './renderable/' * @param fileName Name of the model file, e.g 'teapot.obj' * @param filterTextures Apply texture filtering as materials are loaded * @param flipTextureY Flip the Y coordinate of the texture */ loadModel(path: string, fileName: string, filterTextures?: boolean, flipY?: boolean, flipUV?: boolean): Promise<void>; /** * Add or replace a named camera to the scene * @param name Name of the camera * @param camera Camera instance */ addCamera(name: string, camera: Camera): void; /** * Get a camera by name * @param name Name of the camera */ getCamera(name: string): Camera | undefined; /** * Set the active camera, rendering will switch to this camera's view * @param name Name of the camera to set as active */ setActiveCamera(name: string): void; /** * Create a new model instance, which should have been previously loaded into the cache * @param modelName - Name of the model previously loaded into the cache, don't include the file extension */ createModelInstance(modelName: string, transparent?: boolean): Instance; /** * Create an instance of a primitive sphere * @param material - Material to apply to the sphere * @param radius - Radius of the sphere * @param subdivisionsH - Number of subdivisions along the horizontal * @param subdivisionsV - Number of subdivisions along the vertical */ createSphereInstance(material: Material, radius?: number, subdivisionsH?: number, subdivisionsV?: number): Instance; /** * Create an instance of a primitive plane * @param material - Material to apply to the plane * @param width - Width of the plane * @param height - Height of the plane * @param subdivisionsW - Number of subdivisions along the width * @param subdivisionsH - Number of subdivisions along the height * @param tiling - Number of times to tile the texture over the plane */ createPlaneInstance(material: Material, width?: number, height?: number, subdivisionsW?: number, subdivisionsH?: number, tiling?: number): Instance; /** * Create an instance of a primitive cube */ createCubeInstance(material: Material, size?: number, tilingFactor?: number): Instance; /** * Create an instance of a primitive cylinder */ createCylinderInstance(material: Material, r?: number, h?: number, subdivisionsR?: number, subdivisionsH?: number, caps?: boolean): Instance; /** * Create an instance of a billboard/sprite in the scene * @param textureUrl - Path to the texture image file to use for the billboard * @param width - Width of the billboard (default: 5) * @param height - Height of the billboard (default: 5) * @param type - Type of billboard to create (default: CYLINDRICAL) */ createBillboardInstance(material: Material, size?: number, type?: BillboardType): Instance; /** * Create a new point light in the scene * @param position - Position of the light * @param colour - Colour of the light, defaults to white * @param intensity - Intensity of the light * @returns The new light object */ createPointLight(position: XYZ, colour?: RGB, intensity?: number): LightPoint; /** * Create a new particle system in the scene * @param maxParticles Maximum number of particles to allow in the system * @param baseSize Base size of the particles, default 2 * @returns Both the instance and the particle system */ createParticleSystem(maxParticles?: number, baseSize?: number): { instance: Instance; particleSystem: ParticleSystem; }; /** * Set the EnvironmentMap for the scene, will overwrite any existing envmap. * This will enable static reflections and create a 'skybox' around the scene * @param textureURLs - Array of 6 texture URLs to use for the map, in the order: +X, -X, +Y, -Y, +Z, -Z */ setEnvmap(renderAsBackground?: boolean, ...textureURLs: string[]): void; /** * Remove any current EnvironmentMap from the scene */ removeEnvmap(): void; /** * Set and create a dynamic environment map which will enable dynamic/realtime reflections * @param position - Position to render reflections from * @param size - Size of the map to render, note higher sizes will come with a big performance hit */ setDynamicEnvmap(position: XYZ, size?: number, renderDistance?: number): void; /** * Remove instance from the scene, it will no longer be rendered * @param instance - Instance to remove */ removeInstance(instance: Instance): void; /** * Remove all instances from the scene */ removeAllInstances(): void; /** * Use a custom shader for post effects, user must provide their own shader * @param shaderCode - GLSL shader code for the post effect */ setEffectCustom(shaderCode: string): void; /** * Use bulit-in scanlines post effect shader * @param density - Density of the scanlines, default 1.5 * @param opacity - Opacity of the scanlines, default 0.5 * @param noise - Noise level, default 0.2 * @param flicker - Flicker ammount, default 0.015 */ setEffectScanlines(density?: number, opacity?: number, noise?: number, flicker?: number): void; /** * Use bulit-in glitch post effect shader * @param amount - Amount of glitch, default 0.01 */ setEffectGlitch(amount?: number): void; /** * Use bulit-in noise post effect shader * @param amount - Amount of noise, default 0.1 * @param speed - Speed of noise pattern, default 5.0 */ setEffectNoise(amount?: number, speed?: number): void; /** * Use bulit-in duotone post effect shader for monotone images * @param colour1 - First colour, default [0.15, 0.09, 0.309] * @param colour2 - Second colour, default [0.96, 0.39, 0.407] * @param contrast - Contrast, default 1.5 */ setEffectDuotone(colour1?: RGB, colour2?: RGB, contrast?: number): void; /** * Use bulit-in contrast post effect shader, which reduces the image to two solid colours * @param threshold * @param darkColour * @param lightColour */ setEffectContrast(threshold?: number, darkColour?: RGB, lightColour?: RGB): void; /** * Remove any post effects shader */ removeEffect(): void; /** * Create and build a custom model from a ModelBuilder and cache it for use * @param builder Builder with geometry and materials added * @param name Name of the model */ buildCustomModel(builder: ModelBuilder, name: string): void; } /** * Holds a 3D model, as a list of parts, each with a material * Plus map of named materials */ declare class Model implements Renderable { private programInfo; private readonly parts; private readonly materials; private triCount; private _boundingBox; /** Name of the model, usually the filename without the extension */ readonly name: string; /** * Constructor is private, use static `parse()` method instead */ private constructor(); /** * Render is used draw this model, this is called from the Instance that wraps * this renderable. */ render(gl: WebGL2RenderingContext, uniforms: UniformSet, materialOverride?: Material, programOverride?: twgl.ProgramInfo): void; /** Simple getter for the number of triangles in the model */ get triangleCount(): number; /** * Parse an OBJ file & MTL material libraries, returns a new Model * @param {string} path - The path to the OBJ file * @param {string} objFilename - The name of the OBJ file * @param {boolean} filterTextures - Apply texture filtering to textures, default: true * @param {boolean} flipTextureY - Flip the Y axis of textures as they are loaded, default: false * @param {boolean} flipUV - Flip the UV coords of the model in the vertex/mesh data, default: true */ static parse(path: string | undefined, objFilename: string, filterTextures?: boolean, flipTextureY?: boolean, flipUV?: boolean): Promise<Model>; /** * Parse a custom model from a ModelBuilder, this is used to build models in code * @param {ModelBuilder} builder - The ModelBuilder to parse * @param {string} name - The name of the model */ static parseFromBuilder(builder: ModelBuilder, name: string): Model; /** * Get list of all material names in this model used by all parts * @returns {string[]} - List of material names */ get materialNames(): string[]; /** * Get number of parts in this model */ get partsCount(): number; /** * Get list of parts in this model, names are the material names * @returns {string[]} - List of part material names */ get partList(): string[]; /** * Can modify & override an existing named material * @param {string} name - Name of the material to modify * @param {Material} material - New material to use */ setNamedMaterial(name: string, material: Material): void; /** * Get a named material * @param {string} name - Name of the material to get */ getNamedMaterial(name: string): Material; get boundingBox(): number[]; } /** * Holds part of a model, as the WebGL buffers needed to render it * Plus the material name associated with this part */ declare class ModelPart { readonly bufferInfo: twgl.BufferInfo; readonly materialName: string; /** * @param {twgl.BufferInfo} bufferInfo - WebGL buffer info for this model part * @param {string} materialName - Name of the material associated with this part */ constructor(bufferInfo: twgl.BufferInfo, materialName: string); } /** @ignore */ declare const PROG_DEFAULT = "phong"; /** @ignore */ declare const PROG_BILLBOARD = "billboard"; /** * A singleton cache for parsed and loaded models, indexed by name */ declare class ModelCache { private cache; private static _instance; private constructor(); /** * Return the singleton instance of the model cache */ static get instance(): ModelCache; /** * Return a model from the cache by name * @param name Name of model without extension * @param warn If true, log a warning if model not found */ get(name: string, warn?: boolean): Model | undefined; /** * Add a model to the cache, using the model name as key */ add(model: Model): void; } /** * A caching texture manager * It is instantiated with a WebGL context and then used to load and cache textures */ declare class TextureCache { private cache; private gl; private static _instance; private static initialized; private defaultWhite; private defaultRand; private constructor(); static init(gl: WebGL2RenderingContext, randSize?: number): void; /** * Return the singleton instance of the texture cache */ static get instance(): TextureCache; /** * Return a texture from the cache by name * @param key Key of texture, this is usually the URL or filename path */ get(key: string): WebGLTexture | undefined; /** * Add a texture to the cache * @param key Key of texture, this is usually the URL or filename path * @param texture WebGL texture */ add(key: string, texture: WebGLTexture): void; /** * Create or return a texture from the cache by name * @param src URL or filename path of texture image, or ArrayBufferView holding texture * @param filter Enable texture filtering and mipmaps (default true) * @param flipY Flip the texture vertically (default true) * @param textureKey Unique key, only used for ArrayBuffer textures * @param extraOptions Extra options to pass to twgl.createTexture, see https://twgljs.org/docs/module-twgl.html#.TextureOptions */ getCreate(src: string | ArrayBufferView, filter?: boolean, flipY?: boolean, textureKey?: string, extraOptions?: TextureOptions$1): WebGLTexture | undefined; /** * Return the default white 1x1 texture */ static get defaultWhite(): WebGLTexture; /** * Return the default random RGB texture */ static get defaultRand(): WebGLTexture; /** * Return the number of textures in the cache */ static get size(): number; /** * Clear the texture cache */ static clear(): void; } /** * Singleton cache for parsed and loaded GL programs, indexed by name */ declare class ProgramCache { private cache; private _default; private static _instance; private static initialized; static PROG_PHONG: string; static PROG_BILLBOARD: string; static PROG_SHADOWMAP: string; /** * Create a new program cache, can't be used until init() is called */ private constructor(); /** * Initialise the program cache with a default