1、着色器
webgl
绘图必须依赖于 着色器,这是一种新的绘图机制,它可以灵活而且强大的绘制二维和三维图形。
首先,需要了解以下什么是着色器
着色器代码写在javaScript
中,以字符串的形式存在。
webgl需要两种着色器代码:
- 顶点着色器
- 片元着色器
1.1 顶点着色器
首先来看一下代码
// 顶点着色器
var vertex_shader_source =
'void main() {' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);' + // 设置顶点坐标
' gl_PointSize = 10.0;' + // 设置顶点的大小
'' +
'}';
上面的字符串是着色器程序,它类似于C
语言,有一个main
入口函数,C语言是强类型的语言,变量的赋值必须类型一致,浮点说必须加小数点等等,上面这种代码叫做GLSL ES
语言,是继承自OpenGL ES
得着色器语言。
顶点着色器是用来描述顶点得特性如位置颜色等等得程序,顶点是二维或者三维空间中的一个点
上面的顶点着色器设置了顶点的位置坐标,和顶点的大小,变量gl_Position
和gl_PointSize
是webgl
内置的变量,所以可以直接使用,但是赋值的类型需要一致。
gl_Position 表示顶点的位置
gl_PointSize 表示顶点的尺寸
类型和变量名 | 描述 |
---|---|
vec4 gl_Position | 表示顶点位置 |
float gl_PointSize | 表示顶点的尺寸(像素数) |
gl_Position变量必须被赋值,否则着色器无法工作,gl_PointSize有一个默认值,不是必须被赋值
float
是浮点数,vec4
表示由四个浮点数组成的矢量,如果你熟悉three.js
,里面有一个类型就是vector4()
vec4
是四个参数,这是一个 齐次坐标,如果最后一个分量是1.0
的话 那么前三个分量就是坐标值,齐次坐标(x, y, z, w)等于 (x/w, y/w, z/w)
1.2 片元着色器
首先来看一下着色器代码
// 片元着色器
var fragment_shader_source =
'void main(){' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);' + //设置顶点颜色
'}';
同样和顶点着色器一样,是一个字符串,也是类似 C语言的代码,片元着色器是对逐个片元进行颜色处理过程的程序。
片元 可以理解为像素,图像的每一个单元
片元着色器中的片元就是显示在屏幕上的一个像素,准确来说是这个像素的位置、颜色和其它信息
2、绘制一个点
暂时把webgl
的坐标系统的远点位置理解为canvas
的中心,也就是(0, 0, 0)
具体代码
1、首先声明两个字符串,顶点着色器和片元着色器程序
// 顶点着色器
var vertex_shader_source =
'void main() {' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);' + // 设置顶点坐标
' gl_PointSize = 10.0;' + // 设置顶点的大小
'' +
'}';
// 片元着色器
var fragment_shader_source =
'void main(){' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);' + //设置顶点颜色
'}';
2、获取canvas并初始化着色器
// 获取 canvas 对象
var canvas = document.getElementById('webgl');
// 获取webgl上下文对象
var gl = getWebGLContext(canvas);
// 初始化着色器
if (!initShader(gl, vertex_shader_source, fragment_shader_source)) {
console.log('初始化着色器失败');
return false;
}
3、清空绘图区域并绘制顶点
// 指定canvas背景颜色
gl.clearColor(0.0, 0.5, 0.5, 1.0);
// 清除颜色缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 1);
上面的initShader
是内部封装的一个方法,暂时不需要了解其中的实现原理
注意:上面的着色器代码是运行在 webgl 系统的程序,是运行在 js 程序中
上面的第三步需要了解几个gl
身上的内置方法
gl.drawArrays(mode, first, count)
这是一个用来绘制各种图形的方法,它可以按照某种模式(mode),来绘制图形
方法名 | 参数 | 返回值 |
---|---|---|
gl.drawArrays(mode, first, count) | mode:绘制方式,first:指定从那个顶点开始绘制,count:绘制需要多少个顶点 | INVALID_ENUM:传入的参数不是前述参数之一,INVALID_VALUE:参数first或者count是负数 |
具体可以绘制,点、 线、面 一些绘制细节后面会阐述
因为我们仅仅是绘制了一个点,所以第一个参数是gl.POINTS
,设置第二个参数为0
,表示从第一个顶点开始绘制,第三个参数是1
表示绘制一个点
示例地址
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绘制一个点</title>
<link rel="stylesheet" href="../css/common.css">
</head>
<body>
<canvas id="webgl" width="512" height="512"></canvas>
</body>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>
<script>
// 顶点着色器
var vertex_shader_source =
'void main() {' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);' + // 设置顶点坐标
' gl_PointSize = 10.0;' + // 设置顶点的大小
'' +
'}';
// 片元着色器
var fragment_shader_source =
'void main(){' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);' + //设置顶点颜色
'}';
(function () {
// 获取 canvas 对象
var canvas = document.getElementById('webgl');
// 获取webgl上下文对象
var gl = getWebGLContext(canvas);
// 初始化着色器
if (!initShader(gl, vertex_shader_source, fragment_shader_source)) {
console.log('初始化着色器失败');
return false;
}
// 指定canvas背景颜色
gl.clearColor(0.0, 0.5, 0.5, 1.0);
// 清除颜色缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 1);
}());
// 初始化着色器方法
function initShader(gl, vertexShaderSource, fragmentShaderSource) {
// 创建顶点着色器对象
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
// 创建片元着色器对象
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// 引入着色器代码
gl.shaderSource(vertexShader, vertexShaderSource);
gl.shaderSource(fragmentShader, fragmentShaderSource);
// 编译顶点和片元着色器代码
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
// 创建程序对象
var program = gl.createProgram();
// 附着附着着色器到程序
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// 链接程序
gl.linkProgram(program);
// 使用程序
gl.useProgram(program);
// 返回 program 对象
return program;
}
</script>
</html>