介绍
WebGL 是一个在浏览器里绘图的协议,它到底能干啥?想必各位已经看过很多浏览器实现的酷炫吊炸天效果了,你说没有看过,那可以来这里观摩下:shadertoy,看看几行代码能实现的神奇效果,感受感受大佬的厉害。学会 WebGL 就可以在浏览器中呈现任何想要的视觉效果。
学习这门知识需要有基础数学知识(线性代数、几何、三角学),然后慢慢接触、接受各种图形学中的概念(基础的向量、矩阵、三角函数知识是必须的,因为 shader 不像 js 那样方便断点调试,所以当绘制的图形没有按预期显示出来时候,这些知识可以在潜意识中帮助排查问题)。
那 WebGL 的原理是啥呢?其实 WebGL 是基于 OpenGL 的,应该问下 OpenGL 的原理是啥。WebGL1.0 基于OpenGL ES 2.0,WebGL 2.0基于OpenGL ES 3.0,扩展了 WebGL 1.0,引入新的 API。
在 OpenGL 中最关键的就是渲染管线,是开发者可以自由绘图的基础。OpenGL规范严格规定了每个函数该如何执行,以及它们的输出值,同时 OpenGL 自身也是一个巨大的状态机,内置了一系列的变量描述 OpenGL 此刻应当如何运行。这些知识在 WebGL 中同样适用。目前最新的是 WebGL 2.0,下一代技术是 WebGPU,目前已发布 Beta 版本,可以在 Chrome 113+ 的版本中使用,正式版本也快要发布了。(写文章时间20230426,虽然 WebGPU即将正式发布,但是目前资料较少,还没有广泛推广和应用,无法和实际项目结合。仍然建议先学 WebGL2,把基础的图形学、数学基础打好,一两年之后在学习 WebGPU 也相对轻松简单些。)
常规的学习路径是先了解一些概念和原理,有个大概印象,然后从简单 Demo 入手,逐步深入,因 WebGL 知识体系庞大,所以学习某一部分知识时候 demo 功能会比较单一且枯燥,但是学的多了,慢慢的就能看懂大佬的酷炫效果,自己也可以游刃有余地写出来。
git 上有很多封装好的 WebGL 库,有些是通用的图形库(对WebGL的封装程度简单),有些是专业领域的框架,例如:Threejs、Babylon.js、Cesium等。
这是WebGL 系列的入门文章,免费订阅,如有帮助请点赞收藏,纰漏之处欢迎指正!
渲染管线
WebGL 可以把由一系列三维坐标坐标构成的三维物体渲染为二维图形,这个过程就是渲染管线执行的过程。
可以把渲染管线的执行过程想象成一条流水线,每一个步骤都只负责很专一的工作,我们可以通过编写顶点着色器代码、片元着色器代码和几何着色器代码(WebGL 中不能自定义几何着色器的,暂时不去介绍)来自定义其中的某些步骤。下面是这个流程的大致介绍。
顶点数据: 不只包括顶点的坐标,还有每个顶点的颜色,法线向量,纹理坐标等,这些都是顶点的属性信息。
顶点着色器:可以对输入的顶点数据进行处理,会自动对每一个顶点处理。
图元装配: 图元组装是将顶点着色器中输出的顶点组装成指定的图元,图元组装之后会进行裁剪和背面剔除,删除不必要的图元,从而减少发送到下一个阶段的图元个数,提高性能。
几何着色器: WebGL 中不能自定义几何着色器的,暂时不去介绍。
光栅化: 通过采样将矢量图元离散成一个个片元,会基于图元各个顶点的属性对内每个片元进行进行线性插值处理。
片元着色器: 处理光栅化后的每一个片元,赋予颜色。
混合和测试: 常见的测试有模版测试和深度测试,进一步对片元结果处理,产出像素图形。
WebGL渲染管线流程
WebGL中有很多新概念,绘制顺序也很固定且繁琐,也有很多固定的方法,看似很类似的操作在代码上却是不一样的写法,多写多看几遍就熟悉了。
了解一些概念:
渲染管线: 指三维渲染的过程中显卡执行的、从几何体到最终渲染图像的、数据传输处理计算的过程。几何顶点被组合为图元(点,线段或多边形),然后图元被合成片元,最后片元被转换为帧缓存中的象素数据。
顶点:具有空间坐标和其他信息(如颜色和纹理坐标)的二维点。需要注意的是,WebGL 顶点的坐标范围都要在 -1.0 ~ 1.0之间才是有效值,我们可以叫他标准化设备坐标(Normalized Device Coordinates, NDC),任何落在范围外的坐标都会被丢弃/裁剪,不会显示在你的屏幕上。
图元:Primitive,包含点,线段,线条、闭合线条、三⻆形、三角带、三角扇七种,如下图
裁剪: 图元不在视锥范围内的时候(视锥范围也叫裁剪空间,每个顶点坐标的裁剪空间范围 gl_Position 的第四个值 w,一般是 1),会对其进行裁剪。如下图,红色三角直接被删除,黄色三角被裁剪掉一部分,并重新创建了两个新的定点。
图元裁剪
背面剔除: 剔除那些背对摄像机或观察者的图元,是默认情况下,面剔除是关闭的,我们可以在初始化上下文后,去开启面剔除的能力。(通过相机方向点的顺序来判断是否背向相机)
背面剔除
屏幕映射: 图元NDC坐标向屏幕坐标的变换,会有平移和缩放。也有其他叫法,例如视口变换。
光栅化: 可以理解成栅格化或者像素化,通过采样将图元离散成片元,会默认基于各个顶点的属性对内每个片元进行进行线性插值处理。在经过一系列处理后最终转换为像素,从而呈现在显示设备上的过程,本质是几何离散化。
抗锯齿:采样错误会造成锯齿(Jaggies)效果,学名叫做走样(Aliasing),解决锯齿问题就叫做反走样(Antialiasing)。采样错误还会出现摩尔纹、车轮效果等问题。
片元:二维图象上每个点都包含了颜色、深度、法线和纹理数据。将该点和相关信息叫做一个片元(fragment)
象素:片元比像素多了许多信息,在光栅化中纹理映射之后图元信息转化为了像素。
顶点着色器: 对顶点坐标进行处理的可编程代码,有一些内置变量,例如:gl_Position。
片元着色器: 对片元进行着色处理的可编程代码,有一些内置变量,例如:gl_FragColor。
着色器语言: GLSL ES 语言,类似 c 的语法,最新的是 450 版本。
模版测试: 默认是关闭的,可以设置模板实现。参见:模板测试。
深度测试:也叫深度检测,用来控制物体前后遮挡效果,如果不开启,后绘制的在上面。参见:深度测试。
深度冲突: 开启深度检测后,如果两个面距离的很近,就会产生闪烁效果,可以指定偏移量来解决。
其他名词:blog.csdn.net/u014800094/…
学习路径
先阅读一些基础的书籍:《WebGL 编程指南》
教程网站:
WebGL基本原理 webglfundamentals.org/webgl/lesso…
WebGL2基本原理 webgl2fundamentals.org/webgl/lesso…
参考链接:
zhuanlan.zhihu.com/p/465212097
zhuanlan.zhihu.com/p/438742595
如有帮助请点赞收藏,纰漏之处欢迎指正! 也欢迎关注公众号交流知识哇😄