WebGL编程(4)-基本图形和基本变换

基本图形

基本图形的绘制和顶点的绘制差不多,只需要设置gl.drawArrays()的mode参数对应的值,其他图形都是在基本图形上构成的。
gl.drawArrays(mode, first, count)
mode的可选参数详解

基本图形mode参数描述
gl.POINTS一系列点,绘制在v0,v1,v2…处
线段gl.LINES一系列单独的线段,绘制在(v0,v1)、(v2,v3)、(v4,v5)…处,如果点的个数是奇数,最后一个点将被忽略
线条gl.LINE_STRIP一系列连接的线段,被绘制在(v0,v1)、(v1,v2)、(v2,v3)…处,第1个点是第一条线段的起点,第2点是第1条线段的终点和第2条线段的起点…最后一个点是最后一条线段的终点
回路线条gl.LINE_LOOP一系列连接的线段。与gl.LINE_STRIP绘制的线段相比,增加了一条从最后一个点到第1个点的线段。线段被绘制在(v0,v1)、(v1,v2)…(vn,v0)处,其中vn是最后一个点
三角形gl.TRIANGLES一系列单独的三角形,绘制在(v0,v1,v2),(v3,v4,v5)…处,如果点的个数不是三的整数倍,余下的点将被忽略
三角带gl.TRIANGLE_STRIP一些了带状的三角形,前三个点构成了第1个三角形,从第2个点开始的又三个点构成第2个三角形 (该三角形与前一个三角形共享一条边)。这些三角形被绘制在(v0,v1,v2)、(v2,v1,v3)、(v2,v3,v4)…处,按照逆时针绘制
三角扇面gl.TRIANGLE_FAN一系列三角形组成的类似于扇形的图形,前三个点构成了第1个三角形,第4个点和前一个三角形的最后一条边 组成了接下来的一个三角形。这些三角形被绘制在(v0,v1,v2)、(v0,v2,v3)、(v0,v3,v4)…处

第2个三角形是(v2,v1,v3)而不是(v1,v2,v3),这是为了保证第2个三角形的绘制也是按照逆时针的顺序执行。

图形示例:
在这里插入图片描述

示例代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>基本图形</title>
		<script type="text/javascript" src="js/lib/webgl-debug.js" ></script>
		<script type="text/javascript" src="js/lib/webgl-utils.js" ></script>
		<script type="text/javascript" src="js/lib/cuon-utils.js" ></script>
	</head>
	<body>
		<canvas id='canvas' width="600" height="600">该浏览器不支持WebGL!</canvas>
		
		<script id="vertexShader" type="x-shader/x-vertex">
			attribute vec4 a_Position;
			void main(){
				gl_Position=a_Position;
				//gl_PointSize=5.0;//绘制基本图形时,点的大小无用
			}
		</script>
		
		<script id="fragmentShader" type="x-shader/x-fragment">
			void main(){
				gl_FragColor=vec4(1.0,0.0,0.0,1.0);
			}
		</script>
		
		<script>
			(function main(){
				var canvas=document.getElementById("canvas");
				var vShader=document.getElementById("vertexShader").textContent;
				var fShader=document.getElementById("fragmentShader").textContent;
			
				var gl=getWebGLContext(canvas);
				if(!gl){
					console.log("该浏览器不支持WebGL!");
					return ;
				}
				
				if(!initShaders(gl,vShader,fShader)){
					console.log('初始化着色器失败!');
					return ;
				}
				
				//初始化顶点缓冲区,设置顶点位置
				var n=initVertexBuffer(gl);
				if(n<0){
					console.log('无法获取顶点相关信息!');
					return ;
				}
				
				gl.clearColor(0.0,0.0,0.0,1.0);
				gl.clear(gl.COLOR_BUFFER_BIT);
				
				//gl.drawArrays(gl.POINTS,0,n);
				//绘制三角形
				gl.drawArrays(gl.TRIANGLES,0,n);
			}());
			
			function initVertexBuffer(gl){
				var vertices=new Float32Array([0.0,0.5,-0.5,-0.5,0.5,-0.5]);
				console.log(vertices.length);
				console.log(vertices.BYTES_PER_ELEMENT);
				var n=3;//顶点数
				
				//创建缓冲区对象
				var vertexBuffer=gl.createBuffer();
				if(!vertexBuffer){
					console.log("缓冲区创建失败!");
					return -1;
				}
				//将缓冲区对象绑定到目标
				gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
				//向缓冲区对象写入数据
				gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
				//获取attribute变量的存储位置
				var a_Position=gl.getAttribLocation(gl.program,'a_Position');
				if(a_Position<0){
					console.log('无法获取变量的存储位置!');
					return ;
				}
				
				//将缓冲区对象分配给a_Position变量
				gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
				//将链接a_Position的变量分配给它的缓冲区对象
				gl.enableVertexAttribArray(a_Position);
				
				return n;
			}
		</script>
	</body>
</html>

基本变换

基本变换就是基于每个顶点变换,旋转和缩放本质上还是点的平移。

1.平移

平移就是对应坐标x,y,z相加减

//顶点着色器代码
<script id="vShader" type="x-shader/x-vertex">
			attribute vec4 a_Position;
			uniform vec4 u_Translation;		//平移变量,用uniform修饰,当shader运行后不会改变的数据
			void main(){
				gl_Position=a_Position+u_Translation;
			}
</script>

		<script>
			//rgba(0-1)和rgba(0-255)之间转换乘除255
			(function main(){
				let canvas=document.getElementById("myCanvas");
				let gl=getWebGLContext(canvas);
				if(!gl){
					console.log("该浏览器不支持WebGL!");
					return;
				}
				
				let vShader=document.getElementById("vShader").textContent.trim();
				let fShader=document.getElementById("fShader").textContent.trim();
				if(!initShaders(gl,vShader,fShader)){
					console.log("着色器初始化失败!");
					return;
				}
				
				let a_Position=gl.getAttribLocation(gl.program,"a_Position");
				let u_Translation=gl.getUniformLocation(gl.program,"u_Translation");
				if(a_Position<0 || u_Translation<0){
					console.log("无法获取变量的存储位置");
					return;
				}
				
				//向上平移0.2,向右平移0.3
				gl.uniform4f(u_Translation,0.3,0.2,0.0,0.0);
				
				gl.clearColor(0.0,0.0,0.0,1.0);
				gl.clear(gl.COLOR_BUFFER_BIT);
								
				gl.drawArrays(gl.TRIANGLE_STRIP,0,initVertexBuffer());			
							
				function initVertexBuffer(){
					let vertices=new Float32Array([-0.4,0.4,-0.4,-0.4,0.4,0.4,0.4,-0.4]);
					let num=vertices.length/2;
					
					//创建缓冲区对象
					let vertexBuffer=gl.createBuffer();
					if(!vertexBuffer){
						console.log("缓冲区对象创建失败");
						return;
					}
					
					//将缓冲区对象绑定到目标
					gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
					
					//向缓冲区对象写入数据
					gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
					
					//将缓冲区对象分配给a_Position变量
					gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
					
					//将链接a_position变量与分配给他的缓冲区对象
					gl.enableVertexAttribArray(a_Position);
						
					return num;
				}
			})();
		</script>

2.旋转

基本旋转推到过程(绕z轴旋转为例)
在这里插入图片描述

		<script id="vShader" type="x-shader/x-vertex">
			attribute vec4 a_Position;
			uniform float u_SinB,u_CosB;//声明存储变换角度值得变量
			void main(){
				gl_Position.x=a_Position.x*u_CosB-a_Position.y*u_SinB;
				gl_Position.y=a_Position.y*u_CosB+a_Position.x*u_SinB;
				gl_Position.z=a_Position.z;
				gl_Position.w=1.0;
			}
		</script>
			
			//使用旋转角度求出三角函数值,传递到顶点着色器
				let angle=45.0;
				let radin=Math.PI/180.0*angle;//转为弧度制
				let sinB=Math.sin(radin);
				let cosB=Math.cos(radin);
				
				//获取变量地址
				let u_SinB=gl.getUniformLocation(gl.program,"u_SinB");
				let u_CosB=gl.getUniformLocation(gl.program,"u_CosB");
				//赋值
				gl.uniform1f(u_SinB,sinB);
				gl.uniform1f(u_CosB,cosB);

3.缩放

缩放直接改变齐次坐标:(x,y,z,w)中w的值,也就是顶点中第四个分量,齐次坐标和三维坐标的关系在第二节有描述,w>1.0,图形缩小,w<1.0图形放大,且w必须大于等于0;

			attribute vec4 a_Position;
			uniform float u_SinB,u_CosB,u_ScaleW;
			void main(){
				gl_Position.x=a_Position.x*u_CosB-a_Position.y*u_SinB;
				gl_Position.y=a_Position.y*u_CosB+a_Position.x*u_SinB;
				gl_Position.z=a_Position.z;
				gl_Position.w=u_ScaleW;//设置缩放程度
			}

			
				let u_ScaleW=gl.getUniformLocation(gl.program,"u_ScaleW");
				gl.uniform1f(u_ScaleW,1.5);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值