【笔记】《WebGL编程指南》学习-第2章WebGL入门(6-改变点的颜色))
程序员文章站
2022-05-23 14:02:31
...
这一节的目标是,在上一节用鼠标点击画点的基础上增加改变颜色的功能,点的颜色取决于其位置。
结果:
可以用 uniform 变量将颜色值传给着色器,其步骤与用 attribute 变量传递的类似。不同的仅仅是,这次数据传输的目标是片元着色器,而非顶点着色器:
- 在片元着色器中准备 uniform 变量。
- 用这个 uniform 变量向 gl_FragColor 赋值。
- 将颜色数据从JS传给该 uniform 变量。
示例程序 ColoredPoints.js
//顶点着色器程序
var VSHADER_SOURCE =
'attribute vec4 a_Position;'+
'void main(){'+
'gl_Position=a_Position;'+
'gl_PointSize=10.0;'+
'}';
//片元着色器程序
var FSHADER_SOURCE=
'precision mediump float;'+
'uniform vec4 u_FragColor;'+
'void main(){'+
'gl_FragColor = u_FragColor;'+
'}';
function main() {
//获取canvas元素
var canvas = document.getElementById("webgl");
if(!canvas){
console.log("Failed to retrieve the <canvas> element");
return;
}
//获取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 initialize shaders.");
return;
}
//获取a_Position变量存储位置
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;
}
//获取u_FragColor 变量存储位置
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
if(!u_FragColor){
console.log('Failed to get the storage location of u_FragColor');
return;
}
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]); //白色
}
//清除<canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
var len = g_points.length;
for(var i = 0; i < len; i++){
var xy=g_points[i];
var rgba = g_colors[i];
//将点的位置传递到a_Position变量中
gl.vertexAttrib3f(a_Position, xy[0], xy[1], 0.0);
//将点的颜色传递到u_FragColor变量中
gl.uniform4f(u_FragColor, rgba[0], rgba[1], rgba[2], rgba[3]);
//绘制点
gl.drawArrays(gl.POINTS, 0, 1);
}
}
uniform 变量
只有顶点着色器才能使用 attribute 变量,使用片元着色器时,你就需要使用 uniform 变量。
在使用 uniform 变量之前,首先需要按照与声明 attribute 变量相同的格式<存储限定符><类型><变量名>来声明 uniform 变量。
在例子中, uniform 变量 u_FragColor 被赋值给 gl_FragColor 变量。向 uniform 变量传数据的方式向 attribute 变量传数据相似:首先获取变量的存储地址,然后再JS程序中按照地址将数据传递过去。
//片元着色器程序
var FSHADER_SOURCE=
'precision mediump float;'+
'uniform vec4 u_FragColor;'+
'void main(){'+
'gl_FragColor = u_FragColor;'+
'}';
这一行使用精度限定词来制定变量的范围和精度,本例中为中度精度,后面第5章会详细讲。
'precision mediump float;'+
获取 uniform 变量的存储地址
//获取u_FragColor 变量存储位置
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
if(!u_FragColor){
console.log('Failed to get the storage location of u_FragColor');
return;
}
可以使用以下方法来获取 uniform 变量的存储地址
向 uniform 变量赋值
有了 uniform 变量的存储地址,就可以使用 gl.uniform4f()向变量中写入数据。该函数的功能和参数与 gl.vertexAttrib[1234]f()相似。
gl.uniform4f()的同族函数
gl.uniform4f()也有一系列同族函数。
结果: