webgl基础:着色器基础
2014 年 4 月 30 日
豆皮粉儿,又见面啦!今天由字节跳动的”yancy”童鞋给大家重磅推出一篇 </b></li>
<li><b>上方向:头顶的方向。</b></li>
</ul>
<p>实际生活中,我们的目光总是以我们的眼睛为起始点,到达我们想要看到的物体,同时,随着我们观察的角度不同,物体也会呈现不一样的形态。以一张图说明吧。</p>
<p></p>
<figure data-size=)


。我们之所以能生成并操作 <code>3D</code>图像,都是因为着色器在起作用。<code>WebGL</code>中着色器分为两种。<b>顶点着色器和片元着色器</b>。</p>
<h3>1.3.1 顶点着色器</h3>
<p><b>这里的顶点代表的是组成物体的每一个点。</b></p>
<p>顶点着色器的功能主要是将位置数据经过矩阵变换、计算光照之后生成顶点颜色、变换纹理坐标。并将生成的数据输出到片元着色器。</p>
<h3>1.3.2 片元着色器</h3>
<p>片元着色器的作用是将<b>光栅化阶段</b>生成的每个片元,计算出每个片元的最终元素。</p>
<p><b>注:</b></p>
<p>由于着色器内容比较重要,这里我们先引入这两个概念,先简单理解就可以,后面专门对着色器进行分享。</p>
<h2>2. 绘制图形</h2>
<h3>2.1 获取绘图上下文</h3>
<p>了解了第一小节的内容之后,我们开始进入到 <code>WebGL</code>开发实战中。</p>
<p>还记得 <code>Canvas</code>中第一步需要干什么吗?</p>
<p>没错,需要获取 <code>Canvas</code> 元素和绘图上下文。<code>WebGL</code> 开发也不例外,也需要首先获取元素和绘图上下文。形如下方代码所示:</p>
<p></p>
<figure data-size=)

{}</code>: 创建一个主函数。</li>
<li><code>gl_Position</code>: 指定绘制的坐标,接收一个拥有4个浮点分量的 <code>vec4</code>数据。分别代表 <code>x,y,z,w</code>数据</li>
<li><code>gl_PointSize</code>: 表示要绘制图形的尺寸大小。</li>
<li><code>gl_FragColor</code>: 定义图形颜色, <code>1.00.00.01.0</code> 分别代表 <code>r g b a</code></li>
</ul>
<h3>2.2.2. 创建着色器</h3>
<p>当然,只是编写完着色器代码依然不能完成渲染工作,接下来我们就需要将着色器添加到渲染流程内</p>
<p></p>
<figure data-size=)


;`</code></pre>
</div>
<p>此时就可以打开页面,看到我们绘制的这个点了。</p>
<p>总结代码:</p>
<p></p>
<figure data-size=)
</b></p>
<p><code>WebGL</code> 的渲染过程分为以下几项:</p>
<ul>
<li><b>顶点着色器</b></li>
<li><b>图片装配</b></li>
<li><b>光栅化</b></li>
<li><b>片元着色器</b></li>
<li><b>逐片段操作(本文不会分享此内容)</b></li>
<li><b>裁剪测试</b></li>
<li><b>多重采样操作</b></li>
<li><b>背面剔除</b></li>
<li><b>模板测试</b></li>
<li><b>深度测试</b></li>
<li><b>融合</b></li>
<li><b>缓存</b></li>
</ul>
<p>这里一系列的名词可能会吓到很多同学,千万别被名词吓到哟,接下来的过程中会详细说明。也希望通过本文可以让大家理解基本的渲染流程。附图解一张,助大家理解。</p>
<p></p>
<figure data-size=)
=>{…………}==>A1</code>:坐标 <code>A</code> 经过一系列的计算,最终获取坐标 <code>A1</code></li>
<li><code>B-->()=>{…………}==>B1</code>:坐标 <code>B</code> 经过一系列的计算,最终获取坐标 <code>B1</code></li>
<li>…………</li>
</ul>
<p>顶点着色器计算出来的坐标将会渲染到最终的显示画布上。</p>
<p>此外,顶点着色器还会计算如下内容:<b>颜色、纹理坐标、顶点尺寸……</b></p>
<p>在顶点着色器阶段通常会涉及到三个类型的变量。</p>
<ul>
<li><b>attribute</b>:针对单一顶点生效。</li>
<li>通常用于:顶点位置、顶点大小等内容</li>
<li><b>uniform</b>:影响所有顶点</li>
<li>通常用于:旋转、平移、缩放等位置变换、颜色处理等内容。</li>
<li><b>varying</b>:可通过顶点着色器传入到片元着色器。</li>
</ul>
<p>像 <code>attribute</code> 这个变量之前我们就用到过,用来设置了顶点的位置和大小。回顾一下</p>
<p></p>
<figure data-size=)
。点和线是最简单的几何图元</b><br />经过顶点着色器计算之后的坐标会被组装成<b>组合图元</b>。<br />接下来通过一组图解来看看渲染器如何进行图元装配和光栅化</p></blockquote>
<h3>通俗解释</h3>
<p><b>图元就是一个点、一条线段、或者是一个多边形。</b></p>
<h3>5.1 图元装配</h3>
<p>什么是图元装配呢?简单理解就是说将我们设置的顶点、颜色、纹理等内容组装称为一个可渲染的多边形的过程。</p>
<p><b>注意:</b></p>
<p>如何组装取决于 <code>gl.drawArrays(type,count)</code> 中的 <code>type</code> 类型,本文最后有详细的内容。</p>
<p>在之前的文章里,我们就使用 <code>gl.POINTS</code> 来绘制了一个点。</p>
<h3>5.2 光栅化</h3>
<p><b>片元:二维图象上每个点都包含了颜色、深度和纹理数据。这样一个点称为片元</b></p>
<p>光栅化可以简单理解为以下内容:</p>
<p>通过图元装配生成的多边形,计算像素并填充,<b>剔除</b>不可见的部分,<b>剪裁</b>掉不在可视范围内的部分。最终生成可见的带有颜色数据的图形并绘制。</p>
<p>光栅化流程图解:</p>
<p></p>
<figure data-size=)
。</li>
<li><b>模板测试:</b>模拟观察者的观察行为,可以接为镜像观察。标记所有镜像中出现的片元,最后只绘制有标记的内容。</li>
</ul>
<h2>7. 实例分析</h2>
<p>下面结合2.2.5的代码,我们进行流程分析,加深理解。</p>
<p><b>分析:</b></p>
<ul>
<li>首先创建了两个变量 <code>VERTEX_SHADER顶点着色器</code> 和 <code>FRAGMENT_SHADER片元着色器</code>。这两个内容会通过下面的代码添加到顶点着色器和片元着色器中。</li>
<li>之后通过 <code>gl.createShader()</code> 创建了两个着色器。传入不同的参数即可创建不同的着色器。创建并关联着色器的步骤比较复杂。当你熟悉这个过程之后,可以将这个过程的代码封装起来作为备用。</li>
<li>接下来,通过 <code>将着色器代码添加到着色器中、编辑着色器、创建程序对象、将着色器添加到程序对象中、关联程序对象、使用程序对象</code> 这一系列的步骤初始化着色器和程序对象。</li>
<li>当所有的前置工作准备就绪之后,就可以调用 <code>gl.drawArrays()</code> 方法来绘制想要的图形。</li>
</ul>
<h3>7.1 gl.drawArrays(type, first, count)</h3>
<h3>1. <code>type</code> 代表要绘制的图形形状,值有以下几种:</h3>
<blockquote><p><b>gl.POINTS</b>: 要绘制一系列的点<br /><b>gl.LINES</b>: 要绘制了一系列未连接直线段(单独行)<b>gl.LINE_STRIP</b>: 要绘制一系列连接的线段<br />*gl.LINE_LOOP *: 要绘制一系列连接的线段。它还连接第一个和最后一个顶点,以形成一个环<br /><b>gl.TRIANGLES</b>: 一系列单独的三角形<br /><b>gl.TRIANGLE_STRIP</b>: 绘制一个三角带<br /><b>gl.TRIANGLE_FAN</b>: 绘制一个扇形(三角扇)</p></blockquote>
<h3>2. <code>first</code> 代表从哪个点开始</h3>
<h3>3. <code>count</code> 代表需要使用几个点</h3>
<h3>栗子:</h3>
<p></p>
<figure data-size=)


WebGL
的干货”WebGL基础:着色器基础”!准备好了吗?接下来让我们开启奇幻旅程,进入 3D
的世界。
</b></li>
<li><b>上方向:头顶的方向。</b></li>
</ul>
<p>实际生活中,我们的目光总是以我们的眼睛为起始点,到达我们想要看到的物体,同时,随着我们观察的角度不同,物体也会呈现不一样的形态。以一张图说明吧。</p>
<p></p>
<figure data-size=)


。我们之所以能生成并操作 <code>3D</code>图像,都是因为着色器在起作用。<code>WebGL</code>中着色器分为两种。<b>顶点着色器和片元着色器</b>。</p>
<h3>1.3.1 顶点着色器</h3>
<p><b>这里的顶点代表的是组成物体的每一个点。</b></p>
<p>顶点着色器的功能主要是将位置数据经过矩阵变换、计算光照之后生成顶点颜色、变换纹理坐标。并将生成的数据输出到片元着色器。</p>
<h3>1.3.2 片元着色器</h3>
<p>片元着色器的作用是将<b>光栅化阶段</b>生成的每个片元,计算出每个片元的最终元素。</p>
<p><b>注:</b></p>
<p>由于着色器内容比较重要,这里我们先引入这两个概念,先简单理解就可以,后面专门对着色器进行分享。</p>
<h2>2. 绘制图形</h2>
<h3>2.1 获取绘图上下文</h3>
<p>了解了第一小节的内容之后,我们开始进入到 <code>WebGL</code>开发实战中。</p>
<p>还记得 <code>Canvas</code>中第一步需要干什么吗?</p>
<p>没错,需要获取 <code>Canvas</code> 元素和绘图上下文。<code>WebGL</code> 开发也不例外,也需要首先获取元素和绘图上下文。形如下方代码所示:</p>
<p></p>
<figure data-size=)

{}</code>: 创建一个主函数。</li>
<li><code>gl_Position</code>: 指定绘制的坐标,接收一个拥有4个浮点分量的 <code>vec4</code>数据。分别代表 <code>x,y,z,w</code>数据</li>
<li><code>gl_PointSize</code>: 表示要绘制图形的尺寸大小。</li>
<li><code>gl_FragColor</code>: 定义图形颜色, <code>1.00.00.01.0</code> 分别代表 <code>r g b a</code></li>
</ul>
<h3>2.2.2. 创建着色器</h3>
<p>当然,只是编写完着色器代码依然不能完成渲染工作,接下来我们就需要将着色器添加到渲染流程内</p>
<p></p>
<figure data-size=)


;`</code></pre>
</div>
<p>此时就可以打开页面,看到我们绘制的这个点了。</p>
<p>总结代码:</p>
<p></p>
<figure data-size=)
</b></p>
<p><code>WebGL</code> 的渲染过程分为以下几项:</p>
<ul>
<li><b>顶点着色器</b></li>
<li><b>图片装配</b></li>
<li><b>光栅化</b></li>
<li><b>片元着色器</b></li>
<li><b>逐片段操作(本文不会分享此内容)</b></li>
<li><b>裁剪测试</b></li>
<li><b>多重采样操作</b></li>
<li><b>背面剔除</b></li>
<li><b>模板测试</b></li>
<li><b>深度测试</b></li>
<li><b>融合</b></li>
<li><b>缓存</b></li>
</ul>
<p>这里一系列的名词可能会吓到很多同学,千万别被名词吓到哟,接下来的过程中会详细说明。也希望通过本文可以让大家理解基本的渲染流程。附图解一张,助大家理解。</p>
<p></p>
<figure data-size=)
=>{…………}==>A1</code>:坐标 <code>A</code> 经过一系列的计算,最终获取坐标 <code>A1</code></li>
<li><code>B-->()=>{…………}==>B1</code>:坐标 <code>B</code> 经过一系列的计算,最终获取坐标 <code>B1</code></li>
<li>…………</li>
</ul>
<p>顶点着色器计算出来的坐标将会渲染到最终的显示画布上。</p>
<p>此外,顶点着色器还会计算如下内容:<b>颜色、纹理坐标、顶点尺寸……</b></p>
<p>在顶点着色器阶段通常会涉及到三个类型的变量。</p>
<ul>
<li><b>attribute</b>:针对单一顶点生效。</li>
<li>通常用于:顶点位置、顶点大小等内容</li>
<li><b>uniform</b>:影响所有顶点</li>
<li>通常用于:旋转、平移、缩放等位置变换、颜色处理等内容。</li>
<li><b>varying</b>:可通过顶点着色器传入到片元着色器。</li>
</ul>
<p>像 <code>attribute</code> 这个变量之前我们就用到过,用来设置了顶点的位置和大小。回顾一下</p>
<p></p>
<figure data-size=)
。点和线是最简单的几何图元</b><br />经过顶点着色器计算之后的坐标会被组装成<b>组合图元</b>。<br />接下来通过一组图解来看看渲染器如何进行图元装配和光栅化</p></blockquote>
<h3>通俗解释</h3>
<p><b>图元就是一个点、一条线段、或者是一个多边形。</b></p>
<h3>5.1 图元装配</h3>
<p>什么是图元装配呢?简单理解就是说将我们设置的顶点、颜色、纹理等内容组装称为一个可渲染的多边形的过程。</p>
<p><b>注意:</b></p>
<p>如何组装取决于 <code>gl.drawArrays(type,count)</code> 中的 <code>type</code> 类型,本文最后有详细的内容。</p>
<p>在之前的文章里,我们就使用 <code>gl.POINTS</code> 来绘制了一个点。</p>
<h3>5.2 光栅化</h3>
<p><b>片元:二维图象上每个点都包含了颜色、深度和纹理数据。这样一个点称为片元</b></p>
<p>光栅化可以简单理解为以下内容:</p>
<p>通过图元装配生成的多边形,计算像素并填充,<b>剔除</b>不可见的部分,<b>剪裁</b>掉不在可视范围内的部分。最终生成可见的带有颜色数据的图形并绘制。</p>
<p>光栅化流程图解:</p>
<p></p>
<figure data-size=)
。</li>
<li><b>模板测试:</b>模拟观察者的观察行为,可以接为镜像观察。标记所有镜像中出现的片元,最后只绘制有标记的内容。</li>
</ul>
<h2>7. 实例分析</h2>
<p>下面结合2.2.5的代码,我们进行流程分析,加深理解。</p>
<p><b>分析:</b></p>
<ul>
<li>首先创建了两个变量 <code>VERTEX_SHADER顶点着色器</code> 和 <code>FRAGMENT_SHADER片元着色器</code>。这两个内容会通过下面的代码添加到顶点着色器和片元着色器中。</li>
<li>之后通过 <code>gl.createShader()</code> 创建了两个着色器。传入不同的参数即可创建不同的着色器。创建并关联着色器的步骤比较复杂。当你熟悉这个过程之后,可以将这个过程的代码封装起来作为备用。</li>
<li>接下来,通过 <code>将着色器代码添加到着色器中、编辑着色器、创建程序对象、将着色器添加到程序对象中、关联程序对象、使用程序对象</code> 这一系列的步骤初始化着色器和程序对象。</li>
<li>当所有的前置工作准备就绪之后,就可以调用 <code>gl.drawArrays()</code> 方法来绘制想要的图形。</li>
</ul>
<h3>7.1 gl.drawArrays(type, first, count)</h3>
<h3>1. <code>type</code> 代表要绘制的图形形状,值有以下几种:</h3>
<blockquote><p><b>gl.POINTS</b>: 要绘制一系列的点<br /><b>gl.LINES</b>: 要绘制了一系列未连接直线段(单独行)<b>gl.LINE_STRIP</b>: 要绘制一系列连接的线段<br />*gl.LINE_LOOP *: 要绘制一系列连接的线段。它还连接第一个和最后一个顶点,以形成一个环<br /><b>gl.TRIANGLES</b>: 一系列单独的三角形<br /><b>gl.TRIANGLE_STRIP</b>: 绘制一个三角带<br /><b>gl.TRIANGLE_FAN</b>: 绘制一个扇形(三角扇)</p></blockquote>
<h3>2. <code>first</code> 代表从哪个点开始</h3>
<h3>3. <code>count</code> 代表需要使用几个点</h3>
<h3>栗子:</h3>
<p></p>
<figure data-size=)


WebGL
的干货”WebGL基础:着色器基础”!准备好了吗?接下来让我们开启奇幻旅程,进入 3D
的世界。