Drawing a “Hello World” using webGL is not easy. It involves initialization of the WebGLRenderingContext, initialization of the WebGLProgram, production of model vertex data, and final rendering and rendering.

  1. We want to generate or find the canvas object;
  2. Initialize WebGLRenderingContext, WebGLProgram (GL and Program);
  3. Get model grid vertex data
  4. Model rendering

In this section we are going to focus on how to initialize the WebGLRenderingContext, WebGLProgram

**index.ts**

import RenderContext from './libs/renderContext';
import { Modal, Shape} from './libs';
const container = document.getElementById('root');
function main() {
    // Initialize the Canvas canvas and the gl and program in the RenderContext
    RenderContext.init({ 
        container,
        width: container.offsetWidth,
        height: container.offsetHeight,
    });
    
    // get gl and program
    const gl = RenderContext.getGL()
    constprogram = RenderContext.getProgram(); ** Use gl and program to draw graphics **} main();Copy the code
RenderContext is a global singleton that controls the initialization of GLS and programs, and provides methods for deriving GLS and programs
**renderContext.ts**

import { initGL } from './boot/initGL'
import { initProgram } from './boot/initProgram'
interface Options {
    container: HTMLElement; canvas? : HTMLCanvasElement; width: number; height: number; }// Create a singleton RenderContext
export default class RenderContext{ 
    static gl: WebGLRenderingContext;// bind gl
    static program: WebGLProgram; // Bind the program
    static canvas: HTMLCanvasElement; // Bind canvas
    
    // Initialize canvas
    static init(options: Options) { 
        if (RenderContext.canvas) return;
        if (options.canvas) {
                RenderContext.canvas = options.canvas;
        } else {
            const canvasHtml = document.createElement('canvas');
            canvasHtml.width = options.width;
            canvasHtml.height = options.height;
            canvasHtml.id = 'game-canvas'; options.container.appendChild(canvasHtml); RenderContext.canvas = canvasHtml; }}// Initialize gl and program
    static initContext(){
        if (RenderContext.gl) return;
        if(! RenderContext.canvas)return;
        const gl = initGL(RenderContext.canvas);
        if (gl) {
            const program = initProgram(gl);
            (gl as any).canvas.width = (gl as any).canvas.clientWidth;
            (gl as any).canvas.height = (gl asany).canvas.clientHeight; RenderContext.program = program; RenderContext.gl = gl; }}// Get the singleton GL
    static getGL() {
        RenderContext.initContext()
        return RenderContext.gl;
    }
    
    // Get the singleton program
    static getProgram() {
        RenderContext.initContext()
        returnRenderContext.program; }}Copy the code
The initGL method gets the WebGLRenderingContext from the Canvas object
**boot/initGL.ts**

// Initialize gl
export function initGL(canvas: HTMLCanvasElement) :WebGLRenderingContext | void {
    if (canvas) {
        const gl:WebGLRenderingContext  = canvas.getContext("webgl");
        if(! gl) {throw "gl initialize fail"
        }
        returngl; }}Copy the code
The initProgram method is used to initialize WebGLProgram and associate program with GL;
**boot/initProgram.ts**

import { vertexShaderSource, fragmentShaderSource } from './shader'

// Create vertex shader, slice shader methods
const loadShader = (gl: WebGLRenderingContext, type: GLenum, source: string) = > {
    const shader = gl.createShader(type); // Create vertex shader, slice shader type
    gl.shaderSource(shader, source);
    gl.compileShader(shader); // Compile the shader L code
    if(! gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {const error = `An error occurred compiling this shaders: ${gl.getShaderInfoLog(shader)}`
        gl.deleteShader(shader);
        throw error;
    }
    return shader
}

// Initialize program
export const initProgram = (gl: WebGLRenderingContext) = > {
    // Create vertex and slice shaders
    const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
    const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
    
    / / create the program
    const program: WebGLProgram = gl.createProgram();
    
    // Bind the shader to program
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);

    // Link the program to gl
    gl.linkProgram(program);
    return program;
}
Copy the code
Each WebGLProgram creation requires: vertexShader for vertexShader and fragmentShader for fragmentShader
**boot/shader.ts**

/** * a_position vertex [-1,1] data (0, 0) * u_resolution (1920, 1680) * zeroToOne converts vertex left to [0,1] * zeroToTwo converts vertex coordinates to [0, 2] * clipSpace converts vertex coordinates [-1,1] * gl_Position sets point data * */
export const vertexShaderSource =` attribute vec2 a_position; uniform vec2 u_resolution; void main() { vec2 zeroToOne = a_position / u_resolution; Vec2 zeroToTwo = zeroToOne * 2.0; Vec2 clipSpace = ZeroTotwo-1.0; gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); } `;
export const fragmentShaderSource =` precision mediump float; uniform vec4 u_color; void main() { gl_FragColor = u_color; } `;
Copy the code