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(); }); ```