Skip to content

Instantly share code, notes, and snippets.

@ryancat
Last active March 27, 2020 16:55
Show Gist options
  • Save ryancat/3fe34999bd812b6e9cb4c3dd04644239 to your computer and use it in GitHub Desktop.
Save ryancat/3fe34999bd812b6e9cb4c3dd04644239 to your computer and use it in GitHub Desktop.
Notes taken from learning webgl related topics.

Webgl related notes

Resources are referenced from the following links:

Summary

  • webgl is a state machine and a graphic pipeline. It holds an internal state and allow user update them.
  • When ready to render, there are a handful of methods webgl provides to 'clear' the viewport, with the current internal state defined.
  • We are always drawing 3D object in canvas using webgl.
  • Nearly all webgl APIs are for setting up the webgl state. After that, you will need to call pairs of functions (or programs) with vertex shader and fragment shader to execute the draw methods.
  • WebGL only cares about 2 things: clipspace coordinates and colors. Your job as a programmer using WebGL is to provide WebGL with those 2 things. You provide your 2 "shaders" to do this. A Vertex shader which provides the clipspace coordinates and a fragment shader that provides the color. ref
  • There are essentially two steps for webgl to draw anything:
    • Init phase (prepare buffers). You need to prepare model buffers and bind model data in them. You need to also init shaders to generate program.
    • Draw phase (read buffers). You need to take shader program and matrices (model matrix, projection matrix, model view matrix) from buffers as your input, to call one of the webgl draw methods to draw all the pixels

Notes and tricks

  • Common procedure of using webgl is as following:
    • Detect webgl in executing environment (feature detection)
    • Set webgl viewport dimension so that webgl knows how to convert the clipspace to pixels
    • Mutate webgl internal states
    • clear or other method triggers rendering
  • Detecting webgl can be done with var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); and check gl. The difference between webgl context and experimental-webgl context can be found here. Basically experimental-webgl will be deprecated.
  • Setting canvas dimension (width and height) will automatically set the webgl drawing buffer dimensions in init phase. However after that you need to update the size and viewport if you change the canvas dimension. See this great article for details.
  • You should always use CSS to set the display size for canvas, and use clientWidth and clientHeight to set the actual pixel size in JS. This is the most flexible way to control dimensions.
  • For high-definition DPI display or Retina display, use window.devicePixelRatio to make sure the actual pixel dimensions are the same to display dimensions set by CSS.
  • It's a common optimization in games to actually render less pixels than are displayed and let the GPU scale them up. ref
  • Unlike browser window or canvas, the vertical position in webgl is measured from bottom to top.
  • Colors in webgl go from 0 to 1.
  • There are two shader functions/programs runs when drawing webgl content: vertex shader and fragment shader. On a high level, vertex shader defines the geometry of the 3D object (by rasterizing the states), and fragment shader defines the colors, lights, textures on the 3D object (by applying them on each pixel).
  • In shader functions, we have the following data types
    • attribute and buffer: Similar to data view and array buffer in JS
    • uniform: Similar to global variables in JS
    • texture: Similar to array variable in JS to hold data you can randomly access. For example imageData
    • varying: An adaptor from vertex shader to fragment shader
  • One typical workflow for shader program is ref
    • Initialization phase
      • create webgl context from canvas
      • create vertex shader and fragment shader programs (most likely in string format)
      • create buffer and bind it to webgl
      • bind data to buffer
    • Render phase
      • resize canvas to display size
      • resize the viewport so that clipspace can convert to pixel space
      • clear canvas to prepare for rendering
      • tell webgl to use the program
      • get the attribute location and enable it
      • bind vertex attribute pointer and tell webgl how to set value from buffer
      • tell webgl how to draw and execute the draw function

List of commonly used states and methods

States

  • gl.COLOR_BUFFER_BIT ref: webgl constant indicates the buffers currently enabled for color writing.
  • gl.SCISSOR_TEST ref: Scissoring operation. After gl.enable(gl.SCISSOR_TEST), you can call gl.scissor(x, y, width, height) to define the scissoring area, which will be actually affected by following clear commands.

Methods

  • gl.clear(mask) ref: Clear the drawing buffer to the preset values that are indicated by mask.
  • gl.clearColor(r, g, b, a) ref: Clear the drawing buffer with given color.
  • gl.colorMask(r, g, b, a) ref: Set the color mask with booleans on red, green, blue and alpha channels. When a channel mask is off, the color in that channel won't be rendered even it's set in internal state.
  • gl.scissor(x, y, width, height) ref: Define scissoring area for further rendering. Note that y is from bottom up.
  • gl.createShader(type): Create a vertex or fragment shader.
  • gl.shaderSource(shader, source): Set the source for a given shader.
  • gl.compileShader(shader): Compile the source code for given shader.
  • gl.getShaderParameter(shader, parameterName): Get the shader's parameter by given parameter name.
  • gl.getShaderInfoLog(shader): Get the shader's log for debugging.
  • gl.deleteShader(shader): Dispose the shader from webgl context.
  • gl.createProgram(): Create a program.
  • gl.attachShader(program, shader): Attach a shader into program. A program is composited by a vertex shader and a fragment shader.
  • gl.linkProgram(program): Linking program which will generate executable internally.
  • gl.getProgramParameter(program, parameterName): Get the program's parameter by given parameter name.
  • gl.getProgramInfoLog(program): Get the program's log for debugging.
  • gl.deleteProgram(program): Dispose the program from webgl context.
  • gl.getAttribLocation(program, attributeName): Get the program's attribute name.
  • gl.createBuffer(): Create a buffer for webgl. webgl uses buffer to store binary data.
  • gl.bindBuffer(bufferType, buffer): Bind a buffer to the bind point for webgl, so that consumer can pass data into webgl program.
  • gl.bufferData(bufferType, stronglyTypedData, hintEnumOnHowToUseData): Pass the data into the buffer that of the bufferType type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment