豆皮粉儿们,又见面了,明天这一期,由“Kakashi”,给咱们带来webgl的学习,webgl一种很强的数据可视化的图形库,同时数据可视化也是前端倒退的一个重要方向之一,值得入坑和学习。

本文作者:Kakashi
前言:本篇文章预计浏览耗时【15min】将较为全面根底的带你学习 如何应用WebGL(并重) && 相干原理(简略)。通过本次学习 你将能够从0到1搭建本人的webgl繁难渲染库

一 、背景:

1.1 为什么要用WebGL?

先热身一下吧,看个问题:
如果你有一堆作业没有做完,能够抉择帮手替你实现,你会抉择?

A. 1个老传授
B. 9个小学生

  • 选A的同学,你真的忍心让老传授帮忙写语文填空?
  • 选B的同学,你真的释怀让小学生帮你解线性代数?
    所以咱们要看看“作业”内容到底是什么,有多少作业量。
  • 如果题目是 1+2 ,9个小学生 = 人海战术收费劳动力,没有技术含量,纯正体力活,效率会很高。
  • 如果题目是线性代数 ,老传授 >> 99 个小学生。
    回到咱们的主题,相似的,因为设计指标的不同,CPU和GPU也是大不相同的。它们别离针对了两种不同的利用场景:
  • CPU须要很强的通用性来解决各种不同的数据类型,同时又要逻辑判断又会引入大量的分支跳转和中断的解决。这些都使得CPU的内部结构异样简单。
  • GPU面对的则是类型高度对立的、互相无依赖的大规模数据和不须要被打断的污浊的计算环境。

(图片来自nVidia CUDA文档。其中绿色的是计算单元,橙红色的是存储单元,橙黄色的是管制单元。)
GPU在概念上实用于高度并行计算,因为GPU能够通过计算暗藏内存拜访提早,而不是通过大数据缓存和流控制来防止内存拜访提早。
简而言之,CPU 基于低延时的设计,GPU是基于大的吞吐量设计

1.2 什么是WebGL?

WebGL是一种3D绘图规范,这种绘图技术标准容许把JavaScript和OpenGL ES 2.0联合在一起,通过减少OpenGL ES 2.0的一个JavaScript绑定,WebGL能够为HTML5 Canvas提供硬件3D减速渲染(局部计算GPU),这样Web开发人员就能够借助零碎显卡来在浏览器里更流畅地展现3D场景和模型了,还能创立简单的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创立具备简单3D构造的网站页面,甚至能够用来设计3D网页游戏等等。
总结一下,WebGL的实质 —— JavaScript操作OpenGL接口

    当然,WebGL只是绑定了一层,外部的一些核心内容,如着色器,材质,灯光等都是须要借助GLSL ES语法来操作的。
1.2.1 WebGL / OpenGL / ES X.0之间的关系?

  • OpenGL(Open Graphics Library)
    一种图形应用程序编程接口标准(Application Programming Interface,API)。它是一种能够对图形硬件设施个性进行拜访的软件库,OpenGL被设计为一个现代化的、硬件无关的接口,因而咱们能够在不思考计算机操作系统或窗口零碎的前提下,在多种不同的图形硬件零碎上,齐全通过软件的形式实现OpenGL的接口。
  • OpenGL ES(embedded system)
    OpenGL ES是OpenGL的一个非凡版本,次要针对嵌入式设施应用,专用于嵌入式计算机、智能手机、家用游戏机等设施。OpenGL ES 2003-2004年被首次提出来,其中两次重要降级别离在2007年(OpenGL ES 2.0)和2012年(OpenGL ES 3.0),WebGL就是基于OpenGL ES 2.0的。

二、如何应用WebGL

2.1 入门示例,不再是hello world!

  let gl = (document.getElementById(      'canvas'    ) as HTMLCanvasElement).getContext('webgl') as WebGLRenderingContextBase;    // 指定一个笼罩(清空)canvas的rgba色彩,实质是setColor,它把背景色存到了webgl system中的glCOLOR_BUFFER_BIT,得手动render一下    gl.clearColor(0.0, 0.0, 0.5, 1.0);    // 革除canvas,会革除全副,再应用背景色 填充    gl.clear(gl.COLOR_BUFFER_BIT);  }

运行后果&流程示意:

论断:

  1. WebGL须要依赖canvas这个载体获取对应的绘图上下文
  2. WebGL API基于OpenGL ES,函数命名绝对应
  3. WebGL基于多缓冲区模型

2.2 绘制一个点

如果相似canvas 2d的话,你可能认为WebGL绘制一个点:

gl.drawColor(1.0, 1.0, 1.0, 1.0) // 点的色彩gl.drawPoint(0, 0, 0, 10) // 点的地位大小

相似这样就能够了,可怜的是:
WebGL依赖于一种着色器(shader)的绘图机制,简单而弱小,着色器是 WebGL的外围机制。
WebGL中着色器程序能够写成字符串变量:

// 顶点着色器程序const VSHADER_SOURCE = `        void main(){          gl_Position = vec4(0.5,0.5,0.0,1);          gl_PointSize = 10.0;        }`;// 片元着色器程序const FSHADER_SOURCE = `        void main(){           gl_FragColor = vec4(1.0,0.0,0.0,1.0);        }`;

当然也反对通过ajax申请读取glsl文件,又或者参考MDN GLSL示例,写在script标签中。
接下来咱们初始化着色器(包含加在着色器代码,创立程序,链接,编译等一套流程):

if (!initShaders(this.gl, VSHADER_SOURCE, FSHADER_SOURCE)) {  console.error('初始化着色器失败');  return;}

绘制点:

// 指定一个笼罩(清空)this.canvas的背景色彩this.gl.clearColor(0.0, 0.0, 0.0, 1.0);// 用指定的色彩清空色彩缓冲,从而清空canvasthis.gl.clear(this.gl.COLOR_BUFFER_BIT);// 将1个点绘制进去this.gl.drawArrays(this.gl.POINTS, 0, 1);this.gl.POINTS指定WebGL的绘制模式为点绘制。

运行后果&流程示意:

(思考一下,为什么画在了屏幕右上角?轻轻提醒:坐标零碎)

论断:

  1. WebGL须要两种着色器,应用GLSL ES语言来编写(须要学习老本)。

    1. 顶点着色器(Vertex shader):形容顶点个性(地位,尺寸)。
    2. 片元着色器(Fragment shader):形容 片元(像素)处理过程。
  2. 着色器运行在WebGL零碎中,而不是JS程序。
  3. WebGL 地位应用向量,应用右手坐标系。

    2.3 绘制多个动静的点

    上一节绘制出了一个点,然而点的地位、色彩之类属性是在代码中写死的,这种“硬编码”便于了解,然而不足可拓展性,怎么动静的设置点的信息呢?
    咱们的指标,将地位信息通过Javascript动静传给顶点着色器,须要通过上面的流程:

  4. 在顶点着色器,申明attribute变量。
  5. 将attribute变量赋值给gl_Positon变量。
  6. 向attribute变量传输数据。

咱们须要在第三步来绘制多个点,举个例子:
一共绘制20个点,采取的策略是:

  • 每次绘制一个点,绘制20次?
  • 绘制1次,一次性绘制20个点?
    当然抉择后者。咱们须要借助 缓冲区对象,一次性传入多个顶点数据。

    2.4 绘制一个箭头

    查看Canvas的绘图API,咱们会发现它能画直线、矩形、圆、弧线、贝塞尔曲线。
    于是,咱们看了看WebGL绘图API,发现:

    void gl.drawArrays(mode, first, count);

    mode指定绘制图元的形式,可能值如下:

  • gl.POINTS: 绘制一系列点。
  • gl.LINE_STRIP: 绘制一个线条。即,绘制一系列线段,上一点连贯下一点。
  • gl.LINE_LOOP: 绘制一个线圈。即,绘制一系列线段,上一点连贯下一点,并且最初一点与第一个点相连。
  • gl.LINES: 绘制一系列独自线段。每两个点作为端点,线段之间不连贯。
  • gl.TRIANGLE_STRIP:绘制一个三角带。
  • gl.TRIANGLE_FAN:绘制一个三角扇。
  • gl.TRIANGLES: 绘制一系列三角形。每三个点作为顶点。

const VERTEXRS = [V0,V1,V2,V3,V4,V5];    

如图所示,WebGL可只能绘制三种图元:点、线、三角形。不过所有其余图元,从圆到球体、从立方体到简单三维模型,都能够由一个个三角面片组成。实际上,咱们能够用三角形绘制出所有你想绘制的货色。
那么绘制一个箭头的思路能够有很多,举两个例子:

不过不同的绘制计划间接是有区别的,会影响到法线,进而影响面片方向(侧面还是反面)的判断,这些就不深刻介绍啦。

论断:

  1. WebGL只能绘制点,线,三角形,然而万物能够由三角形组成(准则:数量越少越好)。

2.5 绘制一个正方体

2.5.1 对于三维世界

二维图形和三维图形,最显著的区别是:三维图形有深度,也就是z轴。咱们须要思考两个角度:

  1. 察看方向:观察者在什么地位,在看场景的哪一部分?

观察者的地位称为视点(eye point),从视点登程沿察看方向的射线 叫做眼帘(viewing direction),通过视图矩阵确定察看方向:

  1. 可视空间:观察者能看到多远?(能看多少?是否须要远小近大)
  2. 正摄投影:长方体可视空间,也称盒状空间:

正射投影能够通过投影矩阵确定可视空间:

Matrix4.setOrtho(left, right, bottom, top, near, far);
  • 透视投影:四棱锥/金字塔可视空间:

透视投影能够通过投影矩阵确定可视空间:

Matrix4.setPerspective(fov, aspect, near, far);
2.5.2 对于正方体

通过之前学习,咱们联想到,两个三角形能够拼成一个矩形立体,作为正方体一面。一个正方体也就是 62 = 12个三角形,每个三角形 3个顶点,也就是 12 3 = 36 个顶点。咱们的顶点着色器传入36个顶点就能够了。然而用失常逻辑一想,正方体实际上不是只有8个顶点吗?显然咱们定义36个是有反复的,并没有被多个三角形专用。
如你所愿,WebGL提供了一个通过gl.drawElements函数的复用计划:
立方体被拆成6个面,每个面都由两个三角形组成,每个三角形都有三个顶点,和顶点列表中的三个点相关联。三角形列表中的数字示意该三角形的三个顶点在顶点列表中的索引值。如下图所示:

论断:

  1. WebGL绘制3D 较为简单,须要依赖视图矩阵和投影矩阵实现 3d视觉效果,然而建模局部还是依赖于最小图元-三角形。

2.6 其余纳闷

  • 怎么样平移,旋转,缩放?
    A:线性代数上场啦。举个例子,平移须要将平移矩阵[Tx,Ty,Tz]传入顶点着色器,逐顶点操作,加到对应顶点坐标重量上,再赋值给gl_positon。旋转、缩放相似。
  • 怎么样写文字?
    A:参考链接,或者能够用tiny-sdf库 ,文字即图片的计划。
  • 怎么实现动画?
    A:WebGL不提供动画接口,次要依赖requestAnimation办法。
  • 怎么实现渐变色?
    A:借用顶点着色器缓冲区对象,通过varying变量, 从顶点着色器向片元着色器传输数据。
  • 怎么实现背景图片?
    A:纹理映射(Texture Mapping)。在片元着色器将筹备好的纹理(Image转换)取出赋值给片元。
  • 怎么画圆?
    A:把正方形削成圆形。 片元着色器内能够通过坐标判断放弃绘制一些点。

三、WebGL的流程原理

简略说来,WebGL绘制过程包含以下三步:
1、获取顶点坐标

2、图元拆卸(即画出一个个三角形)

3、光栅化(生成片元,即一个个像素点)

残缺链路:


四、WebGL的现状

看到下图,笔者不禁一把辛酸泪。

对于WebGL而言,最大的问题就是兼容性

一.浏览器支不反对?(入门难度:装置最新chrome)

WebGL遍及水平绝对较高。2.0版本Safari仿佛正在接入,或者对WebGL2.0的推广有所助力。

二.显卡支不反对?(天堂难度:换显卡)

三.显卡和浏览器都ok的话,设置合不合理?(难以评估难度:对非开发者极不敌对)

  • Case1:浏览器设置开启硬件加速。
    关上 chrome 设置(地址栏输出chrome://settings/),『显示高级设置』,找到『零碎』,在『应用硬件加速模式』选项前打钩,重启浏览器。
  • Case2:浏览器设置禁用webgl
    WebGL:--disable-webgl
    关上 chrome://flags 面板(将这行字输出地址栏),ctrl/command + f 搜寻『--disable-webgl』并启用该选项。重启浏览器。
  • Case3:浏览器设置显卡黑名单
    Hardware accelerated:WebGL 已启用,并取得了显卡反对Software only, hardware acceleration unavailable:WebGL 已启用,但没有显卡反对,只有软件渲染反对Unavailable:WebGL 既没有显卡反对也没有软件反对。

WebGL 利用个别须要显卡减速,如果你的浏览器显示 WebGL 未取得显卡反对(即显示为前面两项),如上图webgl2 Unavailable,则两种可能:

  1. 你电脑的显卡可能进入了 chrome 的黑名单。
  2. 2.你的显卡不行(^_^)
    有一些显卡和显卡驱动因为 bug 太多会导致浏览器解体甚至零碎解体,所以很多浏览器都有一个显卡黑名单,对这些有问题的显卡和驱动,浏览器将不启用硬件加速。能够在 chrome://flags 中开启 --ignore-gpu-blacklist 来忽视这个黑名单(不举荐,可能会引发浏览器解体或者零碎解体)

    ---

    附录

    一些罕用的库:

  3. Three (基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文材料最多、应用最宽泛的三维引擎)
  4. stats.js (JavaScript性能监控器,能够测试webgl代码的渲染性能)
  5. dat.GUI(google开发人员创立的,是一个轻量级的图形用户界面库(GUI 组件),应用这个库能够很容易地创立出可能扭转代码变量的界面组件)
  6. ShaderToy(一个酷炫乏味的网站,学习shader编程)
  7. rainbow(一个繁难的webgl渲染库,蕴含本次全副demo⭐️)

参考资料及鸣谢

  • 图解WebGL&Three.js工作原理:
    https://www.cnblogs.com/wanbo...
  • 《WebGL编程指南》:【必看】