一、 最短的教程
<body onload="main()">
<canvas id="glcanvas" width="640" height="480">
你的浏览器似乎不支持或者禁用了 HTML5 <code><canvas></code> 元素。
</canvas>
</body
// 从这里开始
function main() {
// 获取canvas画布
const canvas = document.querySelector("#glcanvas");
// 初始化 WebGL 上下文
const gl = canvas.getContext("webgl");
// 确认 WebGL 支持性
if (!gl) {
alert("无法初始化 WebGL,你的浏览器、操作系统或硬件等可能不支持 WebGL。");
return;
}
// 使用完全不透明的黑色清除所有图像
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 用上面指定的颜色清除缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
}
- clearColor(r,g,b,a) 参数:红、绿、蓝、透明度,其定义域 [0,1];(注意一下定义域范围)
- 一旦指定了背景色,背景色就会驻存在 WebGL 系统中,在下一次调用 gl.clearColor()之前不会改变。换句话说,如果将来什么时候还想用同一个颜色清空绘图区,没必要再指定一次背景色。
二、着色器
1. 顶点着色器
顶点着色器的内置变量
| 类型和变量名 | 描述 |
|---|---|
| vec4 gl_Position | 表示顶点位置 |
| vec4 gl_PointSize | 表示顶点的尺寸(像素数) |
注意: gl_Position 必须被赋值,否则着色器无法正常工作; gl_PointSize 并不是必须的,若不赋值默认是1.0
齐次坐标:gl_Position:(x,y,z,w), 第四个分量w是齐次坐标。
- 齐次坐标(x,y, z, w)等价于三维坐标(x/w, y/x, z/w)。如果w=1, 可以将其当作三维坐标使用。
- w必须大于等于0
- w趋近0, 那么他所表示的点将趋近无穷远,所以在齐次坐标可以有无穷的概念。
- 齐次坐标存在,使得用矩阵乘法来描述顶点变换成为可能,三维图形系统在计算过程中,通常用齐次坐标来表示顶点的三维坐标。
2. 片元着色器
片元着色器的内置变量webgl学习笔记
| 类型和变量名 | 描述 |
|---|---|
| vec4 gl_FragColor | 指定片元颜色(RGBA格式) |
3. 绘制操作
| 类型和变量名 | 描述 |
|---|---|
| vec4 gl_drawArrays(mode, first,count) | 执行顶点着色器,按照mode参数指定方式绘制图形 |
- mode: 指定绘制的万式,可接收以下常量符号:g1.POINTS,g1.LINES,g1.LINE_STRIP,g1.LINE_LOOP, g1.TRIANGLES,g1.TRIANGLE_STRIP,g1.TRIANGLE_FAN
- first: 指定从哪个顶点开始绘制(整型数)
- count: 指定绘制需要多少个顶点
调用gl.drawArrays() 时, 顶点着色器将被执行 count 次,每次处理一个顶点。
4. WebGL 坐标系
4.1 canvas坐标系
4.2 webGL坐标系
5. attribute 变量 和 uniform 变量
- attribute: 传输和顶点相关的数据 (被用来从外部向内部顶点着色器内传输数据,只有顶点着色器能使用他)
- uniform:与顶点无关的数据
5.1 attribute 获取和赋值
5.1.1 获取 attribute 变量的存储位置
| 类型和变量名 | 描述 |
|---|---|
| gl.getAttribLocation(program, name) | 获取由name参数指定的attribute 变量的存储地址 |
5.1.2 attribute 变量赋值
| 类型和变量名 | 描述 |
|---|---|
| gl.vertexAttrib3f(location, v0, v1, v2) | 获取由name参数指定的attribute 变量的存储地址 |
同族函数:
g1.vertexAttrib1f(location,v0)
g1.vertexAttrib2f(location,v0,v1)
g1.vertexAttrib3f(1ocation,v0,v1,v2)
g1.vertexAttrib4f(location,v0,v1,v2,v3)
5.2 uniform 获取和赋值
只有顶点着色器才能使用attribute变量,使用片元着色器时,你就需要使用uniform变量。或者,你可以使用varying变量。
5.2.1 获取 uniform 变量的存储位置
| 类型和变量名 | 描述 |
|---|---|
| gl.getUniformLocation(program, name) | 获取由name参数指定的 uniform 变量的存储地址 |
5.2.2 uniform 变量 赋值
| 类型和变量名 | 描述 |
|---|---|
| gl.uniform4f (program, v0, v1, v2, v3, v4) | 将数据(v0, v1, v2, v3) 传输给由 location 参数指定的uniform变量 |
同族函数:
g1.uniform1f(location,v0)
g1.uniform2f(location,v0,v1)
g1.uniform3f(location,v0,v1,v2)
g1.uniform4f(location,v0,v1,v2,v3)
三、通过鼠标点击绘点
// ClickedPints.js (c) 2012 matsuda
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' gl_PointSize = 10.0;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// // Get the storage location of a_Position
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
// Register function (event handler) to be called on a mouse press
canvas.onmousedown = function(ev){ click(ev, gl, canvas, a_Position); };
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
}
var g_points = []; // The array for the position of a mouse press
function click(ev, gl, canvas, a_Position) {
var x = ev.clientX; // x coordinate of a mouse pointer
var y = ev.clientY; // y coordinate of a mouse pointer
var rect = ev.target.getBoundingClientRect() ;
x = ((x - rect.left) - canvas.width/2)/(canvas.width/2);
y = (canvas.height/2 - (y - rect.top))/(canvas.height/2);
// Store the coordinates to g_points array
g_points.push(x); g_points.push(y);
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
var len = g_points.length;
for(var i = 0; i < len; i += 2) {
// Pass the position of a point to a_Position variable
gl.vertexAttrib3f(a_Position, g_points[i], g_points[i+1], 0.0);
// Draw
gl.drawArrays(gl.POINTS, 0, 1);
}
}
webgl 和 canvas 坐标转换可参考文章: juejin.cn/post/706736…