前言
不同于SVG的声明式绘图,Canvas的指令式绘图,WebGL 利用了 GPU 并行处理绘制图片。这种绘图模式直接深入底层GPU、内存等,所以比较复杂,但功能强大。适合处理数据量大、视觉效果要求高的场景。
图形绘制过程
- 数据经过 CPU 处理,成为具有特定结构的几何信息。
- 这些信息会被送到 GPU 中进行处理。在 GPU 中要经过两个步骤生成光栅信息。
- 光栅信息会输出到帧缓存中,最后渲染到屏幕上。
基本概念
- 图元:WebGL 可以直接处理的图形单元,包括点、线段、三角形等等。其他非图片的图形必须转换成图元才能被处理。
- 光栅:构成图像的像素阵列。
- 帧缓存:在绘图过程中,像素信息被存放于帧缓存中,帧缓存是一块内存地址。
- 光栅化:从顶点着色器和图元提取像素点给片元着色器执行代码的过程
着色器(Shader)
WebGL的着色程序有2个,一个是顶点着色器,一个是片元着色器
顶点着色器(Vertex Shader)
负责处理图形的顶点数据。可以改变顶点的信息(坐标、法线方向、材质等)。
主要作用:
- 通过gl_Position设置顶点
- 定义varying变量,向片元着色器传递数据
片元着色(Fragment Shader)
负责处理光栅化后的信息,就是对指定图元中的像素点着色。
光照效果
由光源、介质(物体的材质)和反射类型决定。
常用光源分4种:环境光(Ambient Light)、平行光(Directional Light)、点光源(Positional Light)和聚光灯(Spot Light)。
反射类型分2种:漫反射和镜面反射。
切线空间(Tangent Space)
切线空间是一个特殊的坐标系,它是由几何体顶点所在平面的 顶点uv 坐标和法线构成的。
切线空间的三个轴,一般用 T (Tangent)、B (Bitangent)、N (Normal) 三个字母表示,所以切线空间也被称为 TBN 空间。其中 T 表示切线、B 表示副切线、N 表示法线。
构建 TBN 矩阵我们有两个方法,一个是根据几何体顶点数据来计算切线(Tangent)、副切线(Bitangent),然后结合法向量一起构建 TBN 矩阵。另一个方法是使用偏导数来计算,这样我们就不用预先在顶点中计算 Tangent 和 Bitangent 了。
法线贴图
具体来说,法线贴图是用一张图片来存储表面的法线数据。这张图片叫做法线纹理,它上面的每个像素对应一个坐标点的法线数据。根据法线纹理中保存的法向量数据以及 TBN 矩阵,将实际的法线计算出来,然后用实际的法线来计算光照的反射。
z-fighting
在 WebGL 中绘制 3D 物体开启了深度检测之后,引擎会自动计算 3D 物体的深度,让离观察者很近的物体面,把离观察者比较远和背对着观察者的物体面遮挡住。那具体是怎么遮挡的呢?其实是根据物体在相机空间中的 z 坐标来判断的。
但有一种特殊情况,就是两个面的 z 坐标相同,又有重叠的部分。这时候,引擎就可能一会儿先渲染 A 面,过一会儿又先去渲染 B 面,这样渲染出来的内容就出现了“闪烁”现象,这就是 z-fighting。
把坐标设置的不完全相同是解决z-fighting的方法之一。