WebGL 坐标系
- canvas2d画布和webgl画布使用的坐标系都是二维直角坐标系,但它们坐标原点、y 轴的坐标方向,坐标基底都不一样
- canvas2d
- 坐标系的原点在左上角, x轴朝右,y轴朝下
- 1个单位的宽就是一个像素的宽,1个单位的高就是一个像素的高,都是按像素来走
- webgl
- 坐标系的原点在画布中心,x轴朝右,y轴朝上
- 1个单位的宽是画布宽度的一半,1个单位的高就是画布高度的一半
Canvas2D 画图示例
ts
// canvas画布
const canvas = document.getElementById('canvas');
// 二维画笔
const ctx = canvas.getContext('2d');
// 设置画笔的颜色
ctx.fillStyle = 'red';
// 用画笔画一个矩形
ctx.fillRect(100, 100, 300, 200);
WebGL 画出一个点
- webgl并不是基于js来绘制,而是基于专业的三维图形渲染引擎来绘制,也就是 GLSL ES 语言来实现三维绘制
- 在webgl中我们使用js来编程, 基于一个 "程序对象" 的概念来和 GLSL ES 语言 进行通信
html
<canvas id="canvas"></canvas>
<!-- 顶点着色器 -->
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
gl_Position = vec4(0,0,0,1); // 设置点位, 注意webgl坐标系中的单位
gl_PointSize = 50.0; // 设置尺寸
}
</script>
<!-- 片元着色器 -->
<script id="fragmentShader" type="x-shader/x-fragment">
void main() {
gl_FragColor = vec4(1,1,0,1); // 黄色
}
</script>
<!-- js脚本 -->
<script type="module">
import { initShaders } from "./utils.js";
const canvas = document.querySelector("#canvas");
canvas.width = 200;
canvas.height = 200;
// 获取着色器文本,这里就是上述我们写的GLSL ES语言着色器代码
const vsSource = document.querySelector("#vertexShader").innerText;
const fsSource = document.querySelector("#fragmentShader").innerText;
//三维画笔
const gl = canvas.getContext("webgl");
// 初始化着色器
// 功能:解析着色器文本,整合到程序对象里,关联webgl上下文对象,实现两种语言的相互通信
initShaders(gl, vsSource, fsSource);
// 刷颜色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制顶点 以点来画
gl.drawArrays(gl.POINTS, 0, 1);
</script>
工具脚本 util.js
js
export function initShaders(gl, vsSource, fsSource) {
// 创建程序对象
const program = gl.createProgram();
// 建立着色对象
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
// 把顶点着色对象装进程序对象中
gl.attachShader(program, vertexShader);
// 把片元着色对象装进程序对象中
gl.attachShader(program, fragmentShader);
// 连接webgl上下文对象和程序对象
gl.linkProgram(program);
// 启动程序对象
gl.useProgram(program);
// 将程序对象挂到上下文对象上
gl.program = program;
return true;
}
function loadShader(gl, type, source) {
// 根据着色类型,建立着色器对象
const shader = gl.createShader(type);
// 将着色器源文件传入着色器对象中
gl.shaderSource(shader, source);
// 编译着色器对象
gl.compileShader(shader);
// 返回着色器对象
return shader;
}
- 着色器语言就是 GLSL ES 语言, 不是JS语言
- 顶点着色器(Vertex shader):描述顶点的特征,如位置、颜色等
- 是绘图的框架,类似于html(不恰当的比喻)
- 顶点着色器里的顶点就是补间动画里的关键帧
- 顶点着色器里的顶点就是决定这一条直线的两个点
- 顶点着色程序,要写在type="x-shader/x-vertex" 的script中
- 在顶点着色器中,gl_Position 是顶点的位置,gl_PointSize 是顶点的尺寸,这种名称都是固定写法
- vec4() 是一个4维矢量对象, 将vec4() 赋值给顶点点位gl_Position 的时候,其中的前三个参数是x、y、z,第4个参数默认1.0,
- 片元着色器(Fragment shader):进行逐片元处理,如光照
- 是绘图的装饰,类似于css(不恰当的比喻), 片元着色器不会给顶点着色,而是给顶点间的片元着色
- 片元着色器里的片元就是关键帧之间以某种算法算出的插值, 举个例子,就像是把直线画到画布上后,这两个点之间构成直线的每个像素
- 在webgl里的片元是像素的意思
- 片元着色程序,要写在type="x-shader/x-fragment" 的script中
- 在片元着色器中,gl_FragColor 是片元的颜色
- 注意:
- void main() {...... } 是主体函数
- gl_Position, gl_PointSize, gl_FragColor 是固定写死的着色器语言变量
- 将vec4() 赋值给片元颜色gl_FragColor 的时候,其中的参数是r,g,b,a
- 上述 util.js 中的执行顺序,就是webgl必须要实现的逻辑
- drawArrays