Atlaslog
Atlaslog / luma.gl / Tutorial / Writing a WebGL program with luma.gl
luma.gl · Tutorial

Writing a WebGL program with luma.gl

Quick answer

This tutorial draws a single triangle with luma.gl alone, without deck.gl or three.js. It walks through createDevice with the webgl2Adapter, createBuffer for three positions, a Model that bundles shaders, attributes and bufferLayout, and an AnimationLoop opening a render pass each frame. It then aligns each step with its native WebGL equivalent and shows how buffer.write updates vertices. Readers can stand up a minimal WebGL2 application and extend it.

Last verified 2026-11-03 · luma.gl 9.4 · Cite this page
Key points
Example
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <style>
    html, body { height: 100%; margin: 0; background: #0d1117; }
    #cv { display: block; width: 100%; height: 100%; }
  </style>
</head>
<body>
  <canvas id="cv"></canvas>

  <script src="https://cdn.jsdelivr.net/npm/@luma.gl/core@9.4.2/dist/dist.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@luma.gl/webgl@9.4.2/dist/dist.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@luma.gl/shadertools@9.4.2/dist/dist.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@luma.gl/engine@9.4.2/dist/dist.min.js"></script>

  <script>
    (async function () {
      const canvas = document.getElementById('cv');
      const device = await luma.luma.createDevice({
        type: 'webgl',
        adapters: [luma.webgl2Adapter],
        createCanvasContext: {
          canvas: canvas,
          useDevicePixels: Math.min(window.devicePixelRatio, 2),
          autoResize: true
        }
      });
      const positions = device.createBuffer(new Float32Array([
        -0.6, -0.45, 0,
         0.6, -0.45, 0,
         0.0,  0.55, 0
      ]));
      const model = new luma.Model(device, {
        topology: 'triangle-list',
        vertexCount: 3,
        attributes: { positions: positions },
        bufferLayout: [
          { name: 'positions', stepMode: 'vertex', format: 'float32x3' }
        ],
        vs: [
          '#version 300 es',
          'in vec3 positions;',
          'void main() {',
          '  gl_Position = vec4(positions, 1.0);',
          '}'
        ].join('\n'),
        fs: [
          '#version 300 es',
          'precision highp float;',
          'out vec4 fragColor;',
          'void main() {',
          '  fragColor = vec4(0.35, 0.80, 0.62, 1.0);',
          '}'
        ].join('\n')
      });
      const loop = new luma.AnimationLoop({
        device: device,
        onRender: function (props) {
          const pass = props.device.beginRenderPass({
            clearColor: [0.05, 0.07, 0.10, 1]
          });
          model.draw(pass);
          pass.end();
        },
        onError: function (error) {
          console.error(error);
        }
      });

      await loop.start();
    })();
  </script>
</body>
</html>
Notes
Runnable examplesChinese originalAll Tutorials
English edition written for Atlaslog. Code is taken from the original Chinese page and runs unchanged.
Cite this page

Atlaslog (2026). Writing a WebGL program with luma.gl. https://www.jingweizhi.com/en/lumagl/tutorials/raw-webgl.html (accessed 2026-11-03).