学习目标:
- 掌握WebGl基础知识
学习内容:
例如:
- canvas画布知识
- 类型化数组
- 着色器的基础知识
1.canvas画布知识
1.1.获取渲染上下文
HTMLCanvasElement.getContext()方法用于返回绘图的上下文对象,绘图上下文对象是2D上下文还是3D上下文取决于传入的参数。
- getContext(‘2d’):创建一个CanvasRenderingContext2D 二维的渲染上下文对象
- getContext(‘webgl’):创建一个WebGLRenderingContext三维的渲染上下文对象
1.2.画布宽高设置
Canvas画布默认会在页面中占据一块位置,这块位置的大小默认是300*150。虽然canvas是一个元素,可以通过CSS样式属性来设置这个元素的宽和高,但是通常不推荐使用CSS样式属性来设置画布的宽高。因为使用CSS属性只是影响画布元素在网页上显示的尺寸,并不会改变画布的分辨率。即使使用CSS样式改变了画布的大小,但是画布的分辨率还是默认的300 * 150,在显示上的缩放会导致绘制的图形失真或者模糊。
Canvas有两个属性:width 和 height,这两个属性定义了画布的实际尺寸,也就是会更改画布绘图的分辨率。
使用HTML属性来设置宽高可以:
- 避免图像失真:使用 HTML属性来设置画布的宽度和高度确保了绘图操作是在正确的分辨率下进行的。如果使用CSS设置尺寸,画布的分辨率不会改变,绘制的图像可能会被拉伸或压缩,从而导致失真。
- 更好地控制分辨率:在高分辨率设备(如 Retina 显示屏)上,通过HTML属性设置宽度和高度可以确保绘制的内容具有足够的像素密度,避免模糊。
- 一致的绘图结果:HTML属性设置的宽度和高度确保了绘制操作的坐标系统是一致的。这对于复杂的绘图操作或需要精确控制图像位置和尺寸的场景尤其重要。
2.类型化数组
JavaScript的类型化数组是一种用于处理和操作二进制数据的对象,类型化数组在处理WebGL等需要高性能和大数据量操作的应用中非常有用。
类型化数组和普通的JavaScript数组不同,类型化数组的每一个元素都是同一类型的二进制数据,这种类型在创建数组时就已经确定了。
作用:常用在处理图像数据、音频数据、视频数据这些方向。对应的API有:WebGL、Canvas API、 WebRTC、File API。
2.1类型化数组和普通数组的区别
内存管理方面
- 类型化数组:类型化数组直接在一个连续的内存块上操作。这意味着所有的数据都紧密地存储在一个固定大小的缓冲区中,数据访问和修改非常高效,因为它们不需要像普通数组那样进行额外的内存引用或分配。
- 普通数组:普通数组是动态的,可以容纳不同类型的数据。这使得它们非常灵活,但由于需要动态调整大小和存储多种类型的数据,它们的内存管理和访问速度比类型化数组要慢。
数据类型方面
- 类型化数组:类型化数组是强类型的,数组中的每个元素都必须是特定类型的值(如Int8、Uint8、Float32等)。这种类型的严格性确保了数据的一致性和高效的内存使用。
- 普通数组:普通数组是弱类型的,可以包含任意类型的值(如数字、字符串、对象等)。这种灵活性虽然方便,但会导致在进行大最数据处理时效率较低。
操作方法方面
- 类型化数组:类型化数组支持一组专门的方法,用于在二进制数据块上进行高效操作。它们不继承自Array.prototype,因此不具备一些普通数组的方法(如 push、 pop、splice等)
- 普通数组:普通数组继承自Array.prototype,拥有丰富的数组操作方法,可以灵活地添加、删除、修改和遍历数组元素。
2.2 类型化数组有哪些
- Int8Array : 8位有符号整数,每个元素占1字节
- Uint8Array :8位无符号整数,每个元素占1字节。
- Uint8ClampedArray :8位无符号整数(固定值,溢出时值被截断),每个元素占1字节。
- Int16Array :16位有符号整数,每个元素占2字节。
- Uint16Array : 16位无符号整数,每个元素占2字节。
- Int32Array : 32位有符号整数,每个元素占4字节。
- Uint32Array:32位无符号整数,每个元素占4字节。
- Float32Array: 32位IEEE 754浮点数,每个元素占4字节。
- Float64Array:64位 IEEE 754浮点数,每个元素占8字节。
2.3 创建和使用类型化数组
类型化数组每一种都有对应的构造函数,要创建类型化数组实例就需要使用new操作符实例化构造函数。
// 创建一个包含10个32位整数的类型化数组
const intArray = new Int32Array(10)
// 向类型化数组中填充数据
for(let i=0;i<intArray.length;i++){
intArray[i] = i*2
}
类型化数组在WebGL中得到了广泛的作用,使用也是非常频繁。比如在定义图形的顶点可以使用类型化数组定义,如下:
const vertices = new Float32Array([
0.0, 1.0, // 第一个顶点的坐标(x=0.0,y=1.0)
-1.0, -1.0, // 第二个顶点的坐标(x=-1.0,y=-1.0)
1.0, -1.0, // 第三个顶点的坐标(x=1.0,y=-1.0)
])
内部项两两一组作为一个点的x坐标和y坐标,上面代码是定义了一个三角型的三个顶点的坐标。
3.着色器的基础知识
GLSL (OpenGL Shading Language)是一种用于编写图形着色器的编程语言。着色器是用于在图形处理单元(GPU)上执行特定图形处理任务的程序。通俗讲,着色器是画点的工具,一个图形是由无数个点组成的,每个点都有其自己的颜色。
3.1着色器的类型
一个着色器就是一个绘制东西到屏幕上的函数,着色器有顶点着色器和bibianbian’yubian’yuanbian’yubianbipipianpian’yupian’yuan片源着色器。
-
顶点着色器:处理每个顶点的属性,如位置、法线、纹理坐标等。它的主要任务是将顶点从对象坐标系转换到屏幕坐标系,并传递其他顶点属性给片源着色器。
-
片源着色器:处理每个像素的颜色。它接收来自顶点着色器插值后的数据,并最终决定每个像素的颜色。
3.2 着色器的语法
在HTML中,如果你想把着色器代码直接写在
<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex"></script>
<!-- 片源着色器 -->
<script id="fragment-shader" type="x-shader/x-fragment">
</script>
数据类型:
- 基本数据类型:float, int, bool
- 向量类型:
1.vec2, vec3, vec4(浮点型)
2.ivec2, ivec3, ivec4(整数型)
3.bvec2, bvec3, bvec4(布尔型) - 矩阵类型: mat2, mat3, mat4
- 采样器类型: sampler2D, samplerCube (用于纹理采样)
变量修饰符:
用于指定变量的作用域、生命周期和用途。不同的修饰符在顶点着色器和片源着色器中起到不同的作用。
- attribute:用于顶点着色器,定义从顶点缓冲区传入的变量(仅在顶点着色器中使用)。
- uniform:定义在整个渲染过程中保持不变的变量,常用于传递变换矩阵、光照参数等。
- varying:用于在顶点着色器和片源着色器之间传递插值数据。
内置变量: - 顶点着色器内置变量:
1.gl_Position 顶点的变换后位置
2.gl_PointSize大小 - 片源着色器内置变量:
1.gl_FragColor:片源的最终颜色。
函数: - 常用数学函数:sin, cos, tan, pow, exp, log, sqrt, abs, min, max, radians
- 向量函数: dot, cross, normalize, length, distance
- 纹理采样函数:texture2D, textureCube
定义精度: precision 关键字用于声明变量的默认精度。
GLSL支持三种不同的精度修饰符:
1.highp(高精度):通常用32位表示,适用于需要高精度的计算,如位置计算、复杂的物理效果等。
2.mediump(中精度):通常用16位表示,适用于需要中等精度但不需要高精度的计算,如纹理坐标。
3.lowp(低精度):通常用10位表示,适用于对精度要求最低的计算,如颜色值。
precision lowp float;
主函数:着色器必须有一个主函数 void main() , 它是入口。
void main(){
gl_Position = vec4(aPosition, 0.0, 1.0) // 把aPosition这个二维向量添加两个值并变为四维向量赋值给gl_Position
}
总结
本篇文章讲解了学习WebGL的一些前置知识,即canvas画布知识,类型化数组以及着色器的基础知识,后续文章会持续更新。