WebGL入门(二)-属于WebGL的Hello Word

1.demo效果

在这里插入图片描述
如上图,使用WebGL在400px400px的画布上绘制了一个30px30px的红色方块,看起然简单,但是麻雀虽小,五脏俱全,涵盖了不少知识点,且听我细细道来

2.相关知识点

2.1 Canvas

Canvas即画布,顾名思义就是绘画的地方,Canvas在HTML5中被定义为一个标签,从此前端开发者可以通过这个标签和脚本语言(JavaScript)尽情发挥自己的想象力,Canvas画布不但可以绘制二维图形,同样可以绘制三维图形。

2.1.1 获取Canvas对象

Canvas画布在THML中被定义为一个标签,所以我们需要通过DOM操作函数 getElementById() 方法获取canvas画布对象。

<body>
  <!--canvas标签创建一个宽高均为400像素蓝色背景的画布-->
  <canvas id="webgl" width="400" height="400" style="background-color: blue"></canvas>

  <script>
    //通过getElementById()方法获取canvas画布
    var canvas = document.getElementById('webgl');
  </script>
</body>

2.1.2 获取Canvas的上下文

Canvas可以绘图,但是它不提供绘图方法,而是提供一种叫 上下文(context) 的机制来进行绘图,Canvas对象提供了一个专门获取上下文的方法,就是 getContext() ,getContext()方法既可以获取二维图形的上下文也可以获取三维图形的上下文,怎么使用根据自己的需要

//获取上下文-二维
var gl = canvas.getContext('2d');

//获取上下文-三维
var gl = canvas.getContext('webgl');

2.2 着色器

WebGL 依赖于一种称为 着色器(shader) 的绘图机制进行绘图,它提供了灵活且强大的绘制图形的方法,所有的WebGL程序必须使用它,它很强大,但同时也更复杂。着色器是WebGL的一项重要的和兴机制。在编码过程中它是以字符串的形式嵌入到JavaScript代码中。

2.2.1 着色器分类

WebGL 有两种着色器,顶点着色器(Vertex shader)片元着色器(Fragment shader)

  • 顶点着色器 顶点着色器是用来描述顶点的特性(如位置、大小等)的程序,顶点指的是二维或三维空间中的一个点,端点或交点

  • 片元着色器 进行逐片元处理过程(如光照)的程序,片元是一个WebGL术语,可以理解为像素

2.2.2 着色器的初始化

在这里你需要知道,WebGL程序包括运行在浏览器中的JavaScript程序和运行在WebGL系统的着色器程序这两部分,着色器程序以字符串的形式通过Javascript代码传给WebGL系统。简单说明一下,这里的以字符串形式体现的着色器程序是使用 着色器语言(GLSL ES) 编写的

2.2.2.1 着色器语言数据类型(此例涉及)

这里提及着色器语言的数据类型,是因为该语言是强类型的编程语言,在赋值时=左右的数据类型必须一致,否则程序报错

  • float 表示浮点数
  • vec4 表示四个浮点数组成的矢量
    由四个分量组成的矢量被称为 齐次坐标,齐次坐标(x,y,z,w)等价于三维坐标(x/w,y/w,z/w)即你想把一个三维坐标转换为齐次坐标时,只需要给它添加一个分量,值为1.0

2.2.2.2 顶点着色器的初始化

顶点着色器的初始化实际就是给它的内置变量赋值,它有两个内置变量分别是gl_Position和gl_PointSize

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

注意:gl_Position变量必须被赋值,否则着色器无法正常工作,gl_PointSize不是必须的,缺省时着色器默认取值1.0

顶点着色器初始化的示例

//顶点着色器
var VSHADER_SOURCE = '' +
  'void main(){\\n' +
  //设置顶点位置(坐标原点)
  '  gl_Position =vec4(0.0,0.0,0.0,1.0);\\n' +
  //设置点的大小(30px)
  '  gl_PointSize=30.0;\\n' +
  '}\\n';

2.2.2.3 片元着色器的初始化

顶点着色器控制点的位置和大小,片元着色器控制点的颜色,片元着色器将点的颜色赋值给内置变量gl_FragColor

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

对这个内置变量赋值后,对应的点就会以这个颜色显示。它的类型也是vec4,包括四个浮点型分量,分别代表RGBA的值
片元着色器初始化的示例

//片元着色器
var FSHADER_SOURCE = '' +
  'void main(){\\n' +
  //设置片元颜色(红色)
  ' gl_FragColor = vec4(1.0,0.0,0.0,1.0);\\n' +
  '}\\n';

3.部分WebGL API说明

3.1设置背景色gl.clearColor()

在清空绘图区之前需要设置背景色。一旦指定了背景色后,背景色就会驻存在WebGL系统中,在下次调用gl.clearColor()方法前不会改变

函数功能:指定绘图区域的背景色
-----------------------------------------------------------
调用示例:gl.clearColor(red, green, blue, alpha)
-----------------------------------------------------------
参数		
			red		指定红色值(从0.01.0)
			green	指定绿色值(从0.01.0)
			blue	指定蓝色值(从0.01.0)
			alpha	指定透明度值(从0.01.0)
			小于0.0的值会被截断为0.0,大于1.0的值会被截断为1.0
-----------------------------------------------------------			
返回值		无
-----------------------------------------------------------
错  误		无			

3.2清空绘图区gl.clear()

清空绘图区实际上是清空颜色缓冲区,在WebGL中缓冲区有三类: 颜色缓冲区、深度缓冲区、模板缓冲区

函数功能:将指定缓冲区设置为预定的值-预定的值指的是gl.clearColor()设置的值
-----------------------------------------------------------------------------------
调用示例:gl.clear(buffer)
-----------------------------------------------------------------------------------
参数		
			buffer					指定待清空的缓冲区,位操作位|可以用来指定多个缓冲区
			gl.COLOR_BUFFER_BIT		代表清空颜色缓冲区
			gl.DEPTH_BUFFER_BIT		代表清空深度缓冲区
			gl.STENCIL_BUFFER_BIT	代表清空模板缓冲区
-----------------------------------------------------------------------------------			
返回值		无
-----------------------------------------------------------------------------------
错  误		INVALID_VALUE			缓冲区不是以上三种类型		

如果没有指定背景色(没有调用gl.clearColor()函数),直接调用gl.clear(),那么使用的默认值如下所示

缓冲区名称 默认值 相关函数
颜色缓冲区 (0.0, 0.0, 0.0, 0.0) gl.clearColor(red, green, blue, alpha)
深度缓冲区 1.0 gl.clearDepth(depth)
模板缓冲区 0 gl.clearStencil(s)

3.3绘制操作gl.drawArrays()

建立了着色器之后,我们就要进行绘制了,gl.drawArrays()是一个强大的函数,可以用来绘制各种图形,该函数的规范如下所示

函数功能:执行顶点着色器,按照mode参数指定的方式绘制图形
--------------------------------------------------------------------------
调用示例:gl.drawArrays(mode, first, count)
--------------------------------------------------------------------------
参数		
			mode		指定绘制的方式,可以接收以下常量符号:
						gl.POINTS,gl.LINES,gl.LINE_STRIP,gl.LINE_LOOP
						gl.TRIANGLES,gl.TRIANGLE_STRIP,gl.TRIANGLE_FAN
			first		指定从哪个点开始绘制-整形数
			count		指定要绘制多少个顶点-整形数
--------------------------------------------------------------------------		
返回值		无
--------------------------------------------------------------------------
错  误		INVALID_ENUM			传入的mode参数不是指定参数
			INVALID_VALUE			参数first或count是负数	

4.demo代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>使用WebGL绘制一个点</title>
</head>

<body>
  <!--canvas标签创建一个宽高均为400像素蓝色背景的画布-->
  <canvas id="webgl" width="400" height="400" style="background-color: blue"></canvas>

  <script>
    //通过getElementById()方法获取canvas画布
    var canvas = document.getElementById('webgl');
    //通过方法getContext()获取WebGL上下文
    var gl = canvas.getContext('webgl');

    //顶点着色器
    var VSHADER_SOURCE = '' +
      'void main(){\\n' +
      //设置顶点位置(坐标原点)
      '  gl_Position =vec4(0.0,0.0,0.0,1.0);\\n' +
      //设置点的大小(30px)
      '  gl_PointSize=30.0;\\n' +
      '}\\n';

    //片元着色器
    var FSHADER_SOURCE = '' +
      'void main(){\\n' +
      //设置片元颜色(红色)
      ' gl_FragColor = vec4(1.0,0.0,0.0,1.0);\\n' +
      '}\\n';

    //初始化着色器
    initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE);

    // 设置canvas的背景色
    gl.clearColor(0.0, 0.0, 0.0, 1.0);

    //清空canvas
    gl.clear(gl.COLOR_BUFFER_BIT);

    //开始绘制,绘制顶点,从第一个顶点开始绘制,绘制一个顶点
    gl.drawArrays(gl.POINTS, 0, 1);

    //初始化着色器函数
    function initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE) {
      //创建顶点着色器对象
      var vertexShader = gl.createShader(gl.VERTEX_SHADER);
      //创建片元着色器对象
      var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
      //引入顶点、片元着色器源代码
      gl.shaderSource(vertexShader, VSHADER_SOURCE);
      gl.shaderSource(fragmentShader, FSHADER_SOURCE);
      //编译顶点、片元着色器
      gl.compileShader(vertexShader);
      gl.compileShader(fragmentShader);

      //创建程序对象program
      var program = gl.createProgram();
      //附着顶点着色器和片元着色器到program
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      //链接program
      gl.linkProgram(program);
      //使用program
      gl.useProgram(program);
      //返回程序program对象
      return program;
    }
  </script>
</body>

</html>

© 版权声明
THE END
喜欢就支持一下吧
点赞84 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容