WebGL学习笔记(三)

本文是WebGL学习笔记的第三部分,主要介绍了uniform变量在WebGL中的作用和使用方法。uniform变量用于从JavaScript向顶点着色器和片元着色器传递一致的数据,特别是在片元着色器中代替attribute变量进行数据传输。文章详细阐述了uniform变量的声明、赋值和传输数据的步骤,并通过实例展示了如何使用uniform变量实现点击不同象限显示不同颜色的点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

uniform

介绍

uniform变量将颜色值传给着色器,其步骤与用attribute变量传递的类似,不同的仅仅是,这次的数据传输目标上是片元着色器,而非顶点着色器。uniform变量用来从JavaScript程序向顶点着色器和片元着色器传输“一致的”数据

只有顶点着色器才能使用attribute变量,使用片元着色器,你就需要使用uniform变量

这是上一篇写attribute的文章

·

格式

在这里插入图片描述
`

使用步骤

① 在片元着色器中,声明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);
	}
}
	

运行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值