JavaScript WebGL draws a face

Posted by LinuxForce on Sun, 26 Dec 2021 06:02:06 +0100

Introduction

JavaScript WebGL Basics After some optimization, we try to draw common two-dimensional faces.

The geometry in WebGL is ultimately composed of triangles, which is more suitable for cutting in.

Draw triangle

This is Example , based on Draw a line The main changes are:

  • vertex
  • Drawing elements

vertex

A triangle has three vertices at Basic doubts I know that the coordinate system is a right-hand coordinate system. I am used to describing the order of vertices, taking the graphics center as the origin, from the first quadrant to the fourth quadrant.

  let vertices = [
    0.5, 0.5, 0.0, // first quadrant
    -0.5, 0.5, 0.0, // Beta Quadrant 
    -0.5, -0.5, 0.0, // third quadrant 
  ]; // triangle

Drawing elements

This time it's a face, drawArrays The drawing mode changes to GL TRIANGLES . By the way, look at several modes of elements.

  • gl.POINTS: draws a series of points.
  • gl.LINES: draw A series of separate line segments, with each two points as the end points, and the line segments are not connected. For example, if you have vertices A, B, C, D, E and F, you will get three line segments.

  • gl.LINE_STRIP: draw a series of line segments, the previous point connecting the next point.

  • gl.LINE_LOOP: draw a series of line segments. The previous point is connected to the next point, and the last point is connected to the first point.

  • gl.TRIANGLES: draw A series of triangles with three points as vertices. For example, if there are six vertices A, B, C, D, E and F, two triangles will be drawn: ABC and DEF.

  • gl.TRIANGLE_STRIP: used to draw triangles with shared edges. Start with the second triangle, read one vertex at A time, and use the last two vertices in front to form A triangle, and so on. For example, if there are six vertices A, B, C, D, E and F, four triangles will be drawn: ABC and BCD, CDE and DEF.

  • gl.TRIANGLE_FAN: draw triangles with shared edges. Start with the second triangle, read one vertex at A time, and use the first vertex and the last vertex before to form A triangle, and so on. For example, if there are six vertices A, B, C, D, E and F, four triangles will be drawn: ABC and ACD, ADE and AEF.

Execution process

Here's one Drawing triangle execution process visualization , it helps to deepen understanding.

HD processing

In the above example, there will be obvious blur and sawtooth in the HD screen, but it is somewhat different from dealing with the blur of 2d context. The main difference is that WebGL needs to use viewport Method specifies the mapping transformation from the standard device to the window coordinates. For details, see This article The explanation inside.

This is HD example.

  function WebGLHD(w = 300, h = 150) {
    const ratio = window.devicePixelRatio || 1;
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("webgl");
    // HD screen blur problem handling
    canvas.width = w * ratio; // Actual rendered pixels
    canvas.height = h * ratio; // Actual rendered pixels
    canvas.style.width = `${w}px`; // Control display size
    canvas.style.height = `${h}px`; // Control display size
    context.viewport(0, 0, context.canvas.width, context.canvas.height);
  }

draw rectangle

As mentioned earlier, geometry in WebGL is ultimately composed of triangles, which need to be decomposed into multiple triangles when drawing polygons.

This is Example , a rectangle can be divided into two triangles:

  let vertices = [
    0.5, 0.5, 0.0,
    -0.5, 0.5, 0.0,
    -0.5, -0.5, 0.0, // First triangle
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0,
    0.5, 0.5, 0.0, // Second triangle
  ]; // rectangle

It can be found that one edge is public. At this time, the buffer object can be indexed to reduce redundant data.

Index buffer object

The full name of Index Buffer Object is Index Buffer Object (IBO), which reuses existing data by index.

Based on the example above, the main changes are as follows:

  • data
  • buffer
  • draw

data

Only 4 vertex position data is enough, and the public data is replaced by index.

  const vertices = [
    0.5, 0.5, 0.0, // 1st vertex
    -0.5, 0.5, 0.0, // 2nd vertex
    -0.5, -0.5, 0.0, // 3rd vertex
    0.5, -0.5, 0.0, // 4th vertex
  ]; // rectangle

The index data is related to the element drawing mode prompted above.

The drawing mode is GL Triangles, the two triangles are independent, and the index data is as follows:

const indexData = [
  0, 1, 2, // Corresponding to the index of 1, 2 and 3 vertices in the vertex position data
  0, 2, 3, // Corresponding to the index of 1, 3 and 4 vertices in the vertex position data
]

The drawing mode is GL TRIANGLE_ When strip, use the two vertices at the end of the previous triangle to build a triangle:

const indexData = [
  1, 0, 2, 3 // When drawing, first take the position data of indexes 1, 0 and 2 to draw the first triangle, and then take the position data of indexes 0, 2 and 3 to draw the second triangle
]

The drawing mode is GL TRIANGLE_ In fan, the triangle is constructed by using the first vertex, the vertex at the end of the previous triangle, and the newly read vertex:

const indexData = [
  0, 1, 2, 3 // When drawing, first take the position data of indexes 0, 1 and 2 to draw the first triangle, and then take the position data of indexes 0, 2 and 3 to draw the second triangle
]

buffer

The index data needs to be buffered to the corresponding variable before it can be used.

/**
 * Buffer index data
 * @param {*} gl WebGL context
 * @param {*} data Index data
 */
function setIndexBuffers(gl, data) {
  // Create a blank buffer object
  const buffer = gl.createBuffer();
  // Bind target
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
  // WebGL does not support the direct use of JavaScript original array types, which requires conversion
  const dataFormat = new Uint16Array(data);
  // Initialize data store
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, dataFormat, gl.STATIC_DRAW);
}

draw

The index buffer object is used, which needs to be used drawElements Method to replace drawArrays . This method has one more type parameter, which refers to the type of index buffer data. The following values can be taken:

  • gl.UNSIGNED_BYTE
  • gl.UNSIGNED_SHORT

Previously, the buffered index data type is converted to Uint16Array, and GL. 0 should be used here UNSIGNED_ SHORT .

Examples of the three methods are as follows:

reference material

Topics: Javascript Front-end html5 css webgl