在WebGL编程中,attribute变量是一种特殊类型的变量,用于从客户端传递数据到顶点着色器。这些数据通常包括顶点的位置、颜色、纹理坐标等,它们是与每个顶点直接相关的信息。attribute变量在顶点着色器中声明,并且对于每个顶点来说都是独立的。
一、创建和使用attribute变量流程
-
在顶点着色器中声明attribute变量:attribute vec4 aPosition;
javascript// 顶点着色器源码 const vertexShaderSource = ` // attribute使用位置,只传递顶点着色器,不能在片元着色器中使用 attribute vec4 aPosition; void main() { gl_Position = aPosition; gl_PointSize = 30.0; }`
-
获取attribute变量的存储地址:gl.getAttribLocation(program, 'aPosition');
javascriptconst program = initShader(gl, vertexShaderSource, fragmentShaderSource) // 获取attribute变量,必须在initShader之后使用,因为会用到program这个程序对象 // gl.getAttribLocation(program, name); // 1.program:程序对象 // 2.name:指定想要获取存储地址的attribute变量的名称 // 返回变量的存储地址 const aPosition = gl.getAttribLocation(program, 'aPosition');
-
设置顶点属性的值:gl.vertexAttrib4f(location, v1, v2, v3,v4)
javascript// gl.vertexAttrib4f(location, v1, v2, v3,v4) // v1, v2, v3,v4 分别代表 X, y, Z, W // location:变量 // v1:第一个分量的值 // v2:第二个分量的值 // v3:第三个分量的值 // v4:第四个分量的值 gl.vertexAttrib4f(aPosition, 0.5, 0.5, 0.0, 1.0) // gl.vertexAttrib3f(aPosition, 0.5, 0.5, 0.0) // gl.vertexAttrib2f(aPosition, 0.5, 0.5) // gl.vertexAttrib1f(aPosition, 0.5)
-
绘制一个水平移动的点
javascript// 绘制一个水平移动的点 let x = 0; setInterval(() => { x += 0.1 if (x > 1.0) { x = 0; } // 设置顶点的值 gl.vertexAttrib1f(aPosition, x) // 绘制点 gl.drawArrays(gl.POINTS, 0, 1); }, 200)
二、完整代码
- html页面代码如下:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
}
</style>
<title>webgl三维坐标系</title>
</head>
<body>
<canvas id="canvas" width="400" height="400">
此浏览器不支持canvas
</canvas>
<script src="./js/index.js"></script>
<script>
const ctx = document.getElementById('canvas')
const gl = ctx.getContext('webgl')
// 顶点着色器源码
const vertexShaderSource = `
// attribute使用位置,只传递顶点着色器,不能在片元着色器中使用
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
gl_PointSize = 30.0;
}`
// 片源着色器源码
const fragmentShaderSource = `
void main() {
gl_FragColor = vec4(0.0,0.0,0.0,1.0); // r, g, b, a
}`
// 设置着色器封装后,直接使用
const program = initShader(gl, vertexShaderSource, fragmentShaderSource)
const aPosition = gl.getAttribLocation(program, 'aPosition');
// 绘制一个水平移动的点
let x = 0;
setInterval(() => {
x += 0.1
if (x > 1.0) {
x = 0;
}
gl.vertexAttrib1f(aPosition, x)
// 绘制点
gl.drawArrays(gl.POINTS, 0, 1);
}, 200)
</script>
</body>
</html>
- index.js文件中的initShader方法代码如下:
javascript
function initShader(gl, vertexShaderSource, fragmentShaderSource) {
const vertexShader = gl.createShader(gl.VERTEX_SHADER);// 创建顶点着色器对象
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);// 创建片段着色器对象
gl.shaderSource(vertexShader, vertexShaderSource);// 设置顶点着色器源代码
gl.shaderSource(fragmentShader, fragmentShaderSource);// 设置片段着色器源代码
gl.compileShader(vertexShader);// 编译顶点着色器
gl.compileShader(fragmentShader);// 编译片段着色器
// 创建一个程序对象
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
return program;
}
- 效果如下: