在WebGL中,uniform变量用于在顶点着色器和片元着色器之间传递全局状态信息,这些信息在渲染过程中不会随着顶点的变化而变化。uniform变量可以用来设置变换矩阵、光照参数、材料属性等。由于它们在整个渲染过程中共享,因此可以被所有使用该着色器程序的顶点和片元访问。
1. 声明uniform变量
// 片源着色器源码
const fragmentShaderSource = `
// 声明uniform变量,一定要加分号!!!
uniform vec4 uColor;
void main() {
gl_FragColor = uColor; // r, g, b, a
}`
2. 获取 uniform 变量存储地址
// gl.getUniformLocation(program, name)
// 此方法使用和入参与 gl.getAttribLocation 相同
// program: 包含顶点和片元着色器的程序对象
// name:uniform 变量的名称
const ucolor = gl.getUniformLocation(program, 'ucolor');
3. 给uniform变量赋值
// gl.uniform4f(location, vO, v1, v2, v3 ) v1, v2, v3,v4分别代表r, g, b, a
// location:变量
// v1:第一个分量的值
// v2:第二个分量的值
// v3:第三个分量的值
// v4:第四个分量的值
gl.uniform4f(uColor,1.0, 0.0, 0.0, 1.0);
赋值需要注意的点:声明和赋值是对应的,同时main()中的gl_FragColor也需要对应修改。
- uniform float uColor 对应 gl.uniform1f(uColor,1.0, 0.0, 0.0, 1.0);
- uniform vec2 uColor 对应 gl.uniform2f(uColor,1.0, 0.0);
- uniform ve34 uColor 对应 gl.uniform3f(uColor,1.0, 0.0, 0.0);
- uniform vec4 uColor 对应 gl.uniform4f(uColor,1.0, 0.0, 0.0, 1.0);
uniform float uColor;
void main() {
gl_FragColor = vec(uColor, 0.0, 0.0, 1.0);
}
uniform vec2 uColor;
void main() {
gl_FragColor = vec(uColor.r, uColor.g, 0.0, 1.0);
}
uniform vec3 uColor;
void main() {
gl_FragColor = vec(uColor.r, uColor.g, uColor.b, 1.0);
}
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
4. 设置精度
// 高精度:highp
// 中精度:mediump
// 低精度:lowp
const fragmentShaderSource = `
precision mediump float;// 设置精度
uniform vec4 uColor;
void main() {
gl_FragColor = uColor; // r, g, b, a
}`
5. 完整代码
<!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;
}
canvas {
margin: 50px auto;
display: block;
background: pink;
}
</style>
<title>修改点的颜色</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 vec4 aPosition;
void main() {
gl_Position = aPosition;
gl_PointSize = 5.0;
}`
// 片源着色器源码
const fragmentShaderSource = `
// 4.设置精度
precision mediump float;
// 1.声明uniform变量,一定要加分号!!!
uniform vec4 uColor;
void main() {
gl_FragColor = uColor; // r, g, b, a
}`
const program = initShader(gl, vertexShaderSource, fragmentShaderSource)
const aPosition = gl.getAttribLocation(program, 'aPosition');
// 2.获取返回变量的存储地址
const uColor = gl.getUniformLocation(program, 'uColor');
const points = [];
ctx.onclick = function (e) {
const x = e.clientX;
const y = e.clientY;
const domPosition = e.target.getBoundingClientRect();
const domx = x - domPosition.left;
const domy = y - domPosition.top;
const halfWidth = ctx.offsetWidth / 2;
const halfHeigth = ctx.offsetHeight / 2;
const clickX = (domx - halfWidth) / halfWidth;
const clickY = (halfHeigth - domy) / halfHeigth;
points.push({ clickX, clickY })
points.forEach(element => {
gl.vertexAttrib2f(aPosition, element.clickX, element.clickY)
// 3.给uniform变量赋值
gl.uniform4f(uColor, element.clickX, element.clickY, 0.0, 1.0);
gl.drawArrays(gl.POINTS, 0, 1);
});
}
// 着色器
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;
}
</script>
</body>
</html>