属于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.0到1.0)
green 指定绿色值(从0.0到1.0)
blue 指定蓝色值(从0.0到1.0)
alpha 指定透明度值(从0.0到1.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>
暂无评论内容