uniform
介绍
uniform变量将颜色值传给着色器,其步骤与用attribute变量传递的类似,不同的仅仅是,这次的数据传输目标上是片元着色器,而非顶点着色器。uniform变量用来从JavaScript程序向顶点着色器和片元着色器传输“一致的”数据
只有顶点着色器才能使用attribute变量,使用片元着色器,你就需要使用uniform变量
·
格式
`
使用步骤
① 在片元着色器中,声明uniform变量
//使用精度限定词来指定变量的范围和精度
'precision mediump float;\n'+
//声明uniform变量
'uniform vec4 u_FragColor;\n'+
② 将uniform变量赋值给gl_FragColor变量
gl_FragColor=u_FragColor;
③ 向uniform变量传输数据
//获取uniform变量的存储位置
var u_FragColor=gl.getUniformLocation(gl.program,'u_FragColor');
↓
在初始化函数中创建了这个程序对象
//获取了存储地址后,就将该JavaScript变量向着色器传入值
gl.uniform4f(u_FragColor,rgba[0],rgba[1],rgba[2],rgba[3]);
gl.getUniformLocation(program,name):获取由name参数指定的uniform变量的存储地址。
参数 | 含义 |
---|---|
program | 指定包含顶点着色器和片元着色器的着色器程序对象 |
name | 指定想要获取其存储地址的uniform变量的名称 |
gl.uniform4f(location,v0,v1,v2):将数据以(v0,v1,v2)传给由location参数指定的uniform变量
参数 | 含义 |
---|---|
location | 指定将要修改的uniform变量的存储位置 |
v0 | 指定填充uniform变量的第一个分量的值 (r) |
v1 | 指定填充uniform变量的第二个分量的值 (g) |
v2 | 指定填充uniform变量的第三个分量的值 (b) |
v3 | 指定填充uniform变量的第三个分量的值 (a) |
gl.uniform4f有一系列同族函数,该系列函数的任务就是为JavaScript向片元着色器中的uniform传值,下面简单介绍
函数 | 说明 |
---|---|
gl.uniform1f(location,v0) | 仅传输一个值,uniform变量的第2、3个分量被设为0.0,第四个分量被设为1.0 |
gl.uniform2f(location,v0,v1) | 填充前两个分类,第三个分量被设为0.0,第四个分量被设为1.0 |
gl.uniform3f(location,v0,v1,v2) | 填充前三个分量,第四个分量被设为1.0 |
gl.uniform4f(location,v0,v1,v2,v3) | 填充了所有四个分类 |
运用了uniform变量,我们就能很方便将顶点的位置从JavaScript传到着色器程序中
代码讲解
稍微改进上一篇文章中的代码,运用uniform变量实现点击不同象限显示不同颜色的点
1.修改click()函数,增加一个存储点颜色的数组,并在点击时判断点在哪个象限,从而填入不同的颜色
//在click()中添加以下代码
var g_colors=[]; //存储点颜色的数组
function click(ev,gl,canvas,a_Position,u_FragColor){
//求x,y
......
if(x>=0.0&&y>=0.0){ //第一象限
g_colors.push([1.0,0.0,0.0,1.0]); //红色
}else if(x<0.0&&y<0.0){ //第三象限
g_colors.push([0.0,1.0,0.0,1.0]); //绿色
}else{ //其他
g_colors.push([1.0,1.0,1.0,1.0]); //白色
}
}
}
完整代码如下:
//ColorsPoints.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Click points</title>
</head>
<body onload="main()">
<canvas id="webgl" width="400" height="400">
Please use the browser supporting "canvas".
</canvas>
<script src="js/ClickPoints.js"></script>
</body>
</html>
//ColorsPoints.js
//顶点着色器
var VSHADER_SOURCE=
'attribute vec4 a_Position;\n'+
'void main(){\n'+
'gl_Position=a_Position;\n'+
'gl_PointSize=10.0;\n'+
'}\n';
//片元着色器
var FSHADER_SOURCE=
'precision mediump float;\n'+
'uniform vec4 u_FragColor;\n'+
'void main(){\n'+
'gl_FragColor=u_FragColor;\n'+
'}\n';
function main(){
//获取<canvas>元素
var canvas=document.getElementById('webgl');
//获取WebGL上下文
var gl=getWebGLContext(canvas);
if(!gl){
console.log('Failed to get the rendering context for WebGL');
return;
}
//初始化着色器
if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
console.log('Failed to initilize shaders.');
return;
}
//获取attribute变量的存储位置
var a_Position=gl.getAttribLocation(gl.program,'a_Position');
if(a_Position<0){
console.log('Failed to get the storage location of a_position');
return;
}
//获取uniform变量的存储位置
var u_FragColor=gl.getUniformLocation(gl.program,'u_FragColor');
//注册鼠标点击事件响应函数
canvas.onmousedown=function(ev){click(ev,gl,canvas,a_Position,u_FragColor)};
//设置<canvas>的背景色
gl.clearColor(0.0,0.0,0.0,1.0);
//用背景色填充<canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
}
var g_points=[]; //鼠标点击位置数组
var g_colors=[]; //鼠标点击颜色的数组
function click(ev,gl,canvas,a_Position,u_FragColor){
var x=ev.clientX;
var y=ev.clientY;
var rect=ev.target.getBoundingClientRect();
x=((x-rect.left)-canvas.width/2)/(canvas.width/2);
y=(canvas.height/2-(y-rect.top))/(canvas.height/2);
//将坐标存储到g_points数组中
g_points.push([x,y]);
if(x>=0.0&&y>=0.0){ //第一象限
g_colors.push([1.0,0.0,0.0,1.0]); //红色
}else if(x<0.0&&y<0.0){ //第三象限
g_colors.push([0.0,1.0,0.0,1.0]); //绿色
}else{ //其他
g_colors.push([1.0,1.0,1.0,1.0]); //白色
}
//每次点击时都清一次背景
gl.clear(gl.COLOR_BUFFER_BIT);
var len=g_points.length;
for(var i=0;i<len;i+=2){
var xy=g_points[i];
var rgba=g_colors[i];
//将点的位置传输到a_Position变量中
gl.vertexAttrib3f(a_Position,xy[0],xy[1],0.0);
//将点的颜色传输到u_Position变量中
gl.uniform4f(u_FragColor,rgba[0],rgba[1],rgba[2],rgba[3]);
//绘制点
gl.drawArrays(gl.POINTS,0,1);
}
}
运行结果如下: