文档: https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API

webGL是什么

WebGL(Web图形库)是Web上3D图形的新标准,旨在渲染2D图形和交互式3D图形。
webGL是js的一个API,它可以在浏览器中渲染高性能的2D和3D图形。
WebGL,全称Web Graphics Library,是一种使用JavaScript编写的、基于OpenGL ES 2.0的3D图形库,为HTML5 Canvas提供了硬件加速的3D渲染功能。WebGL可以实现高效、流畅的3D场景渲染,可以让开发者在浏览器中创建交互式的3D游戏、数据可视化、地图等应用。

webGL中的数据类型

WebGLRenderingContext

WebGLRenderingContext对象的数据类型如下表所示:

类型web接口数据类型描述
GLenmumunsigned long用于枚举
GLboolenboolean布尔类型
GLbitfieldunsigned long一个位字段(bit field),用于存储逻辑位(bit)
Gbytebyte八位,一个字节,表示的是有符号的整数
GLshortshort十六位,两个字节,表示的是有符号的整数
GLintlong三十二位,四个字节,表示有符号的整型数
GLsizeilong用来描述尺寸,例如,会话缓冲 drawing buffer 地宽度和高度
GLintptrlong long用来表示指针的特殊类型。
GLsizeiptrlong long用来表示指针的特点书类型
GLubyteoctet八位,一个字节表示的是无符号的整数
GLushortunsigned short十六位, 两个字节,表示无符号的整数
GLuintunsign long三十二位,四个字节表示有符号的整数
GLfloatunrestricted float三十二位的IEEE标准的浮点数
GLclampfunrestricted float限制32位IEEE浮点数

WebGL2RenderingContext

WebGL2RenderingContext包含WebGLRenderingContext对象的所有数据类型,并且包含如下数据类型:

类型web接口数据类型描述
GLint64long long六十四位有符号整数

WebGL的特点

  • 硬件加速:WebGL使用GPU的加速能力,可以快速、流畅地渲染3D场景。
  • 跨平台:WebGL是Web标准,可以跨平台运行在各种设备上,包括PC、手机、平板等。
  • 动态渲染:WebGL可以在运行时动态生成、修改3D场景,支持高度交互性。
  • 开放标准:WebGL是由Khronos Group制定的开放标准,具有完整的API文档,开发者可以根据文档编写对应的代码。

WebGL的用途

  • 游戏开发:WebGL可以在浏览器中创建高质量、流畅的3D游戏,比如《一起来捉妖》等。
  • 数据可视化:WebGL可以用于大数据的可视化展示,可以将复杂的数据变成图形化的形式,让用户更容易理解。
  • 虚拟现实:WebGL可以实现360度全景图像的展示,可以让用户感受到身临其境的虚拟现实体验。
  • 地图展示:WebGL可以用于地图的展示,可以实现3D建筑的展示、路线规划、交通流量等功能。

WebGL技术栈

  • OpenGL ES:WebGL是基于OpenGL ES 2.0标准开发的,需要掌握OpenGL ES的基础知识。
  • Three.js:Three.js是一个优秀的WebGL渲染引擎,提供了丰富的API,可以简化WebGL开发。
  • WebGLInspector:WebGLInspector可以帮助开发者调试WebGL程序,可以查看WebGL状态、着色器源码等信息。
  • GLSL:GLSL是WebGL的着色器语言,需要掌握如何编写和调试GLSL着色器。

WebGL图元

WebGL 的基本图元包含点、线段、三角形,而三角形又分为三类:基本三角形、三角行带、三角形扇。

  • 基本三角形:
    依照顶点顺序,每三个顶点构成一个三角形,多余的点不再连接。
    在这里插入图片描述

  • 三角形带:
    共用一条带上的顶点组成新的三角形,从而形成三角形带。每个顶点和前两个顶点相连形成三角形。
    在这里插入图片描述

  • 三角形扇:
    以一个顶点为中心,三角形呈扇形排列,共用两个顶点的三角形扇。以第一个点做原点,每个顶点都连接着第一个顶点和他的前一个顶点。
    在这里插入图片描述

WebGL的常量

WebGL提供了一些常量,这些常量经常作为函数的参数或者函数的返回值使用。
WebGL的常量挂载在WebGL的两个渲染上下文函数中,我们通过gl.常量名的格式访问WebGL的常量。

清除缓存相关常量

清除缓存的相关常量是为清除缓存的函数 WebGLRenderingContext.clear()作参数的,有如下取值:

常量名称说明
DEPTH_BUFFER_BIT0x00000100传递給clear来清除深度缓冲区
STENCIL_BUFFER_BIT0x00000400传递给 clear 来清除当前模板缓冲区。
COLOR_BUFFER_BIT0x00000400传递给clear来清除颜色缓冲区

指定图形渲染方式相关常量

指定图形渲染方式的相关常量主要作为 WebGLRenderingContext.drawElements()WebGLRenderingContext.drawArrays() 的参数。

常量名称说明
POINTS0x0000画点
LINES0x0001画线段,两点之间使用线段进行连接
LINE_LOOP0x0002画回路,每两个点之间被当成一条独立的线段,线段首尾相连
LINE_STRIP0x0003画一个从第一个定点到最后一个顶点相连的线段
TRIANGLES0x0004每三个顶点创建一个独立的三角行
TRIANGLES_STRIP0x0005画一组相连的三角形带
TRIANGLE_FAN0x0006画一组相连的三角形扇

获取 GL 参数信息得相关常量

传递给 WebGLRenderingContext.getParameter() 的常量,用以指定要返回的信息

常量名称说明
BLEND_EQUATION0x8009传递给getParameter以获取当前的RGB混合函数
BLEND_EQUATION_RGB0x8009和BLEND_EQUATION功能类似,用于获取当前的RGB混合函数
BLEND_EQUATION_ALPHA0x883D传递给getParameter以获取当前的alpha函数
BLEND_DST_RGB0x80C8传递给getParameter以获取当前目标的RGB混合函数
BLEND_SRC_RGB0x80C9传递给getParamter以获取当前源的RGB混合函数
BLEND_DST_ALPHA0x80CA传递给getParamter以获当前目标的alpha混合函数
BLEND_ SRC_ALPHA0x80CB传递給getParamter以获取当前源的alpha混合函数
BLEND_COLOR0x8005传递给getParamter以获取当前的混合颜色
ARRAY_BUFFER_BINDING0x8894传递給getParamer 获取数组缓冲区绑定
ELEMENT_ARRAY_BUFFER_BINDING0x8895传递給getParamer 获取当前数组元素缓冲区
LINE_WIDTH0x0B21传递给getParamer获取当前的LineW.idth
ALIASED_POINT_SIZE_RANGE0x0B21传递给getParamer获取使用gl.POINTS绘制的点的大小
ALASED_LINE_WIDTH_RANGE0x846E传递给getParams得到一条线的可用宽度范围。返回一个长度为2的数组。其中低值为0,高值为1
CULL_FACE_MODE0x0B45传递给getParameter获取当前的cullFace值。应当返回FRONT,BACK, FRONT_AND_BACK
FRONT_FACE0x0B46传递給getParamter已确定当前的frontFace的值。应该为CW或CCW
DEPTH_RANGE0x0B70传递给geParameter返回长度为2的浮点数数组,以表示当前深度范围
DEPTH_WRITEMASK0x0B72传递给getParamter确定是否启用深度缓冲区写入操作
DEPTH_CLEAR_VALUE0x0B73传递给getParamter确定当前的深度清除值
DEPTH_FUNC0x0B74传递给getParamter获取当前的深度函数。返回NEVER、ALWAYS、LESS、EQUAL、GREATAER、GEQUAL、NOTEQUAL
STENCIL_CLEAR_VALUE0x0B91传递给getParamter获取将消除的模板值。
STENCIL_FUNC0x0B92传递给getParmeter获取当前的模板函数。返回NEVER,ALWAYS,LESS,EQUAL,LEQUAL,GREATER,GEQUAL或NOTEQUAL
STENCIL_FAIL0x0B94传递给getParamter 获取当前模板的失效函数。应该返回 KEEP ,RELOACE,INCR,DECR,INVERT,INCR_WRAP,或 DECR_WRAP
STENCIL_PASS_DEPTH_FAIL0x0B95如果深度缓冲区测试失败,则传递给getParameter获取当前模板的失败函数。应返回KEEP ,RELOACE,INCR,DECR,INVERT,INCR_WRAP,或 DECR_WRAP
STENCIL_PASS_DEPTH_PASS0x0B96如果深度缓冲区测试通过,则传递给getParameter获取当前模板的失败函数 。应返回KEEP ,RELOACE,INCR,DECR,INVERT,INCR_WRAP,或 DECR_WRAP
STENCIL_REF0x0B97传递给getParameter获取用于模板测试的参考值
VIEWPORT0x0BA2返回带有当前视口尺寸四个元素
SCISSOR_BOX0x0C10返回带有当前裁剪盒子尺寸的四个元素

WebGL的展示模型

webGL的展示原理是:WedGL空间中的点和多边形的个体转换由基本的转换矩阵(平移、缩放、旋转)处理。可以将这些矩阵组合在一起并以特殊方式分组,以使启用预渲染复杂的3D场景。这些组合成的矩阵最终将原始数据类型移动到一个称为裁剪空间的特殊坐标空间中。这个特殊空间是一个中心点位于(0,0,0),角落范围在(-1,-1,-1)到(1,1,1)之间2个单位宽的立方体。该裁剪空间被压缩到一个二维空间并栅格化为图像。

裁剪空间

在webGL程序中,数据通常上传到具有自己的坐标系统的GPU(视觉处理器)上,然后顶点着色器将这些点转换到一个称为裁剪空间的特殊坐标系上。延展到裁剪空间之外的任何数据都会被裁减并且不会被渲染。如果一个三角形超出了该空间的边界,则将其裁剪成新的三角形,并且仅仅保留新的三角形在裁剪空间中的部分。
在这里插入图片描述
它是一个角在 (-1, -1, -1),对角在 (1, 1, 1),中心点在 (0, 0, 0) 的每边 2 个单位的立方体。裁剪空间使用的这个两个立方米坐标系称为归一化设备坐标(NDC)

三种矩阵

  • 模型矩阵,它定义了如何获取原始数据模型数据并将其在3D世界空间中移动。
  • 投影矩阵用于将世界坐标空间转换成裁剪空间坐标。常用的投影矩阵(透视矩阵)用于模拟充当3D世界中观看者的替身的典型相机的效果。
  • 视图矩阵负责移动场景中的对象以模拟相机位置的变化,改变观察者当前能够看到的内容。

齐次坐标

“齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易用于进行仿射(线性)几何变换。”—— F.S.Hill, JR。
过齐次坐标的理解可以看齐次坐标1 齐次坐标2

概念

简单来说齐次坐标是为了解决投影空间的问题诞生的,在传统的笛卡尔坐标系中,我们认为两条平行线永远不可能相交,但是在投影空间中两条平行线在无穷远处是相交的,此时笛卡尔坐标系就无法表示了。齐次坐标是用N+1个数来表示N维坐标的一种方式。图形和几何学的计算在投影空间中成为可能。
其中笛卡尔坐标和齐次坐标的转换规则如下:

  • 从普通坐标转换成齐次坐标时
    如果(x,y,z)是个点,则变为(x,y,z,1);
    如果(x,y,z)是个向量,则变为(x,y,z,0)
  • 从齐次坐标转换成普通坐标时
    如果是(x,y,z,1),则知道它是个点,变成(x/1,y/1,z/1);
    如果是(x,y,z,0),则知道它是个向量,仍然变成(x,y,z)

即假设在二维平面中有(1,2)(2,2)两个点表示的是两条平行线的正投影,那么通过齐次坐标就可以表示这两条平行线在投影坐标中效果,如下表示的是相交的两根线:
在这里插入图片描述
坐标轴中红线上的点在二维坐标中对应的都是(2,2);黑线上的点在二维坐标轴中对应的都是(1,2)。

齐次坐标的作用

  1. 明确区分向量和点
    通过普通坐标和齐次坐标的变换规则我们可以得知:
    如果n+1维坐标是1,就表示这是一个点
    如果n+1维坐标是0,就表示这是一个向量
  2. 易用于进行仿射(线性)几何变换
    许多图形应用涉及到几何变换,主要包括平移、旋转、缩放
    以矩阵表达式来计算这些变换时,平移是矩阵相加,旋转和缩放则是矩阵相乘,综合起来可以表示为p' = p*m1+ m2(m1旋转缩放矩阵, m2为平移矩阵, p为原向量,p’为变换后的向量)。
    引入齐次坐标的目的主要是合并矩阵运算中的乘法和加法,表示为p' = p*M的形式。即它提供了用矩阵运算把二维、三维甚至高维空间中的一个点集从一个坐标系变换到另一个坐标系的有效方法。”

WebGL中的齐次坐标

在webGL中引入齐次坐标的作用:

  • 许多不错的3D处理技术都是用的齐次坐标进行的处理,WebGL引入齐次坐标有利于图形更好的处理。
  • WebGL中的着色器函数就是使用的齐次坐标做的处理
gl_Position = vec4(position, 1.0);

position位置变量是在 draw() 方法中定义的,并作为 attribute 传递给着色器。position这是一个三维点,但最终通过管线传递的 gl_Position 变量实际上是四维的 , 是 (x,y,z,w) 而不是 (x,y,z) 。

模型转换

在现实世界的应用程序中,你拥有的源坐标不全部在裁剪空间中。因此大多数时候,你需要将模型数据和其他坐标转换(平移、旋转、缩放)到裁剪空间中。
一个立方体数据由顶点位置,立方体表面颜色和构成单个多边形的顶点位置的顺序组成(以 3 个顶点为一组,以构成立方体表面的三角形)。这些位置和颜色存储在 GL 缓冲区中,作为属性发到着色器,然后分别进行操作。最后,计算并设置单个模型矩阵。该矩阵表示要在组成模型的每个点上执行的转换,以将其移到正确的空间,并在模型中的每个点上执行任何其他所需的转换。这不仅适用于每一个顶点,而且还适用于模型每个表面的每个点。在这种情况下,对于动画的每一帧,一系列缩放,旋转和平移矩阵会将数据移动到裁剪空间中所需的位置。

eg:
MDN是 MDN WebGL 共享代码中定义的矩阵。

CubeDemo.prototype.computeModelMatrix = function (now) {
  // 缩小 50%
  var scale = MDN.scaleMatrix(0.5, 0.5, 0.5);

  // 轻微旋转
  var rotateX = MDN.rotateXMatrix(now * 0.0003);

  // 根据时间旋转
  var rotateY = MDN.rotateYMatrix(now * 0.0005);

  // 稍微向下移动
  var position = MDN.translateMatrix(0, -0.1, 0);

  // 相乘,确定以相反的顺序读取它们
  this.transforms.model = MDN.multiplyArrayOfMatrices([
    position, // step 4
    rotateY, // step 3
    rotateX, // step 2
    scale, // step 1
  ]);
};

| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐