c = a - b
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const gl = canvas.getContext('webgl')
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT); // 使用预设值来清空缓冲
// 创建着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER)
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
// 绑定数据源
// 声明顶点着色器 attribute 变量
// vec4是4维变量类型
gl.shaderSource(vertexShader, `
attribute vec4 a_Position;
attribute float a_PositSize;
void main(){
gl_Position = a_Position;
gl_PointSize = a_PositSize;
}
`)
// 片元着色器变量 uniform, precision mediump float是片元着色器的规范
gl.shaderSource(fragmentShader, `
precision mediump float;
uniform vec4 u_FragColor;
void main(){
gl_FragColor = u_FragColor;
}
`)
// 编译着色器
gl.compileShader(vertexShader)
gl.compileShader(fragmentShader)
// 创建着色器程序
const program = gl.createProgram()
// 绑定着色器
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
// 连接着色器
gl.linkProgram(program)
// 使用着色器
gl.useProgram(program)
const a_Position = gl.getAttribLocation(program, 'a_Position')
const a_PositSize = gl.getAttribLocation(program, 'a_PositSize')
const u_FragColor = gl.getUniformLocation(program, 'u_FragColor')
const g_points = []; // 存点的位置,如果异步执行drawArrays会导致颜色缓冲区重置,所以在这里我们需要同步执行
canvas.addEventListener('click', function (event) {
// 获取鼠标距离视口尺寸的距离
const { clientX, clientY } = event
// 获取cavans坐标宽高,距离视口尺寸的距离
const { left, top, width, height } = canvas.getBoundingClientRect()
// 鼠标在canvas中的位置
const [cssX, cssY] = [clientX - left, clientY - top]
// canvas坐标转webgl坐标
// canvas画布的中心位置
const [halfWidth, halfHeight] = [width / 2, height / 2]
// 鼠标基于webgl坐标的中心位置
const [xBaseCenter, yBaseCenter] = [cssX - halfWidth, cssY - halfHeight]
// 解决y方向的差异
const yBaseCenterTop = -yBaseCenter
// 解决坐标基底的差异
const [x, y] = [xBaseCenter / halfWidth, yBaseCenterTop / halfHeight]
g_points.push({ x, y, z: Math.random() * 50, color: { r: Math.random(), g: Math.random(), b: Math.random(), a: 1 } }); // z随机改变点位的大小
gl.clear(gl.COLOR_BUFFER_BIT); // 只有在绘制前清空缓冲区,才不会被drawArrays清空底色
g_points.forEach(({ x, y, z, color: { r, g, b, a } }) => {
// gl.vertexAttrib[1234]f()可以为顶点 attibute 变量赋值, 数字代表参数位数,f代表参数类型浮点i整型v代表送数字等...
gl.vertexAttrib2f(a_Position, x, y)
gl.vertexAttrib1f(a_PositSize, z)
gl.uniform4f(u_FragColor, r, g, b, a)
gl.drawArrays(gl.POINTS, 0, 1)
})
})
</script>
</body>
</html>