JavaScript|JavaScript WebGL 基础概念

引子 看了一个库的源码,里面用到了 WebGL ,就开始找 WebGL 的资料。发现相关的知识点很多,按照自己的理解习惯进行了整理记录。

  • Origin
  • My GitHub
简介 WebGL 是一个跨平台、免费的开放式 Web 标准,用于基于 OpenGL ES 的初级 3D 图形 API 。可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。在 JavaScript 中可以通过 HTML5 的 Canvas 元素使用。WebGL 1.0 基于 OpenGL ES 2.0,WebGL 2.0 基于 OpenGL ES 3.0 。目前浏览器支持情况见Can I use WebGL ?
WebGL 官方相关引导资源见这里,感觉浏览加载有些慢,单独下载了一份到 Github : WebGL 1.0、WebGL 2.0。
OpenGL ES 是一个跨平台、免费的 API ,用于在嵌入式和移动系统(包括控制台、手机、设备和车辆)上渲染高级 2D 和 3D 图形。它是 OpenGL 的子集。
OpenGL 是业界最广泛采用的 2D 和 3D 图形 API ,为各种计算机平台带来了数千种应用程序。它独立于窗口系统和操作系统。OpenGL 公开了最新图形硬件的所有功能。
OpenGL 规范严格规定了每个函数该如何执行,以及它们的输出值。至于内部具体每个函数是如何实现的,将由 OpenGL 库的开发者自行决定,因此在不同系统中相同的 API 可能会出现表现行为不一致的情况。
OpenGL ES 对应的可编程语言是 OpenGL ES Shading Language (GLSL ES),该语言基于 OpenGL Shading Language (GLSL) 制定。GLSL 是 OpenGL 的主要着色语言,其风格类似 C 语言,是为图形计算量身定制的,它包含一些针对向量和矩阵操作的有用特性。
下面的概念大都是关于 OpenGL ,由于 WebGL 核心还是基于 OpenGL ,同样有助于理解。
状态机 状态机(FSM)是一个计算数学模型,是一个抽象的机器,能在任何给定的时间处于有限状态中的一个。FSM 可以根据一些输入从一种状态改变到另一种状态。
OpenGL 自身就是一个巨大的状态机:一系列的变量描述 OpenGL 此刻应当如何运行。在 OpenGL 相关程序中可以看到很多全局的变量,其中一些是输出变量,一些输入变量。
图形渲染管线 在 OpenGL 中,任何事物都在 3D 空间中,而屏幕和窗口却是 2D 像素,这导致 OpenGL 的大部分工作都是关于把 3D 坐标转变为适应屏幕的 2D 像素。3D 坐标转为 2D 坐标的处理过程是由 OpenGL 的图形渲染管线(Graphics Pipeline)管理。
图形渲染管线可以被划分为几个阶段,每个阶段将会把前一个阶段的输出作为输入。所有这些阶段都是高度专门化的,并且很容易并行执行。正是由于它们具有并行执行的特性,当今大多数显卡都有成千上万的小处理核心,它们在 GPU 上为每一个(渲染管线)阶段运行各自的小程序,从而在图形渲染管线中快速处理数据。这些小程序叫做着色器(Shader)。
【JavaScript|JavaScript WebGL 基础概念】下面是一个图形渲染管线的每个阶段的抽象展示。注意蓝色部分代表可以注入自定义着色器,也就是可编程。
JavaScript|JavaScript WebGL 基础概念
文章图片

作为图形渲染管线输入的数据叫做顶点数据(Vertex Data)。顶点数据是一系列顶点的集合。一个顶点(Vertex)是一个 3D 坐标数据的集合。而顶点数据是用顶点属性(Vertex Attribute)表示的,它可以包含任何我们想用的数据。
输入的数据会进入到图形渲染管线的第一个处理阶段:顶点着色器。
顶点着色器
顶点着色器(Vertex Shader)可编程,主要的目的是把 3D 坐标转为标准化设备坐标。还会在 GPU 上创建内存用于储存顶点数据,还要配置 OpenGL 如何解释这些内存,并且指定其如何发送给显卡。顶点着色器允许我们对顶点属性进行一些基本处理。
顶点相关的信息都存放在顶点缓冲对象(Vertex Buffer Objects, VBO)中,它会在 GPU 内存(通常被称为显存)中储存大量顶点。使用这些缓冲对象的好处是可以一次性发送一大批数据到显卡上,而不是每个顶点发送一次。当数据发送至显卡的内存中后,顶点着色器几乎能立即访问顶点,这是个非常快的过程。
接着进入到图元装配阶段。
图元装配
图元装配(Primitive Assembly)将顶点着色器输出的所有顶点作为输入,所有的点会装配成指定图元的形状。图元基本形状有:
  • 线
  • 三角形
图元装配阶段的输出会传递给几何着色器阶段。
几何着色器
几何着色器(Geometry Shader)可编程,把图元形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其它的)图元来生成其它形状。
几何着色器的输出会被传入光栅化阶段。
光栅化
光栅化(Rasterization)会把图元映射为最终屏幕上相应的像素,生成供片段着色器使用的片段(Fragment)。在片段着色器运行之前会执行裁切(Clipping)。裁切会丢弃超出视图以外的所有像素,用来提升执行效率。
片段着色器
片段着色器(Fragment Shader)可编程,主要目的是计算一个像素的最终颜色,这也是所有 OpenGL 高级效果产生的地方。通常,片段着色器包含 3D 场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。
在所有对应颜色值确定以后,最终的对象将会被传到最后一个阶段:测试混合。
测试混合
测试混合(Tests And Blending)阶段检测片段的对应深度(和模板(Stencil))值,用它们来判断这个像素是其它物体的前面还是后面,决定是否应该丢弃。这个阶段也会检查 alpha 值(alpha值定义了一个物体的透明度)并对物体进行混合(Blend)。所以,即使在片段着色器中计算出来了一个像素输出的颜色,最后渲染的像素颜色也可能完全不同。
WebGL 中的着色器 WebGL 中主要编写的着色器有顶点着色器和片段着色器。具体实现见 JavaScript WebGL 绘制一条直线。
参考资料
  • WebGL lessons
  • WebGL基础绘制之一:绘制一个点
  • 你好,三角形
  • WebGL MDN
  • Khronos
  • MDN WebGL 绘制正方形

    推荐阅读