mirror of
https://github.com/visgl/luma.gl.git
synced 2025-12-08 17:36:19 +00:00
162 lines
7.9 KiB
Markdown
162 lines
7.9 KiB
Markdown
# AnimationLoop
|
|
|
|
Manages an animation loop and optionally a WebGL context and a WebGL canvas. It provides a number of features related to initialization and animation of a WebGL context.
|
|
|
|
* Provides a number of commonly needed variables as part of the `context` object which is passed to `onRender` and `onFinalize` callbacks.
|
|
* Objects returned by `onInitailize` will be appended to `context` object hence available to `onRender` and `onFinalize`.
|
|
* To avoid problems with page load timing, move context creation to the `onCreateContext` method.
|
|
* By default, `onRender` method manages resizing of canvas, viewport and framebuffer.
|
|
* Makes it easy to wait for the HTML page to load before creating a canvas and WebGL resources.
|
|
|
|
References:
|
|
|
|
* [WebGL Fundamentals](https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html#drawingbuffer) contains excellent information on the subtleties of the how the WebGL context's drawing buffer and the HTML canvas interact.
|
|
* When running in the browser, this class uses [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
|
|
|
|
|
|
## Usage
|
|
|
|
Autocreates a canvas/context
|
|
```js
|
|
import {AnimationLoop, ClipSpace} from '@luma.gl/core';
|
|
|
|
const animationLoop = new AnimationLoop({
|
|
onInitialize({gl}) {
|
|
// Keys in the object returned here will be available in onRender
|
|
return {
|
|
clipSpaceQuad: new ClipSpace({gl, fs: FRAGMENT_SHADER})
|
|
};
|
|
},
|
|
onRender({tick, clipSpaceQuad}) {
|
|
// Tick is autoupdated by AnimationLoop
|
|
clipSpaceQuad.setUniforms({uTime: tick * 0.01}).draw();
|
|
}
|
|
});
|
|
|
|
animationLoop.start();
|
|
```
|
|
|
|
Use a canvas in the existing DOM through its HTML id
|
|
```js
|
|
animationLoop.start({canvas: 'my-canvas'});
|
|
```
|
|
|
|
## Methods
|
|
|
|
### constructor(props : Object)
|
|
|
|
```js
|
|
new AnimationLoop({
|
|
onCreateContext,
|
|
onInitialize,
|
|
onFinalize,
|
|
onRender,
|
|
|
|
autoResizeViewport,
|
|
autoResizeDrawingBuffer
|
|
});
|
|
```
|
|
|
|
* `props.onCreateContext`=`null` (callback) - function without parameters that returns a `WebGLRenderingContext`. This callback will be called exactly once, after page load completes.
|
|
* `props.onInitialize` (callback) - if supplied, will be called once after first `start()` has been called, after page load completes and a context has been created.
|
|
* `props.onRender`=`null` (callback) - Called on every animation frame.
|
|
* `props.onFinalize`=`null` (callback) - Called once when animation is stopped. Can be used to delete objects or free any resources created during `onInitialize`.
|
|
* `props.autoResizeViewport`=`true` - If true, calls `gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight)` each frame before `onRender` is called. Set to false to control viewport size.
|
|
* `props.autoResizeDrawingBuffer`=`true` - If true, checks the canvas size every frame and updates the drawing buffer size if needed.
|
|
* `props.useDevicePixels` - Whether to use `window.devicePixelRatio` as a multiplier, e.g. in `autoResizeDrawingBuffer` etc.
|
|
* `props.gl`=`null` (WebGLContext) - If supplied, will render into this external context instead of creating a new one.
|
|
* `props.glOptions`=`{}` (object) - Options to create the WebGLContext with. See [createGLContext](/docs/api-reference/webgl/context/context.md).
|
|
* `props.debug`=`false` (bool) - Enable debug mode will provide more validations and error messages, but less performant.
|
|
* `props.createFramebuffer`=`false` (bool) - If true, will make a `framebuffer` (FrameBuffer) parameter available to `onInitialize` and `onRender` callbacks.
|
|
|
|
|
|
### start([options : Object]) : AnimationLoop
|
|
|
|
Restarts the animation
|
|
|
|
`animationLoop.start(options)`
|
|
|
|
* `options`=`{}` (object) - Options to create the WebGLContext with. See [createGLContext](/docs/api-reference/webgl/context/context.md).
|
|
|
|
### stop() : AnimationLoop
|
|
|
|
Stops the animation
|
|
|
|
`animationLoop.stop()`
|
|
|
|
### waitForRender() : Promise
|
|
|
|
Returns a promise which resolves in the next frame after rendering and the `onRender` callback have completed.
|
|
|
|
```js
|
|
const loop = await animationLoop.waitForRender()
|
|
// can now read pixels from webgl context
|
|
loop.gl.readPixels(...)
|
|
```
|
|
|
|
### redraw() : AnimationLoop
|
|
|
|
Immediately invokes a redraw (call `onRender` with updated animation props). Only use if the canvas must be updated synchronously.
|
|
|
|
### setNeedsRedraw(reason : String) : AnimationLoop
|
|
|
|
`animationLoop.setNeedsRedraw(reason)`
|
|
|
|
* `reason` (`String`) - A human readable string giving a hint as to why redraw was needed (e.g. "geometry changed").
|
|
|
|
If set, the value will be provided as the `needsRedraw` field to the `onRender` callback.
|
|
|
|
Notes:
|
|
* `onRender` will be called for each animation frame regardless of whether this flag is set, and the redraw reason is automatically cleared.
|
|
* If called multiple times, the `reason` provided in the first call will be remembered.
|
|
* `AnimationLoop` automatically sets this flag if the WebGL context's drawing buffer size changes.
|
|
|
|
|
|
### setProps(props : Object) : AnimationLoop
|
|
|
|
`animationLoop.setProps({...props})`
|
|
|
|
* `props.autoResizeViewport` - Call `gl.viewport` before each call to `onRender()`
|
|
* `props.autoResizeDrawingBuffer` - Update the drawing buffer size to match the canvas size before each call to `onRender()`
|
|
* `props.useDevicePixels` - Whether to use `window.devicePixelRatio` as a multiplier, e.g. in `autoResizeDrawingBuffer` etc.
|
|
|
|
### toDataURL
|
|
|
|
Returns returns a `Promise` that resolves to the data URL of the canvas once drawing operations are complete for the current frame. The data URL can be used as the `src` for an HTML image element.
|
|
|
|
`animationLoop.toDataURL()`
|
|
|
|
|
|
## Callback Parameters
|
|
|
|
The callbacks `onInitialize`, `onRender` and `onFinalize` that the app supplies to the `AnimationLoop`, will be called with an object containing named parameters:
|
|
|
|
| Parameter | Type | Description |
|
|
| --- | --- | --- |
|
|
| `_animationLoop` | `AnimationLoop` | (**experimental**) The calling `AnimationLoop` instance |
|
|
| `gl` | `WebGLRenderingContext` | This `AnimationLoop`'s gl context. |
|
|
| `canvas` | `HTMLCanvasElement` or `OffscreenCanvas` | The canvas associated with this context. |
|
|
| `width` | The drawing buffer width, in "device" pixels (can be different from canvas.width). |
|
|
| `height` | The drawing buffer height, in "device" pixels (can be different from canvas.width). |
|
|
| `aspect` | The canvas aspect ratio (width/height) to update projection matrices |
|
|
| `useDevicePixels` | Boolean indicating if canvas is utilizes full resolution of Retina/
|
|
| `needsRedraw` | `String` | Redraw flag (will be automatically set if drawingBuffer resizes) |
|
|
| `time` | `Number` | Milliseconds since `AnimationLoop` was created (monotonic). |
|
|
| `tick` | `Number` | Counter that updates for every frame rendered (monotonic). |
|
|
| `framebuffer` | `FrameBuffer` | Availabel if `createFrameBuffer: true` was passed to the constructor. |
|
|
| `_mousePosition` | `[x, y]` or `null` | (**experimental**) Current mouse position over the canvas. |
|
|
| `_offScreen` | `Boolean` | (**experimental**) If the animation loop is rendering to an OffscreenCanvas. |
|
|
| ... | Any fields in the object that was returned by the `onInitialize` method. |
|
|
|
|
### Frame timers
|
|
* The animation loop tracks GPU and CPU render time of each frame the in member properties `cpuTime` and `gpuTime`. If `gpuTime` is set to `-1`, then the timing for the last frame was invalid and should not be used (this rare and might occur, for example, if the GPU was throttled mid-frame).
|
|
|
|
## Remarks
|
|
|
|
* You can instantiate multiple `AnimationLoop` classes in parallel, rendering into the same or different `WebGLRenderingContext`s.
|
|
* Works both in browser and under Node.js.
|
|
* All `AnimationLoop` methods can be chained.
|
|
* Postpones context creation until the page (i.e. all HTML) has been loaded. At this time it is safe to specify canvas ids when calling [`createGLContext`](/docs/api-reference/webgl/context/context.md).
|
|
* The supplied callback function must return a WebGLRenderingContext or an error will be thrown.
|
|
* This callback registration function should not be called if a `WebGLRenderingContext` was supplied to the AnimationLoop constructor.
|