{Where Am I}

Let's make some utility functions

In the last three chapters - Coordinate Spaces, Graphics Primitives and Graphics Pipeline we had a lot of theory and now its time to shift back to some code.

You must have noticed a few things in the chapters Let's draw a point and Draw Multiple Points:

Well, we are going to reduce these pain points by creating a new file named webgl-utilities.js and importing it into our HTML files before script.js from now on.

New HTML template:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body style="margin: 0">
    <canvas></canvas>
    <script src="../webgl-utilities.js"></script>
    <script src="./script.js"></script>
  </body>
</html>

I have imported the webgl-utilities.js with a ../ because I have kept it outside my working folder.

Utility function to create and compile a shader

function utilCreateShader(gl, shaderType, shaderSource) {
  const shader = gl.createShader(shaderType);
  gl.shaderSource(shader,shaderSource);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    if (shaderType == gl.VERTEX_SHADER) {
      console.error("Error in vertex shader:");
    } else {
      console.error("Error in fragment shader:");
    }
    const error = gl.getShaderInfoLog(shader);
    console.error(error);
    throw error;
  }
  return shader;
}

Args of this function:

Function calling

const vertexShader = utilCreateShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = utilCreateShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

Utility function to create and link a program


function utilCreateProgram(gl, vertexShader, fragmentShader) {
  const program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    const error = gl.getProgramInfoLog(program);
    throw error;
  }
  return program;
}

Args of this function:

Function calling

const program = utilCreateProgram(gl, vertexShader, fragmentShader);

Utility function to create and set data in the buffer

function utilCreateBuffer(gl,data) {
  const buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
  return buffer;
}

Args of this function:

Note: From now we will put any webgl utility function we make in the file webgl-utilities.js

Function calling

const pointsBuffer = utilCreateBuffer(gl,  pointsCoordinates);

Sample program using these functions ( Draw Triangle ):

//Step 1: Set the viewport
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl2");
canvas.height = window.innerHeight; // For making the canvas full screen
canvas.width = window.innerWidth; // For making the canvas full screen
gl.viewport(0, 0, canvas.width, canvas.height);

//Step 2: Write the shaders
// vertex shader
const vertexShaderSource = `#version 300 es
in vec2 a_position;
void main(){
  gl_Position = vec4(a_position,0,1);
  gl_PointSize = 30.0;
}`;

// fragment shader
const fragmentShaderSource = `#version 300 es
precision mediump float;
out vec4 color;
void main(){
  color = vec4(1,0,0,1); 
}`;

// Step 3: Compile the shaders
const vertexShader = utilCreateShader(gl, gl.VERTEX_SHADER, vertexShaderSource);

const fragmentShader = utilCreateShader(
  gl,
  gl.FRAGMENT_SHADER,
  fragmentShaderSource
);

// Step 4: Create a WebGL program
const program = utilCreateProgram(gl, vertexShader, fragmentShader);

const pointsCoordinates = [
  0, 0.5, // First point
  -0.5, -0.5, // Second point
  0.5, -0.5, // Third point
];

const a_position_location = gl.getAttribLocation(program, "a_position");
// Create Buffer
const pointsBuffer = utilCreateBuffer( gl, pointsCoordinates);
gl.vertexAttribPointer(a_position_location, 2, gl.FLOAT, false, 0, 0);

gl.enableVertexAttribArray(a_position_location)
// Step 7: Use the WebGL program
gl.useProgram(program);

// Step 8: Issue the draw call
gl.drawArrays(gl.TRIANGLES, 0, 3);

Checkout the full webgl-utilities.js