# 一、绘制一个三角形

​ 之前绘制点的时候只需要一个点的数据即可,如果要绘制三角形的话,则需要三个点,这时候就需要使用缓冲区对象,向着色器传递多个点的多个数据比如坐标,颜色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
1.创建缓冲区对象
*/
const buffer = gl.createBuffer()
// gl.deleteBuffer() 删除缓冲区对象

/*
2.绑定缓冲区对象
*/
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)

/*
3.向缓冲区写入数据
*/
const vertex = new Float32Array([0.5,0.0,0.0,0.5,-0.5,0.0])
gl.bufferData(gl.ARRAY_BUFFER,vertex,gl.STATIC_DRAW)

/*
4.将缓冲区对象的值写入Attribute中
*/
/*
vertexAttribPointer(index, size, type, normalized, stride, offset)
index为顶点数据的下标,也即getAttribLocation的返回值。size指的是给顶点传入的数据大小,比如顶点的坐标需要传入四个值,如果少传入,w默认为1.0,其他默认0.0。
type为数据的类型。normalized指数据是否进行归一化,指将数据化成[-1,1]这个范围,如果数据本身就在这个范围的话,这个参数就可以是flase。
stride指两个数据的偏移量,如果数组只包括顶点的一种数据比如坐标,这里就填零,如果数组包含坐标(3),颜色(4),纹理(2)等等就填就填需要9*Fszie,Fsize = vertex.BYTES_PER_ELEMENT,offset指数据的其实偏移量,也即从Attribtue第几个开始写入。
*/
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0)

/*
5.开启Attribute变量
*/
gl.enableVertexAttribArray(a_Position)

gl.clearColor(0.0,0.0,0.0,1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.drawArrays(gl.TRIANGLES,0,3)

# 二、关于 drawArrays 的第一个参数

​ drawArrays 的第一个参数有以下 7 种

  1. GL_POINTS: 绘制点
  2. GL_LINES: 每两个点连接成一条线,如果传入的点的个数是奇数就舍弃最后一个点
  3. GL_LINE_STRIP: 两个点依次连接。
  4. GL_LINE_LOOP: 与上面不同的是这个会将最开始的点与最后的点进行连接
  5. GL_TRIANGLES: 每三个点绘制成单独的三角形,如果传入的点不是三点的倍数则会舍弃 1 或者 2 个点
  6. GL_TRIANGLE_STRIP: 绘制一组三角形,对于第 n 个三角形,如果 n 是奇数,三个顶点由 n,n+1,n+2 构成。如果 n 是偶数,三个顶点由 n+1,n,n+2 构成。
  7. GL_TRIANGLE_FAN: 绘制一组三角形,对于第 n 个三角形,由第一个顶点和 n+1,n+2 构成。

参考资料:

OpenGLES 中函数 glDrawArrays 详解 - 风过蔷薇 - 博客园 (cnblogs.com)

# 三、绘制矩形和扇形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
三种绘制矩形的方法
1.使用GL_TRIANGLE_STRIP绘制,这种方法绘制只要四个顶点
const vertex = new Float32Array([
-0.5,0.5,
-0.5,-0.5,
0.5,0.5,
0.5,-0.5
])
2.使用GL_TRIANGLE_FAN绘制,需要五个顶点
const vertex = new Float32Array([
-0.5,0.5,
-0.5,-0.5,
0.5,0.5,
0.5,-0.5,
-0.5,-0.5
])
3.使用GL_TRIANGLES绘制,需要六个顶点
const vertex = new Float32Array([
-0.5,0.5,
-0.5,-0.5,
0.5,0.5,
0.5,-0.5,
-0.5,-0.5,
0.5,0.5
])
总的来说还是第一种方法好

扇形的话就只能用GL_TRIANGLE_FAN
const vertex = new Float32Array([
0.0,0.0,
0.5,0.5,
0.0,0.7,
-0.5,0.5
])

# 四、给顶点着色器传递颜色以绘制彩色的图形

​ 渲染模型的流程 —— 首先逐顶点遍历,然后图形装配,将顶点连接。之后光栅化处理获取模型所占用的像素点,然后逐片元着色器处理每一个像素点。如果使用 varying 给顶点传入颜色,在逐片元着色器处理的时候,会根据该像素点与这片面积上的三个顶点的距离和颜色计算出该像素点的颜色,这个过程叫做内插。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
const canvas = document.getElementById('canvas')
const gl = canvas.getContext('webgl')

const vertexCode = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main(){
gl_Position = a_Position;
v_Color = a_Color;
}
`

const fragmentCode = `
precision mediump float;
varying vec4 v_Color;
void main(){
gl_FragColor = v_Color;
}
`
const vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader,vertexCode)
gl.compileShader(vertexShader)

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader,fragmentCode)
gl.compileShader(fragmentShader)

const program = gl.createProgram()
gl.attachShader(program,vertexShader)
gl.attachShader(program,fragmentShader)
gl.linkProgram(program)
gl.useProgram(program)

const a_Position = gl.getAttribLocation(program,'a_Position')
const a_Color = gl.getAttribLocation(program,'a_Color')
/*
1.创建缓冲区对象
*/
const buffer = gl.createBuffer()
// gl.deleteBuffer() 删除缓冲区对象

/*
2.绑定缓冲区对象
*/
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)

/*
3.向缓冲区写入数据
*/
const vertex = new Float32Array([
0.0,0.0,1.0,0.0,0.0,1.0,
0.5,0.5,0.0,1.0,0.0,1.0,
-0.5,0.5,0.0,0.0,1.0,1.0,
// -0.5,0.5
])
const Fsize = vertex.BYTES_PER_ELEMENT
gl.bufferData(gl.ARRAY_BUFFER,vertex,gl.STATIC_DRAW)

/*
4.将缓冲区对象的值写入Attribute中
*/
/*
vertexAttribPointer(index, size, type, normalized, stride, offset)
index为顶点数据的下标,也即getAttribLocation的返回值。size指的是给顶点传入的数据大小,比如顶点的坐标需要传入四个值,如果少传入,w默认为1.0,其他默认0.0。
type为数据的类型。normalized指数据是否进行归一化,指将数据化成[-1,1]这个范围,如果数据本身就在这个范围的话,这个参数就可以是flase。
stride指两个数据的偏移量,如果两个数据之间没有其他数据这个就填0,offset指数据的其实偏移量,也即从Attribtue第几个开始写入。
*/
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,Fsize*6,0)
gl.vertexAttribPointer(a_Color,4,gl.FLOAT,false,Fsize*6,Fsize*2)
/*
5.开启Attribute变量
*/
gl.enableVertexAttribArray(a_Position)
gl.enableVertexAttribArray(a_Color)

gl.clearColor(0.0,0.0,0.0,1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.drawArrays(gl.TRIANGLES,0,3)

参考资料:

https://ice-webgl.netlify.app/content/ 三、webgl 颜色和纹理 / 1. 绘制彩色的三角.html