luma.gl/docs/tutorials/external-context.mdx
2023-11-10 10:27:47 -05:00

130 lines
3.7 KiB
Plaintext

import {DeviceTabs} from '@site/src/react-luma';
# External WebGL Contexts
:::info
This page applies to WebGL only
:::
:::caution
External context example is temporarily disabled until support is added to luma.gl v9
:::
This tutorial will be a simple demonstration of how to use an externally created WebGL context
with luma.gl's higher-level APIs. So far, we have either created a WebGL context ourselves
to use with low-level APIs, or allowed the the `AnimationLoop` class to create a WebGL context for us.
luma.gl's higher-level APIs expect some instrumentation on the WebGL context,
so we can't just use a context we create ourselves with classes like `Model` and `Buffer`.
The `AnimationLoop` class performs this instrumentation for us using the `instrumentGLContext`
function from **@luma.gl/gltools**, and we can use this function directly
if we want to control creation of the context or use a context passed to us by another framework
(e.g. the GeoSpatial example uses this technique with a WebGL context
created by [MapboxGL](https://docs.mapbox.com/mapbox-gl-js/api/)).
We'll create a modified version of the [Hello Triangle](/docs/tutorials/hello-triangle) tutorial that creates a WebGL context manually rather than using the `AnimationLoop` class. To start with, we'll modify our imports:
```typescript
import {Model} from '@luma.gl/engine';
import {Buffer, clear} from '@luma.gl/webgl';
import {instrumentGLContext} from '@luma.gl/gltools';
```
We then create our context and pass it to `instrumentGLContext`:
```typescript
const canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 600;
document.body.appendChild(canvas);
const gl = instrumentGLContext(canvas.getContext('webgl'));
```
This performs some polyfilling (done by `polyfillContext`, and we create our own render loop using `requestAnimationFrame` rather than using the `AnimationLoop` callbacks.
```typescript
const gl = instrumentGLContext(canvas.getContext('webgl'));
gl.clearColor(0, 0, 0, 1);
const positionBuffer = new Buffer(gl, new Float32Array([-0.5, -0.5, 0.5, -0.5, 0.0, 0.5]));
const colorBuffer = new Buffer(gl, new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]));
// ...
const model = new Model(gl, {
vs,
fs,
attributes: {
position: positionBuffer,
color: colorBuffer
},
vertexCount: 3
});
requestAnimationFrame(function draw() {
requestAnimationFrame(draw);
clear(gl, {color: [0, 0, 0, 1]});
model.draw();
});
```
If all went well, a tri-color triangle should render as it did in the **Hello Triangle** example. The full source code is listed below for reference:
```typescript
import {Model} from '@luma.gl/engine';
import {Buffer, clear} from '@luma.gl/webgl';
import {instrumentGLContext} from '@luma.gl/gltools';
const canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 600;
document.body.appendChild(canvas);
const gl = instrumentGLContext(canvas.getContext('webgl'));
gl.clearColor(0, 0, 0, 1);
const positionBuffer = new Buffer(gl, new Float32Array([-0.5, -0.5, 0.5, -0.5, 0.0, 0.5]));
const colorBuffer = new Buffer(gl, new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]));
const vs = `
attribute vec2 position;
attribute vec3 color;
varying vec3 vColor;
void main() {
vColor = color;
gl_Position = vec4(position, 0.0, 1.0);
}
`;
const fs = `
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1.0);
}
`;
const model = new Model(gl, {
vs,
fs,
attributes: {
position: positionBuffer,
color: colorBuffer
},
vertexCount: 3
});
requestAnimationFrame(function draw() {
requestAnimationFrame(draw);
clear(gl, {color: [0, 0, 0, 1]});
model.draw();
});
```