canvas#webgl
View Compiled
      html,
      body {
        margin: 0;
        padding: 0;
        border: 0;
        font-size: 100%;
        font: inherit;
        vertical-align: baseline;
        background: #000;
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
// πŸ–ΌοΈ Get Canvas
let canvas: HTMLCanvasElement = document.getElementById('webgl') as HTMLCanvasElement;
canvas.width = canvas.height = 640;

// βšͺ Initialization
let gl: WebGLRenderingContext = canvas.getContext('webgl');

if (!gl) {
    // This rendering engine failed to start...
    throw new Error('WebGL failed to initialize.');
}

// Most WebGL Apps will want to enable these settings:

// ⚫ Set the default clear color when calling `gl.clear`
gl.clearColor(0.0, 0.0, 0.0, 0.0);
// 🎭 Write to all channels during a clear
gl.colorMask(true, true, true, true)
// πŸ‘“ Test if when something is drawn, it's in front of what was drawn previously
gl.enable(gl.DEPTH_TEST);
// ≀ Use this function to test depth values
gl.depthFunc(gl.LEQUAL);
// πŸŒ’ Hide triangles who's normals don't face the camera
gl.cullFace(gl.BACK);
// πŸ₯ Properly blend images with alpha channels
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

// πŸ“ˆ Position Vertex Buffer Data
const positions = new Float32Array([
    1.0, -1.0, 0.0,
   -1.0, -1.0, 0.0,
    0.0, 1.0, 0.0
]);

// 🎨 Color Vertex Buffer Data
const colors = new Float32Array([
    1.0, 0.0, 0.0, // πŸ”΄
    0.0, 1.0, 0.0, // 🟒
    0.0, 0.0, 1.0  // πŸ”΅
]);

// βœ‹ Declare Vertex Buffer Handles
let positionBuffer: WebGLBuffer = null;
let colorBuffer: WebGLBuffer = null;

// πŸ‘‹ Helper function for creating WebGLBuffer(s) out of Typed Arrays
let createBuffer = (arr) => {
    // βšͺ Create Buffer
    let buf = gl.createBuffer();
    let bufType =
        arr instanceof Uint16Array || arr instanceof Uint32Array ? gl.ELEMENT_ARRAY_BUFFER : gl.ARRAY_BUFFER;
    // 🩹 Bind Buffer to WebGLState
    gl.bindBuffer(bufType, buf);
    // πŸ’Ύ Push data to VBO
    gl.bufferData(bufType, arr, gl.STATIC_DRAW);
    return buf;
};

// βšͺ Create VBO
positionBuffer = createBuffer(positions);
colorBuffer = createBuffer(colors);

// πŸ—„οΈ Index Buffer Data
const indices = new Uint16Array([ 0, 1, 2 ]);

// βœ‹ Declare Index Buffer Handle
let indexBuffer: WebGLBuffer = null;

// βšͺ Create IBO (☝ Refer to helper function above)
indexBuffer = createBuffer(indices);

// βœ‹ Declare Vertex Shader Handle
let vertModule: WebGLShader = null;

// πŸ•ΈοΈ Vertex Shader Source
const vertShaderCode = `
attribute vec3 inPosition;
attribute vec3 inColor;

varying vec3 vColor;

void main()
{
    vColor = inColor;
    gl_Position = vec4(inPosition, 1.0);
}
`;

// πŸ‘‹ Helper function for creating WebGLShader(s) out of strings
let createShader = (source: string, stage) => {
    // βšͺ Create Shader
    let s = gl.createShader(stage);
    // πŸ“° Pass Vertex Shader String
    gl.shaderSource(s, source);
    // πŸ”¨ Compile Vertex Shader (and check for errors)
    gl.compileShader(s);
    // ❔ Check if shader compiled correctly
    if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
        console.error('An error occurred compiling the shader: ' + gl.getShaderInfoLog(s));
    }
    return s;
};

vertModule = createShader(vertShaderCode, gl.VERTEX_SHADER);

// βœ‹ Declare Vertex Shader Handle
let fragModule: WebGLShader = null;

// 🟦 Fragment Shader Source
const fragShaderCode = `
precision mediump float;

varying highp vec3 vColor;

void main()
{
    gl_FragColor = vec4(vColor, 1.0);
}
`;

// ☝️ Refer to vertex sample above
fragModule = createShader(fragShaderCode, gl.FRAGMENT_SHADER);

// βœ‹ Declare Program Handle
let program: WebGLProgram = null;


// πŸ‘‹ Helper function for creating WebGLProgram(s) out of WebGLShader(s)
let createProgram = (stages: WebGLShader[]) => {
    let p = gl.createProgram();
    for (let stage of stages) {
        gl.attachShader(p, stage);
    }
    gl.linkProgram(p);
    return p;
};

program = createProgram([vertModule, fragModule]);

// βœ‹ Declare animation handler
let animationHandler: number = 0;

// πŸ”Ί Render triangle
let render = () => {
    // πŸ–ŒοΈ Encode drawing commands
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.useProgram(program);
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.scissor(0, 0, canvas.width, canvas.height);

    // Bind Vertex Layout
    let setVertexBuffer = (buf: WebGLBuffer, name: string) => {
        gl.bindBuffer(gl.ARRAY_BUFFER, buf);
        let loc = gl.getAttribLocation(program, name);
        gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 4 * 3, 0);
        gl.enableVertexAttribArray(loc);
    };

    setVertexBuffer(positionBuffer, 'inPosition');
    setVertexBuffer(colorBuffer, 'inColor');

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);

    // ➿ Refresh canvas
    animationHandler = requestAnimationFrame(render);
};

// 🏎️ Start the Rendering Engine
render();
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.