webGL概念和基础入门

目录
1 webGL 是什么
2 webGL 发展史
3 webGL / openGL / ES X.0 之间的关系
4 webGL 基础概念
5 webGL 工作原理
6 webGL 初始化及渲染流程
7 webGL webGL 绘制三角形
8 webGL 库介绍
9 webGL 总结



1. webGL 是什么

维基百科
WebGL 是一种 JavaScript API,用于在不使用插件的情况下在任何兼容的网页浏览器中呈现交互式 2D 和 3D 图形。WebGL 完全集成到浏览器的所有网页标准中,可将影像处理和效果的 GPU 加速使用方式当做网页 Canvas 的一部分。WebGL 元素可以加入其他 HTML 元素之中并与网页或网页背景的其他部分混合。WebGL 程序由 JavaScript 编写的句柄和 OpenGL Shading Language (GLSL)编写的着色器代码组成,该语言类似于 C 或 C++,并在电脑的图形处理器(GPU)上执行。

MDN
WebGL(Web 图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5 <canvas >元素中使用。这种一致性使 API 可以利用用户设备提供的硬件图形加速。

官网
WebGL(Web Graphics Library) 是一种跨平台、免费、开放的 Web 标准,是基于 OpenGL ES 的底层 3D 图形 API,通过 HTML5 Canvas 元素公开给 ECMAScript。熟悉 OpenGL ES 2.0 的开发人员将 WebGL 视为使用 GLSL 的基于着色器的 API,其结构在语义上与底层 OpenGL ES API 的相似。它非常接近 OpenGL ES 规范,对开发人员期望的内存管理语言(如JavaScript )做出了一些让步。WebGL 1.0 公开了 OpenGL ES 2.0 功能集; WebGL 2.0 公开了 OpenGL ES 3.0 API。WebGL 为 web 带来了无插件的 3D,直接在浏览器中实现。

WebGL 的本质 —— JavaScript 操作 OpenGL 接口
webGL.png

传统网页和 WebGL 网页的软件结构

核心要点
1. Web 3D 图形 API;
2. 基于 OpenGL ES;
3. 依赖 Canvas 图形容器;
4. 在GPU运行;

2. webGL 发展史

背景
WebGL 规范产生以前,浏览器如果想实现 3D 动画效果,只能借助一些浏览器插件,比如 Adobe 的 Flash、微软的 SilverLight 等来实现,那么为了打破这一局限,各大知名公司联手制定了一种跨平台的 3D 开发标准,也就是 WebGL 规范。

起源
WebGL起源于Mozilla员工弗拉基米尔·弗基西维奇的一项称为Canvas 3D实验项目,并于 2006 年首次展示了 Canvas 3D 的原型,2007 年底在 FireFox 和 Opera 浏览器中实现。

发展
2009年初非营利技术联盟Khronos Group创建了WebGL的工作组,最初的工作成员包括Apple、Google、Mozilla、Opera等。2011 年 3 月 WebGL 1.0 规范发布,该规范基于OpenGL ES 2.0。截至2012年3月,工作组的主席由肯·罗素(Ken Russell,全名“Kenneth Bradley Russell”)担任。WebGL 2.0 规范的发展始于2013年,并于2017年1月完成,该规范基于OpenGL ES 3.0,首度实现在Firefox 51、Chrome 56和Opera 43中。

3. webGL / openGL / ES X.0 之间的关系

下图显示了它们之间的关系:
webGL2.png
OpenGL -> OpenGL ES -> OpenGL ES 2.0 -> WebGL

  • OpenGL(Open Graphics Library) 一种图形应用程序编程接口规范 (Application Programming Interface,API)。它是一种可以对图形硬件设备特性进行访问的软件库,OpenGL 被设计为一个现代化的、硬件无关的接口,因此我们可以在不考虑计算机操作系统或窗口系统的前提下,在多种不同的图形硬件系统上,完全通过软件的方式实现 OpenGL 的接口。

  • OpenGL ES(embedded system) OpenGL ES 是 OpenGL 的一个特殊版本,主要针对嵌入式设备使用,专用于嵌入式计算机、智能手机、家用游戏机等设备。他从 OpenGL 中移除了很多旧的和无用的特性,并为其添加了一些新的特性。例如,去除了矩形等多余的多边形,而只保留了点、线、三角形等基本图形。这使它在保持轻量级的同时仍然保留足够强大的能力来渲染漂亮的 3D 图形。

  • WebGL 从 OpenGL ES 衍生而来的。WebGL 1.0 基于 OpenGL ES 2.0,WebGL 2.0 基于 OpenGL ES 3.0。

4. webGL 基础概念

4.1 坐标系

webgl 的三维坐标系统是笛卡尔坐标系中的右手坐标系,具有 x,y,z 三个维度。右手坐标系如下图:(箭头指向为正轴方向)
image.png
每个方向都有可使用的值的区间,超出该矩形区间的图像不会绘制:

  • x 轴最左边为 -1,最右边为 1;

  • y 轴最下边为 -1,最上边为 1;

  • z 轴朝向你的方向最大值为 1,远离你的方向最大值为 -1;

笛卡尔坐标系以屏幕中心为原点,规范正交化后是 -1 到 1,方便转化为笛卡尔坐标计算。

4.2 投影

在计算机三维图像中,投影可以看作是一种将三维坐标变换为二维坐标的方法,常用到的有正交投影和透视投影。正交投影多用于三维建模(例如建筑的平面图采用的就是正交投影),透视投影则由于和人的视觉系统相似,多用于在二维平面中呈现三维世界。
透视投影(近大远小特点)
image.png

透视投影基本模型
透视投影成像原理

image.png

正交投影
用一个盒子状的可见范围平行投影物体, 没有近大远小的概念。

image.png

4.3 光照

平行光源: 类似太阳光, 可以认为发光光源距离无限远, 因此所有光线方向相同, 光照强度相同;

点光源: 类似聚光灯效果, 照射到物体上的光线方向不同, 强度也不同;

环境光: 从各个方向以相同强度照射到物体上的光线;

平行光


点光源


环境光


4.4 网格

3D空间内的所有物体都是由点、线及面组成。一个点由3个值组成 - x、y、z,表示3D空间内的唯一位置。2个点可以连成一条线,3个点我们就可以形成一个平面。多个面相互拼接就组成了网格。网格用来描述物体形状。
image.png
网格本身是没有纹理和材质。

4.5 纹理

在计算机图形学中,纹理贴图(Texturing)是使用图像、函数或其他数据源来改变物体表面外观的技术。

4.6 材质

材质就是网格表面的特性。表现物体对光的交互(反射、折射等),供渲染器读取的数据,包括贴图纹理、光照算法等。

4.7 着色器

  • GUI 渲染能够让我们看到界面,主要是靠着色器进行渲染的。着色器一般分为顶点着色器、片元着色器。
  • 顶点着色器的作用是用来计算顶点的位置,即告诉 OpenGL 这个顶点在 NDC(标准化设备坐标) 中的坐标。
  • 片元着色器也叫片段着色器,可以理解为像素着色器,一个片元就当成一个像素。片元着色器主要是用来确认这个像素的颜色。

5. webGL 工作原理

WebGL 的工作方式和流水线类似,也是按照流水线的方式将 3D 模型数据渲染到 2D 屏幕上的,业界把这种渲染方式称为图形管线或者渲染管线。

image.png

OpenGL ES 2.0 渲染管道

GPU 渲染管线的主要处理过程如下:

  • 首先进入顶点着色器阶段,利用 GPU 的并行计算优势对顶点逐个进行坐标变换。
  • 然后进入图元装配阶段,将顶点按照图元类型组装成图形。
  • 接下来来到光栅化阶段,光栅化阶段将图形用不包含颜色信息的像素填充。
  • 在之后进入片元着色器阶段,该阶段为像素着色,并最终显示在屏幕上。
渲染管线渲染图解

image.png

6. webGL 初始化及渲染流程

6.1 获取 webgl 上下文

1234
// <canvas id="canvas"></canvas> canvas 的 dom 结构 const ctx = document.querySelector('#canvas'); const gl = ctx.getContext('webgl');

6.2 初始化视窗(viewport)

1
gl.viewport(0, 0, canvas.width, canvas.height);

6.3 编写着色器代码

1234567891011121314
/ 顶点着色器 const VERTEX_SHADER = '' + 'void main(){' + ' gl_Position = vec4(0.0,0.0,0.0,1.0);' + ' gl_PointSize = 15.0;' + '}' + '' // 片元着色器 const FRAGMENT_SHADER = '' + 'void main() {' + ' gl_FragColor = vec4(1.0,0.0,0.0,1.0);' + '}' + ''

6.4 创建着色器

12345
// 创建顶点着色器 const vertexShader = gl.createShader(gl.VERTEX_SHADER); // 创建片元着色器 const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

6.5 编译着色器

12345678
// 将顶点着色器代码添加到顶点着色器中 gl.shaderSource(vertexShader, VERTEX_SHADER); // 将片元着色器代码添加到片元着色器中 gl.shaderSource(fragmentShader, FRAGMENT_SHADER); // 添加完成后,需要编译着色器 gl.compileShader(vertexShader); gl.compileShader(fragmentShader);ht);

6.6 初始化 program

1234567891011
program = gl.createProgram(); // 将着色器添加到渲染程序中 gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); // 关联 program gl.linkProgram(program); // 使用 program gl.useProgram(program);

6.7 绘制图形(viewport)

这里我们以一个点为例,在画布上绘制一个点。

1
gl.viewport(0, 0, canvas.width, canvas.height);

效果截图如下:
image.png

完整示列

7 webGL 绘制三角形

三角形是 3D 基础图形,下面我们用 webGL 绘制一个三角形。
JS 代码如下:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
// <style> // canvas { // width: 100%; // height: 100%; // } // </style> // <canvas id="canvas"></canvas> canvas 的 dom 结构 const canvas = document.getElementById('canvas'); const webgl = canvas.getContext('webgl'); // 设置视窗 webgl.viewport(0, 0, webgl.canvas.width, webgl.canvas.height); // 设置webGL背景颜色 webgl.clearColor(0, 1, 1, 1); webgl.clear(webgl.COLOR_BUFFER_BIT); // 顶点着色器代码 const vertexShaderSource = ` attribute vec4 a_position; void main(){ gl_Position = a_position; }`; // 片元着色器代码 const fragmentShaderSource = ` // precision mediump float; void main(){ gl_FragColor = vec4(0.93, 0, 0.56, 1); }`; // 创建着色器 const vertexShader = webgl.createShader(webgl.VERTEX_SHADER); const fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER); // 将着色器代码添加到着色器 webgl.shaderSource(vertexShader, vertexShaderSource); webgl.shaderSource(fragmentShader, fragmentShaderSource); // 编译着色器 webgl.compileShader(vertexShader); webgl.compileShader(fragmentShader); // 初始化 program var program = webgl.createProgram(); webgl.attachShader(program, vertexShader); webgl.attachShader(program, fragmentShader); webgl.linkProgram(program); webgl.useProgram(program); // 三角形的三个顶点, 用 3 组 Vec2 坐标来进行数据定义 var vertices = new Float32Array([0, 0.5, 0.5, 0, -0.5, -0.5]); // 获取 Shader 的定点变量 var positionAttributeLocation = webgl.getAttribLocation(program, 'a_position'); // 创建缓冲区对象 var positionBuffer = webgl.createBuffer(); // 绑定缓冲区对象 webgl.bindBuffer(webgl.ARRAY_BUFFER, positionBuffer); // 写入数据到缓冲区对象 webgl.bufferData(webgl.ARRAY_BUFFER, vertices, webgl.STATIC_DRAW); // 分配缓冲区对象给 attribute 变量 webgl.vertexAttribPointer( positionAttributeLocation, 2, webgl.FLOAT, false, 0, 0 ); // 开启 attitude 变量 webgl.enableVertexAttribArray(positionAttributeLocation); // 绘制三角形 webgl.drawArrays(webgl.TRIANGLES, 0, 3);

效果截图如下:
image.png

完整示列

8. webGL 库介绍

可以看出仅绘制一个简单的三角形,就需要写一长串 JS 代码,如果用原生 WebGL API 编写一个动态的 3D 交互式网页,那么开发成本是极其昂贵的。尽管从功能上而言,原生 WebGL API 可以满足我们任意场景的开发需要,但是其开发和学习的成本极其昂贵,对于 WebGL 的初学者而言是极度不友好的。为此涌现了很多开发框架,下面介绍一些常用的 WebGL 开发框架。

Three.js
Threejs 是最著名的 3D WebGL JavaScript 开源库。Threejs 是3D渲染引擎,其应用范围广泛(如Web 3D游戏、3D模型展示、Web VR、数据可视化等)。Threejs 用最简单、直观的方式封装WebGL中的常用方法,具有低复杂、轻量级、易扩展等特点。

Cesium.js [ˈsiːziəm]
CesiumJS 是一个开源JavaScript库,专用于创建具有最佳性能、精度、视觉质量和易用性的 3D 地图。其拥有较为全面的 3D 地图开发 API,对于需要开发 3D 地图的开发者是一个不错的选择。

Babylon.js [ˈbæbəˌlɑn]
Babylon.js 是一个 javascript 开源框架,主要用于构建 3D 游戏。Babylon.js 是最受欢迎的3D游戏引擎之一,被开发人员广泛使用。

A-Frame
A-Frame 是用于构建虚拟现实(VR)体验的 javaScript 开源框架,它的底层渲染基于 Threejs。A-Frame 作为一个独立的开源项目,已经发展成为最大的VR社区之一。

ThingJS
ThingJS 面向物联网的3D可视化开发平台, 主要用于楼栋建筑组成的园区级别的场景。ThingJS 平台不是开源的,平台提供了一套在线的三维开发环境。ThingJS 是新兴的 3D 框架,诞生于 2018 年。

9 总结

首先介绍了 webGL 基本概念、发展历史,阐述了 webGL、OpenGL、SE X.0 之间的关系。接着简要介绍了 WebGL 坐标系、投影、材质、着色器等基础概念,介绍了 webGL 渲染管线的主要处理过程。然后详细介绍了 webGL 初始化及渲染流程,介绍如何使用webGL 绘制一个三角形。最后分析了 webGL 开发动态 3D 界面优缺点,并介绍了 three.js、Babylon.js、Cesium.js 等常用的 webGL 开发框架。




参考

  1. https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API
  2. https://webglfundamentals.org/webgl/lessons/zh_cn/
  3. https://zh.wikipedia.org/wiki/WebGL
  4. https://www.khronos.org/webgl/
  5. http://eux.baidu.com/blog/fe/832
  6. https://www.cnblogs.com/zaisanshuiyifang/p/15597951.html
  7. https://cloud.tencent.com/developer/article/1746988
  8. https://blog.towavephone.com/webgl-zero-based-practice-learn/
# webGL,前端
docker容器替换脚本
富文本编辑器 wangEditor 5 推荐
评论
luoqiangweb开发China
文章29
分类13
标签7