1

Introduction

JavaScript WebGL basic doubts made some optimizations, and then tried to draw common two-dimensional surfaces.

The geometry in WebGL is ultimately composed of triangles, and it is more appropriate to cut in by triangles.

Draw a triangle

This is exemplary , based draw a line main changes are:

  • vertex
  • Draw primitives

vertex

The triangle has three vertices. From the basic doubt point , it is known that the coordinate system is a right-handed coordinate system. Personally, I am used to describing the order of the vertices with the center of the figure as the origin, from the first quadrant to the fourth quadrant.

  let vertices = [
    0.5, 0.5, 0.0, // 第一象限
    -0.5, 0.5, 0.0, // 第二象限
    -0.5, -0.5, 0.0, // 第三象限
  ]; // 三角形

Draw primitives

This time I draw a face, and the drawing mode in drawArrays gl.TRIANGLES . By the way, take a look at several modes of primitives.

  • gl.POINTS: draw a series of points.
  • gl.LINES: Draw a series of individual line segments, with every two points as endpoints, and the line segments are not connected. For example, if there are vertices A, B, C, D, E, F, you will get three line segments.

94-lines

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

94-line-strip

  • 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.

94-line-loop

  • gl.TRIANGLES: Draw a series of triangles, with every three points as vertices. For example, if there are 6 vertices A, B, C, D, E, F, 2 triangles will be drawn: ABC and DEF.

94-triangles

  • gl.TRIANGLE_STRIP: Used to draw triangles with shared sides. Starting from the second triangle, read one vertex at a time, and use the last two vertices in the front to form a triangle, and so on. For example, if there are 6 vertices A, B, C, D, E, F, 4 triangles will be drawn: ABC and BCD and CDE and DEF.

94-triangle-strip

  • gl.TRIANGLE_FAN: Draw a triangle with shared sides. Starting from the second triangle, read one vertex at a time, and use the first vertex and the last vertex to form a triangle, and so on. For example, if there are 6 vertices A, B, C, D, E, F, 4 triangles will be drawn: ABC and ACD and ADE and AEF.

94-triangle-fan

Implementation process

Here is a drawing triangle execution process visualization , combined with a look will help deepen the understanding.

HD processing

In the above example, there will be obvious blur and jagged on the HD screen, but it is a little different from the blur of the 2d The main difference is that WebGL needs to use the viewport method to specify the mapping transformation from the standard device to the window coordinates. For details, see the explanation article

This is the HD example .

  function WebGLHD(w = 300, h = 150) {
    const ratio = window.devicePixelRatio || 1;
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("webgl");
    // 高清屏幕模糊问题处理
    canvas.width = w * ratio; // 实际渲染像素
    canvas.height = h * ratio; // 实际渲染像素
    canvas.style.width = `${w}px`; // 控制显示大小
    canvas.style.height = `${h}px`; // 控制显示大小
    context.viewport(0, 0, context.canvas.width, context.canvas.height);
  }

Draw rectangle

As mentioned earlier, the 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, // 第一个三角形
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0,
    0.5, 0.5, 0.0, // 第二个三角形
  ]; // 矩形

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

Index buffer object

The full name of the index buffer object is Index Buffer Object (IBO), which reuses existing data through indexing.

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

  • data
  • buffer
  • draw

data

Only 4 vertex position data is enough, and the common data uses index instead.

  const vertices = [
    0.5, 0.5, 0.0, // 第 1 个顶点
    -0.5, 0.5, 0.0, // 第 2 个顶点
    -0.5, -0.5, 0.0, // 第 3 个顶点
    0.5, -0.5, 0.0, // 第 4 个顶点
  ]; // 矩形

The index data is related to the primitive drawing mode suggested above.

When the drawing mode is gl.TRIANGLES , the two triangles are independent, and the index data is as follows:

const indexData = [
  0, 1, 2, // 对应顶点位置数据中 1、2、3 顶点的索引
  0, 2, 3, // 对应顶点位置数据中 1、3、4 顶点的索引
]

When the drawing mode is gl.TRIANGLE_STRIP , use the two vertices at the end of the previous triangle to construct a triangle:

const indexData = [
  1, 0, 2, 3 // 绘制时,先取索引 1、0、2 的位置数据绘制第一个三角形,然后再取索引 0、2、3 的位置数据 绘制第二个三角形
]

When the drawing mode is gl.TRIANGLE_FAN , use the first vertex, a vertex at the end of the previous triangle, and the newly read vertex to construct a triangle:

const indexData = [
  0, 1, 2, 3 // 绘制时,先取索引 0、1、2 的位置数据绘制第一个三角形,然后再取索引 0、2、3 的位置数据 绘制第二个三角形
]

buffer

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

/**
 * 缓冲索引数据
 * @param {*} gl WebGL 上下文
 * @param {*} data 索引数据
 */
function setIndexBuffers(gl, data) {
  // 创建空白的缓冲对象
  const buffer = gl.createBuffer();
  // 绑定目标
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
  // WebGL 不支持直接使用 JavaScript 原始数组类型,需要转换
  const dataFormat = new Uint16Array(data);
  // 初始化数据存储
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, dataFormat, gl.STATIC_DRAW);
}

draw

The index buffer object is used, and drawElements method needs to be used instead of drawArrays . This method has an type parameter 061bfdcae2f81a, which refers to the type of index buffer data. The following values are available:

  • gl.UNSIGNED_BYTE
  • gl.UNSIGNED_SHORT

The previous buffer index data type is converted to Uint16Array , and 061bfdcae2f879 should be used gl.UNSIGNED_SHORT .

Examples of the three methods are as follows:

Reference


XXHolic
363 声望1.1k 粉丝

[链接]