webGL学习笔记(一)

本文介绍了WebGL的基础知识,包括如何使用<canvas>标签,绘制图像的步骤,以及着色器的概念。文章通过示例代码讲解了顶点着色器和片元着色器的工作原理,并探讨了WebGL坐标系统和绘制操作。

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

WebGL入门

webGL,是一项用来在网页上绘制和渲染复杂三维图形(3D图形),并允许用户与之进行交互的技术。webGL接合了HTML5和JavaScript,允许开发者在网页上创建和渲染3D图形。

下面是一些精彩的webGL示例

Aquarium
在这里插入图片描述
Cube
在这里插入图片描述
WebGL Bookcase
在这里插入图片描述
WebGL Earth
在这里插入图片描述
接下来先简单介绍一下使用到的知识要点

一、使用 < canvas > 标签

canvas即是画布,< canvas >标签定义了网页上的绘图区域

示例代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Draw a blue rectangle</title>
	</head>
	
	//<body>元素加载完成后执行main()函数作为JavaScript程序的入口
	<body onload="main()">
		<canvas id="example" width="400" height="400">
			//错误信息,提醒那些用着老式浏览器的用户
			please use a browser tht supports "canvas"	
		</canvas>
		<script src="DrawRectangle.js"></script>
	</body>
	
</html>

二、绘制图像步骤

1.获取 < canvas >元素

var canvas = docuement.getElementById(“id”)

2.向该元素请求图像的“绘图上下文”

//获取绘制二维图形的绘图上下文
var ctx = canvas.getContext(‘2d’);
//获取绘制三维图形的绘图上下文
var ctx = canvas.getContext(“webgl”) || canvas.getContext(“experimental-webgl”)

3.在绘图上下文上调用相应的绘图函数,以绘制二维图形

示例代码

//DrawRectangle.js

fucntion main(){

	//获取<canvas>元素
	var canvas=document.getElementById('example');
	if(!canvas){
		console.log('Failed to retrieve the <canvas> element');
		return;
	}

	//获取绘图上下文
	var ctx=canvas.getContext('2d');

	//绘制蓝色矩形
	ctx.filStyle="rgba(0,0,255,1.0)"//设置填充颜色为蓝色
	ctx.fillRect(120,10,150,150);//使用填充颜色填充矩形
}

三、着色器

上面的二维图形绘制,是先指定一个绘图颜色,然后绘制一个矩形

ctx.filStyle=“rgba(0,0,255,1.0)”//设置填充颜色为蓝色
ctx.fillRect(120,10,150,150);//使用填充颜色填充矩形

三维图形的颜色绘制就比二维图形的复杂多了,WebGL依赖于一种新的称为着色器的绘图机制。在三维场景中,仅仅用线条和颜色把图形画出来是远远不够的。你必须考虑,比如,光线照上去之后,或者观察者的视角发生变化吗,对场景会有什么影响。着色器可以高度灵活地完成这些工作,提供各种渲染。

以下先看一段完整代码对着色器有一个大致的认识,我们再慢慢解释

//HelloPoint1.js

//顶点着色器程序
var VSHADER_SOURCE=
	'void main(){\n'+
	'gl_Position=vec4(0.5,0.0,0.0,1.0);\n'+
	'gl_PointSize=10.0;\n'+
	'}\n';
	
//片元着色器程序
var FSHADER_SOURCE=
	'void main(){\n'+
	'gl_FragColor=vec4(1.0,1.0,0.0,1.0);\n'+
	'}\n';

function main(){
	//获取<canvas>元素
	var canvas=document.getElementById('webgl');
	
	//获取绘制三维图形的绘图上下文
	var gl=canvas. canvas.getContext("webgl");
	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;
	}
	
	//设置<canvas>的背景色
	gl.clearColor(0.0,0.0,0.0,1.0);
	//用背景色填充<canvas>
	gl.clear(gl.COLOR_BUFFER_BIT);
	//绘制一个点
	gl.drawArrays(gl.POINTS,0,1);
}

initShaders()是开源代码库中的一个函数,作用是对字符串形式的着色器进行了初始化,具体函数如下:

function initShaders(gl, vshader, fshader) {
  var program = createProgram(gl, vshader, fshader);
  if (!program) {
    console.log('Failed to create program');
    return false;
  }

  gl.useProgram(program);
  gl.program = program;

  return true;
}

顶点着色器(Vertex shader)

顶点着色器是用来描述顶点特性(如位置、颜色等)的程序。顶点是指二维或三维空间中的一个点,比如二维或三维图形的端点或交点。顶点着色器置顶了点的位置和尺寸

var VSHADER_SOURCE=
	'void main(){\n'+
	'gl_Position=vec4(0.5,0.0,0.0,1.0);\n'+
	'gl_PointSize=10.0;\n'+
	'}\n';

上面这段程序表示绘制一个点,这个点的位置是(0.5,0.0,0.0),点的尺寸是10.0

gl_Position:表示顶点位置

vec4:表示由四个浮点数组成的数据类型

floatfloatfloatfloat

三维坐标不是只有x,y,z吗,为什么需要四个浮点数来表示顶点位置呢?

这是因为这里运用了齐次坐标

齐次坐标就是用N+1维来代表N维坐标,使用如下符号描述:(x,y,z,w)

齐次坐标(x,y,z,w)等价于三维坐标(x/w,y/w,z/w)

将最后一个分量赋值为1.0就可以表示三维坐标了

为什么要用齐次坐标呢?

这是因为齐次坐标的存在使得用矩阵来描述顶点变换成为可能,后面再深入探讨。

gl_Position:表示点的尺寸(像素数)

顺便说说WebGL的坐标系统叭
在这里插入图片描述

WebGL的坐标系和< canvas >坐标的对应关系如下

  • < canvas>的中心点:(0.0,0.0,0.0)
  • < canvas>的上边缘和下边缘:(-1.0,0.0,0.0)和(1.0,0.0,0.0)
  • < canvas>的左边缘和右边缘:(0.0,-1.0,0.0)和(0.0,1.0,0.0)

片元着色器(Fragment shader)

进行逐片元处理过程如光照的程序。片元是WebGL术语,你可以将其理解为像素。片元着色器指定了点的颜色

var FSHADER_SOURCE=
	'void main(){\n'+
	'gl_FragColor=vec4(1.0,1.0,0.0,1.0);\n'+
	'}\n';

上面这段程序表示绘制一个点,点的颜色是(1.0,1.0,0.0,1.0)->rgba、

四、绘制操作

建立了着色器之后,我们就需要进行绘制操作,使用到的是gl.drawArrays()函数,这是一个强大的函数,可以用来绘制各种图形,该函数的规范如下

gl.drawArrays(mode,first,count)

mode:指定绘制的方式,可以接受以下常量符号

形状mode方式
gl.POINTS绘制v0,v1……
线段gl.LINE_STRIP一系列单独的线段,绘制(v0,v1),(v2,v3)……如果是奇数,最后一个省略
线条gl.LINE_STRIP一系列连接的线段,绘制(v0,v1),(v1,v2),(v2,v3)……除了第一个和最后一个,其他的点点即是起点又是终点
回路gl.LINE_LOOP一系列连接的线段,绘制(v0,v1),(v1,v2),(v2,v3)……(vn,v0),最后一个点会连接起点
三角形gl.TRIANGLES一系列单独的三角形,绘制(v0,v1,v2),(v3,v4,v5)……如果不是3的倍数,剩下的将会被忽略
三角带gl.TRIANGLES_STRIP一系列连接的三角形,绘制(v0,v1,v2),(v2,v1,v3),(v2,v3,v4)……以此类推,第二个是(v2,v1,v3)而不是(v1,v2,v3)是为了保持绘制按照逆时针绘制
扇形TRIANGLE_FAN与GL_TRIANGLE_STRIP类似,不过它的三角形的顶点排列顺序是T = [n-1 n-2 n].各三角形形成一个扇形序列

在这里插入图片描述
first:指定从哪个顶点开始绘制
count:指定绘制需要用到多少个顶点

在上一段代码中

//设置的背景色
gl.clearColor(0.0,0.0,0.0,1.0);
//用背景色填充
gl.clear(gl.COLOR_BUFFER_BIT);
//绘制一个点
gl.drawArrays(gl.POINTS,0,1);

gl.drawArrays(gl.POINTS,0,1);表示从v0开始画一个点

当程序调用gl.drawArrays()时,顶点着色器将被执行count次,每次处理一个顶点。一旦顶点着色器执行完后,片元着色器就会开始执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值