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.
- We want to generate or find the canvas object;
- Initialize WebGLRenderingContext, WebGLProgram (GL and Program);
- Get model grid vertex data
- 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