[WebGL Series] 2. Create Program object

Creation of WebGL program object

The program object consists of Vertex Shader Object and Fragment Shader Object. Therefore, creating a program object involves two parts, one is the creation of the shader object and the other is the program Creation of objects.

Overall process

  1. Create a vertex shader object
  2. Create a fragment shader object
  3. Create program object
  4. Add vertex shader and fragment shader to program
  5. Link program to webgl context
  6. Use the created program object

Creation of shader objects

The creation of a shader object consists of three steps:

  1. Create shader object
  2. Feed the shader source code into the object
  3. Compile shader

Code implementation

/**
 * Create shader object
 * @param {*} gl webgl context object
 * @param {*} type The type of shader created. The vertex shader is gl.VERTEX_SHADER and the fragment shader is gl.FRAGMENT_SHADER.
 * @param {*} source glsl source code
 */
function loadShader(gl, type, source) {<!-- -->
  //Create shader
  const shader = gl.createShader(type);
  // Send the glsl source code into the shader object
  gl.shaderSource(shader, source);
  //Compile shader
  gl.compileShader(shader);

  // Check whether the shader is compiled successfully
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {<!-- -->
    alert("An error occurred while compiling shader:" + gl.getShaderInfoLog(shader));
    // Compilation failed, delete shader
    gl.deleteShader(shader);
    return null;
  }

  return shader;
}

Interface

WebGLShader WebGLRenderingContext.createShader(type)

Create a Shader object

  • type: one of WebGLRenderingContext.VERTEX_SHADER and WebGLRenderingContext.FRAGMENT_SHADER, indicating whether a vertex shader or a fragment shader is created

void WebGLRenderingContext.shaderSource(WebGLShader shader, string source)

Set the GLSL code for the WebGLShader shader object

  • shader: WebGLShader used to set program code
  • source: string containing glsl program code

void WebGLRenderingContext.compileShader(WebGLShader shader)

Compile the GLSL shader into a binary data, which is then used by WebGLProgram

  • shader: WebGLShader, vertex shader or fragment shader

Object WebGLRenderingContext.getShaderParameter(WebGLShader shader, pname)

Returns the given shader information

  • shader: Shader object that needs to obtain information
  • pname: Specifies the attribute name of the information to be queried, which can be the following values:
    • WebGLRenderingContext.DELETE_STATUS: Identifies whether the shader has been deleted, deleted GL_TRUE, not deleted GL_FALSE
    • WebGLRenderingContext.COMPILE_STATUS: Identifies whether the shader is successfully compiled, successful GL_TRUE, unsuccessful GL_FALSE
    • WebGLRenderingContext.SHADER_TYPE: Identifies the type of shader
      • WebGLRenderingContext.VERTEX_SHADER: Vertex shader
      • WebGLRenderingContext.FRAGMENT_SHADER: fragment shader

Object WebGLRenderingContext.getShaderInfoLog(WebGLShader shader)

Get the shader information log, including warning, debug and compilation information

  • shader: Shader object that needs to obtain information

void WebGLRenderingContext.deleteShader(WebGLShader shader)

Delete the shader object provided by the parameter. If the object has been deleted, this method is invalid.

  • shader: The shader object that needs to be deleted

DOMString WebGLRenderingContext.getShaderSource(shader)

Return the shader’s source code in the form of DOMString

  • shader: WebGLShader, the shader to obtain the source code

Create shader program object

Creating a shader program object requires four steps:

  1. Create program object
  2. Bind a shader program to a shader object
  3. Link context to shader program
  4. Using shader programs

Code implementation

/**
 * Initialize shader program
 * @param {*} gl webgl context
 * @param {*} vsSource vertex shader source string
 * @param {*} fsSource fragment shader source code string
 */
function initShaderProgram(gl, vsSource, fsSource) {<!-- -->
  // Create shader object
  const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
  const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

  // Create shader program
  const shaderProgram = gl.createProgram();
  // Bind the shader program to the shader
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  
  // Link the context to the shader program
  gl.linkProgram(shaderProgram);

  // gl.validateProgram(shaderProgram);

  // Check whether the shader program is created successfully
  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {<!-- -->
    alert("Initialization shader program error:" + gl.getProgramInfoLog(shaderProgram));
    // If creation fails, delete the shader object and shader program object
    gl.deleteProgram(shaderProgram);
    gl.deleteShader(vertexShader);
    gl.deleteShader(fragmentShader);

    return null;
  }

  //Use shader program
  gl.useProgram(shaderProgram);

  return shaderProgram;
}

Interface

WebGLProgram WebGLRenderingContext.createProgram()

Initialize a WebGLProgram object

void WebGLRenderingContext.attachShader(program, shader)

Add a shader to WebGLProgram

  • program: WebGLProgram object
  • shader: WebGLShader object

void WebGLRenderingContext.linkProgram(program)

Links to the given WebGLProgram, completing the process of preparing GPU code for the program’s fragment vertex shader

  • program: WebGLProgram, the specified shader program

Object WebGLRenderingContext.getProgramParameter(program, pname)

Return program information

  • program: specified program
  • pname: Glenum, can be of the following types:
    • WebGLRenderingContext.DELETE_STATUS: GLboolean, whether it was deleted
    • WebGLRenderingContext.LINK_STATUS: GLboolean, whether the link was successful
    • WebGLRenderingContext.VALIDATE_STATUS: GLboolean, whether the last verification operation was successful
    • WebGLRenderingContext.ATTACHED_SHADERS: GLint, returns the number of added shaders. You can later use WebGLRenderingContext.getAttachedShaders() to obtain these shaders
    • WebGLRenderingContext.ACTIVE_ATTRIBUTES: GLint, returns the number of activated attribute variables in the shader. You can later use the WebGLRenderingContext.getActiveAttrib() method to obtain these variables
    • WebGLRenderingContext.ACTIVE_UNIFORMS: GLint, returns the number of activated uniform variables in the shader. You can later use the WebGLRenderingContext.getActiveUniform() method to obtain these variables
    • WebGLRenderingContext.TRANSFORM_FEEDBACK_BUFFER_MODE [WebGL2 only]: GLenum, returns the buffer mode when transform feedback is activated
      • WebGLRenderingContext.SEPARATE_ATTRIBS
      • WebGLRenderingContext.INTERLEAVED_ATTRIBS
    • WebGLRenderingContext.TRANSFORM_FEEDBACK_VARYINGS [WebGL2 only]: GLint, indicating the number of varying variables to capture in transform feedback mode
    • WebGLRenderingContext.ACTIVE_UNIFORM_BLOCKS [WebGL2 only]: GLint, indicating the number of uniform blocks containing active uniforms.

Object WebGLRenderingContext.getProgramInfoLog(program)

Obtain information in the program, including errors in the link and check for legality

  • program: WebGLProgram object

void WebGLRenderingContext.deleteProgram(program)

Deleting a program will have no effect if it has already been deleted.

  • program: WebGLProgram, the program that needs to be deleted

void WebGLRenderingContext.useProgram(program)

Add the defined program object to the current rendering state

  • program: WebGLProgram object

void WebGLRenderingContext.validateProgram(program)

Check whether the program is linked successfully and whether it can be used in the current webgl

Note that after the WebGLProgram object is successfully created, the added WebGLShader object is useless. You can call deleteShader to delete it to prevent it from occupying internal memory