Skip to main content

External WebGL Contexts

This tutorial will be a simple demonstration of how to use an externally created WebGL context with luma.gl's higher-level APIs.

caution

The tutorial pages have not yet been updated for luma.gl v9.

  • External context example is temporarily disabled until support is added to luma.gl v9
  • This page applies to WebGL only

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).

We'll create a modified version of the Hello Triangle tutorial that creates a WebGL context manually rather than using the AnimationLoop class. To start with, we'll modify our imports:

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:

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.

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:

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;

out vec3 vColor;

void main() {
vColor = color;
gl_Position = vec4(position, 0.0, 1.0);
}
`;

const fs = `
in 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();
});