将自己在掘金上发的笔记搬了过来:WebGL基础、个人博客
OpenGL, OpenGL ES, WebGL, GLSL, GLSL ES API Tables (umich.edu)
步骤
如图,针对几个单词进行解释:
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
// 创建上下文, 注意兼容
function create3DContext(canvas, options) {
const names = ['webgl', 'experimental-webgL','webkit-3d','moz-webgl']; // 特性判断
if(options.webgl2) names.unshift(webgl2);
let context = null;
for(let ii = 0; ii < names.length; ++ii) {
try {
context = canvas.getContext(names[ii], options);
} catch(e) {
// no-empty
}
if(context) {
break;
}
}
return context;
}
Vertex Shader(顶点着色器)
通过类型数组position,并行处理每个顶点的位置
attribute vec2 position;// vec2 二维向量
void main() {
gl_PointSize = 1.0;
gl_Position = vec4(position, 1.0, 1.0);
}
Fragment Shader(片元着色器)
为顶点轮廓包围的区域内所有像素进行着色
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);//对应rgba(255,0,0,1.0),红色
}
其具体步骤如下:
创建顶点着色器和片元着色器代码:
// 顶点着色器程序代码
const vertexShaderCode = `
attribute vec2 position;
void main() {
gl_PointSize = 1.0;
gl_Position = vec4(position, 1.0, 1.0);
}
`;
// 片元着色器程序代码
const fragmentShaderCode = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
使用 createShader()
创建着色器对象
使用 shaderSource()
设置着色器的程序代码
使用 compileShader()
编译一个着色器
// 顶点着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertex);
gl.compileShader(vertexShader);
// 片元着色器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragment);
gl.compileShader(fragmentShader);
使用**createProgram()
** 创建 WebGLProgram
对象
使用 attachShader()
往 WebGLProgram
添加一个片段或者顶点着色器。
使用 **linkProgram()
**链接给定的WebGLProgram
,从而完成为程序的片元和顶点着色器准备GPU代码的过程。
使用 useProgram()
将定义好的WebGLProgram
对象添加到当前的渲染状态
// 创建着色器程序并链接
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
通过一个顶点数组表示其顶点,使用 createBuffer()
创建并初始化一个用于储存顶点数据或着色数据的WebGLBuffer
对象并返回bufferId
,然后使用 bindBuffer()
将给定的 bufferId
绑定到目标并返回,最后使用**bufferData()
**,将数据绑定至buffer中。
// 顶点数据
const points = new Float32Array([
-1, -1,
0, 1,
1, -1,
]);
// 创建缓冲区
const bufferId = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
getAttribLocation() 返回了给定
WebGLProgram
对象中某属性的下标指向位置。vertexAttribPointer() 告诉显卡从当前绑定的缓冲区(bindBuffer()指定的缓冲区)中读取顶点数据。
enableVertexAttribArray() 可以打开属性数组列表中指定索引处的通用顶点属性数组。
const vPosition = gl.getAttribLocation(program, 'position'); // 获取顶点着色器中的position变量的地址
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0); // 给变量设置长度和类型
gl.enableVertexAttribArray(vPosition); // 激活这个变量
Output
drawArrays() 从向量数组中绘制图元
// output
gl.clear(gl.COLOR_BUFFER_BIT); //清除缓冲的数据
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);
看看人家canvas2D,绘制同样的三角形:
// canvas 简单粗暴,都封装好了
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(250, 0);
ctx.lineTo(500, 500);
ctx.lineTo(0, 500);
ctx.fillStyle = 'red';
ctx.fill();
mesh-js/mesh.js: A graphics system born for visualization . (github.com)
const {Renderer, Figure2D, Mesh2D} = meshjs;
const canvas = document.querySelector ('canvas');
const renderer = new Renderer(canvas);
const figure = new Figure2D();
figurie.beginPath();
figure.moveTo(250, 0);
figure.lineTo(500,500);
figure.lineTo(0, 500);
const mesh = new Mesh2D(figure, canvas);
mesh.setFill({
color: [1, 0, 0, 1],
});
renderer.drawMeshes([mesh]);
使用Earcut进行三角剖分
const vertices = [
[-0.7, 0.5],
[-0.4, 0.3],
[-0.25, 0.71],
[-0.1, 0.56],
[-0.1, 0.13],
[0.4, 0.21],
[0, -0.6],
[-0.3, -0.3],
[-0.6, -0.3],
[-0.45, 0.0],
];
const points = vertices.flat();
const triangles = earcut(points)
由设计师导出给我们,再提取
SpriteJS/next - The next generation of spritejs.
这就是数字图像处理相关的知识了(学过的都还回来了.jpg)
从线性变换到齐次矩阵
老师的又一个栗子:Apply Transforms
3D标准模型的四个齐次矩阵(mat4)
这节课老师非常详尽的讲解了WebGL的绘图及其相关库,展示了很多有意思的WebGL小项目~
本文引用的大部分内容来自月影老师的课和MDN!月影老师,tql!