豆皮粉儿,又见面啦!今天由字节跳动的"yancy"童鞋给你们重磅推出一篇WebGL
的干货"WebGL基础:着色器基础"!准备好了吗?接下来让咱们开启奇幻旅程,进入 3D
的世界。javascript
本文做者:yancyjava
3D
首先咱们要介绍的是几个概念,这是咱们要进入到 3D
不可或缺的内容。认识一下它们吧。编程
这几个概念在WebGL
中属于最多见的内容。缓存
实际生活中,咱们的目光老是以咱们的眼睛为起始点,到达咱们想要看到的物体,同时,随着咱们观察的角度不一样,物体也会呈现不同的形态。以一张图说明吧。markdown
如此几个内容,建立出了3D
世界的基本显示模型,因而可知其重要程度。后面咱们也会说到如何在 WebGL
中设定这几个内容。也会有的小伙伴把视点称为相机,目标点称为画布。实际上是同样的道理。按照本身的理解记忆就好。函数
可视范围指的是咱们所能看到的最大范围。如:通常状况下咱们看不到本身身后的事物。性能
众所周知,三维物体具备深度的概念。在咱们的理解中,深度就是 z
轴。测试
虽然咱们能够将物体放置在三维空间中的任何位置,可是在WebGL
中,可视范围以外的物体是不被绘制的,这也是为了节省开销。spa
水平视角、垂直视角、可视深度
定义了可视空间的概念。设计
可视空间分为两种。
若是想渲染 3D
图形,就须要通过一系列的步骤,这些步骤称为渲染管线。在开发 WebGL
程序时,咱们就须要经过着色器语言跟GPU进行沟通,用来设定咱们须要渲染和显示的图形。
因而可知:着色器是编写WebGL
时最重要的一点(没有之一)。咱们之因此能生成并操做3D
图像,都是由于着色器在起做用。WebGL
中着色器分为两种。顶点着色器和片元着色器。
这里的顶点表明的是组成物体的每个点。
顶点着色器的功能主要是将位置数据通过矩阵变换、计算光照以后生成顶点颜色、变换纹理坐标。并将生成的数据输出到片元着色器。
片元着色器的做用是将光栅化阶段生成的每一个片元,计算出每一个片元的最终元素。
注:
因为着色器内容比较重要,这里咱们先引入这两个概念,先简单理解就能够,后面专门对着色器进行分享。
了解了第一小节的内容以后,咱们开始进入到WebGL
开发实战中。
还记得Canvas
中第一步须要干什么吗?
没错,须要获取 Canvas
元素和绘图上下文。WebGL
开发也不例外,也须要首先获取元素和绘图上下文。形以下方代码所示:
获取到绘图上下文以后,咱们须要初始化WebGL
的着色器了,着色器代码是以字符串的形式嵌入到渲染程序中,因此咱们须要编写两个着色器的字符串。
两个着色器代码都是以字符串的形式存在,并在执行渲染时嵌入到渲染流程内。
说明:
void main() {}
: 建立一个主函数。gl_Position
: 指定绘制的坐标,接收一个拥有4个浮点份量的vec4
数据。分别表明 x,y,z,w
数据gl_PointSize
: 表示要绘制图形的尺寸大小。gl_FragColor
: 定义图形颜色,1.0 0.0 0.0 1.0
分别表明r g b a
固然,只是编写完着色器代码依然不能完成渲染工做,接下来咱们就须要将着色器添加到渲染流程内
完成上述两步以后,咱们就须要将着色器代码添加到着色器中。看下例子。
完成编译以后,咱们须要将着色器添加到渲染程序中。
完成上述步骤以后,就能够绘制咱们的图形了。这里咱们以一个点为例。在画布上绘制一个点出来。
gl.drawArrays(gl.POINTS, 0, 1);
复制代码
此时就能够打开页面,看到咱们绘制的这个点了。
总结代码:
WebGL
的渲染依赖底层 GPU
的渲染能力。因此 WebGL
渲染流程和 GPU
内部的渲染管线是相符的。
渲染管线的做用是将3D模型转换为2维图像。
在早期,渲染管线是不可编程的,叫作固定渲染管线,工做的细节流程已经固定,修改的话须要调整一些参数。
现代的 GPU
所包含的渲染管线为可编程渲染管线,能够经过编程 GLSL,着色器语言
来控制一些渲染阶段的细节。
(心理承受弱的同窗可跳过此小节)
WebGL
的渲染过程分为如下几项:
这里一系列的名词可能会吓到不少同窗,千万别被名词吓到哟,接下来的过程当中会详细说明。也但愿经过本文可让你们理解基本的渲染流程。附图解一张,助你们理解。
顶点着色器的做用是经过计算得到最终的顶点坐标, 如:
A --> () => {…………} ==> A1
:坐标 A
通过一系列的计算,最终获取坐标 A1
B --> () => {…………} ==> B1
:坐标 B
通过一系列的计算,最终获取坐标 B1
顶点着色器计算出来的坐标将会渲染到最终的显示画布上。
此外,顶点着色器还会计算以下内容:颜色、纹理坐标、顶点尺寸……
在顶点着色器阶段一般会涉及到三个类型的变量。
像 attribute
这个变量以前咱们就用到过,用来设置了顶点的位置和大小。 回顾一下
其余的两个变量暂时没有用到,接下来的内容里会用到这两种类型的变量。敬请期待😁
什么是图元?
描述各类图形元素的函数叫作图元,描述几何元素的称为几何图元(点,线段或多边形)。点和线是最简单的几何图元
通过顶点着色器计算以后的坐标会被组装成组合图元。
接下来经过一组图解来看看渲染器如何进行图元装配和光栅化
图元就是一个点、一条线段、或者是一个多边形。
什么是图元装配呢? 简单理解就是说将咱们设置的顶点、颜色、纹理等内容组装称为一个可渲染的多边形的过程。
注意:
如何组装取决于 gl.drawArrays(type, count)
中的 type
类型,本文最后有详细的内容。
在以前的文章里,咱们就使用 gl.POINTS
来绘制了一个点。
片元:二维图象上每一个点都包含了颜色、深度和纹理数据。这样一个点称为片元
光栅化能够简单理解为如下内容:
经过图元装配生成的多边形,计算像素并填充,剔除不可见的部分,剪裁掉不在可视范围内的部分。最终生成可见的带有颜色数据的图形并绘制。
光栅化流程图解:
WebGL
中,咱们也能够设定物体的背面不可见,那么在渲染过程当中,就会将不可见的部分剔除,不参与绘制。节省渲染开销。接收光栅化阶段生成的片元,在光栅化阶段中,已经计算出每一个片元的颜色信息,这一阶段会将片元作逐片元挑选的操做,处理过的片元会继续向后面的阶段传递。
经过模板测试和深度测试来肯定片元是否要显示,测试过程当中会丢弃掉部分无用的片元内容,而后生成可绘制的二维图像绘制并显示。
z
轴的值作测试,值比较小的片元内容会覆盖值比较大的。(相似于近处的物体会遮挡远处物体)。下面结合2.2.5的代码,咱们进行流程分析,加深理解。
分析:
首先建立了两个变量 VERTEX_SHADER 顶点着色器
和 FRAGMENT_SHADER 片元着色器
。这两个内容会经过下面的代码添加到顶点着色器和片元着色器中。
以后经过 gl.createShader()
建立了两个着色器。传入不一样的参数便可建立不一样的着色器。建立并关联着色器的步骤比较复杂。当你熟悉这个过程以后,能够将这个过程的代码封装起来做为备用。
接下来,经过 将着色器代码添加到着色器中、编辑着色器、建立程序对象、将着色器添加到程序对象中、关联程序对象、使用程序对象
这一系列的步骤初始化着色器和程序对象。
当全部的前置工做准备就绪以后,就能够调用 gl.drawArrays()
方法来绘制想要的图形。
type
表明要绘制的图形形状,值有如下几种:gl.POINTS: 要绘制一系列的点
gl.LINES: 要绘制了一系列未链接直线段(单独行) gl.LINE_STRIP: 要绘制一系列链接的线段
**gl.LINE_LOOP **: 要绘制一系列链接的线段。它还链接第一个和最后一个顶点,以造成一个环
gl.TRIANGLES: 一系列单独的三角形
gl.TRIANGLE_STRIP: 绘制一个三角带
gl.TRIANGLE_FAN: 绘制一个扇形(三角扇)
first
表明从哪一个点开始count
表明须要使用几个点其余的形状能够本身尝试…………会有意想不到的效果。