上一章说到,着色器是以字符串的形式传入initShaders(), 然后在WebGL系统中,着色器就建立好了并随时可以使用。 顶点着色器先执行,它对gl_Position变量和gl_PointSize变量进行赋值,并将它们传入片元着色器,然后片元着色器再执行。 实际上,片元着色器接收到的是经过光栅化处理后的片元值。 我们这里简化流程,后续将会进行解释,可以简单认为这两个变量从顶点着色器传入了片元着色器。

如何画出一个点

已经初始化了着色器,下面来看看如何绘制出一个点。 需要三个信息来画出这个点:位置,尺寸, 颜色。
顶点着色器将指定点的位置和尺寸, 在这个示例中,点的位置是(0.0, 0.0, 0.0)而点的尺寸是10.0
片元着色器将指定点的颜色。 在这个示例中点的颜色是(1.0, 0.0, 0.0, 1.0)

顶点着色器

现在来看看上一章中我们顶点着色器的代码

  1. //顶点着色器程序
  2. var VSHADER_SOURCE="" +
  3. "void main(){\n" +
  4. " gl_Position = vec4(0.0,0.0,0.0,1.0);\n" +//设置坐标
  5. " gl_PointSize = 10.0;\n" +//设置尺寸
  6. "}\n";

和c语言一样,必须包含一个main函数。 main前面的关键字表示这个函数会不会有返回值。 还有,不能为main指定参数。 首先赋值坐标,然后赋值尺寸。这两个变量是顶点着色器中的,而且有着特殊的含义。

类型和变量名 描述
gl_Position 表示顶点的位置
float gl_PointSize 表示点的尺寸 (像素)

注意:gl_Position必须被赋值,否则着色器无法正常工作, gl_PointSize不是必须的, 如果不赋值会取默认值1.0。

作为前端,看到这个变量类型我们会感到惊讶。和js不同,GLSL ES是一种强类型的编程语言。
GLSE中的数据类型

类型 描述
float 表示浮点数
vec4 表示由四个浮点数组成的矢量(float, float, float, float)

注意 赋值给gl_Position的矢量中,我们添加了第四个参数1.0作为第四个分量。有四个分量组成的矢量被称为齐次坐标, 因为它能够提高处理三维数据的效率, 所以在三维图形系统中被大量使用。虽然齐次坐标是四维的,但是如果最后一个分量是1.0, 那个这个齐次坐标就可以表示前三个分量为坐标值的那个点。

片元着色器

顶点着色器控制点的位置和大小,片元着色器控制点的颜色。片元就是显示在屏幕上的一个像素。
片元着色器的作用就是处理片元,使其显示在屏幕上。在回顾下片元着色器的代码。

  1. //片元着色器程序
  2. var FSHADER_SOURCE = "" +
  3. "void main(){\n" +
  4. " gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n" +//设置颜色
  5. "}\n";

和顶点着色器一样,它也是从main()函数开始执行。
片元着色器将点的颜色赋值给gl_FragColor变量,该变量是片元着色器唯一的内置变量,它控制着像素在屏幕上的最终颜色。

类型和变量名 描述
vec4 gl_FragColor 指定片元颜色(RGBA格式)

对这个内置变量赋值后,相应的像素就会以这个颜色显示。和顶点着色器中的顶点位置一样,颜色值也是vec4类型,包括四个浮点型分量。

绘制操作

建立了着色器之后, 我们就需要进行绘制操作,在这个例子中,就是化一个点。 首先要清空绘制区域,然后使用gl.drawArrays()来进行绘制。

  1. gl.drawArrays(gl.POINTS, 0, 1);

gl.drawArrays()是一个强大的函数, 它可以用来绘制各种图形。
执行顶点着色器,按照mode参数指定的方式绘制图形。

gl.drawArrays(mode, first, count)

参数 mode 指定绘制的方式,可以接收一下常量符号:gl_POINTS,
gl.LINES, gl.LINE_STRIO, gl.LINE_LOOP, gl.TRIANGLES, gl.TRAINGLE_ST, gl.TRAINGLE_FAN
firsr 指定从哪个顶点开始绘制 (整数型)
count 指定绘制需要用到多少个顶点(整数型)
返回值
错误 INVALID_ENUM 传入的mode参数不是前述参数之一
INVALID_VALUS 参数first活count是负数
  1. 示例调用该函数时候,因为我们绘制的是单独的点, 所以设置第一个参数为gl.POINTS;设置第二个参数为0 表示从第一个顶点开始画起, 第三个参数count1,表示在这个简单的程序中仅绘制了一个点。<br /> 现在当程序调用gl.drawArrays()时,顶点着色器将被执行count次, 每次处理一个顶点。 这个例子中着色器只执行一次,我们只绘制一个点。当着色器执行的时候将调用并朱行执行内部的main函数。<br /> 一旦顶点着色器执行完之后,片元着色器就开始执行。<br /> 现在,我们对顶点着色器和片元着色器的工作方式有了一个大概的了解。