WebGL编程指南(1)简介

   书本源代码 https://download.csdn.net/download/qfire/10371055

   2009年,Khronos建立了WebGL工作小组,开始基于OpenGL ES着手建立WebGL规范,并于2011年发布了WebGL规范的第1个版本。本书主要基于第1版的WebGL规范编写,后续更新目前都是以草案的形式发布,如有需要,也可参考。www.khronos.org/registry/webgl/specs/1.0/

1.1 WebGL程序的结构

   

1.2 Canvas是什么?

   在HTML5出现之前,如果你想在网页上显示图像,只能使用HTML提供的原生方案<img>标签。用这个标签显示图像虽然简单,但只能显示静态的图片,不能进行实时绘制和渲染。因此,后来出现了一些第三方解决方案,如Flash Player等。HTML5的出现改变了一切,它引入了<canvas>标签,允许JavaScript动态绘制图形。

实例

       清空

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8"/>
	<title>Clear canvas</title>
</head>
<body οnlοad="main()">
	<canvas id="webgl" width="400" height="400">
		Please use the browser supporting "canvas"
	</canvas>

	<script src="../lib/webgl-utils.js"></script>
	<script src="../lib/webgl-debug.js"></script>
	<script src="../lib/cuon-utils.js"></script>
	<script src="HelloCanvas.js"></script>
</body>
</html>
function main() {
	var canvas = document.getElementById('webgl');
	var gl = getWebGLContext(canvas);
	if (!gl) {
		console.log("Failed to get the rendering context for WebGL");
		return;
	}
	//RGBA
	gl.clearColor(0.0, 0.0, 0.0, 1.0);
	//清空
	gl.clear(gl.COLOR_BUFFER_BIT);
	//绘制点
	//gl.drawColor(1.0, 0.0, 0.0, 1.0);
	gl.drawPoint(0, 0, 0, 10);  //点的位置和大小
}

       绘制一个10个像素大的红色的点,WebGL处理的是三维图形,所以我们有必要为这个点指定三维坐标。

       WebGL依赖于一种新的称为着色器的绘图机制。着色器提供了灵魂且强大的绘制二维或三维图形的方法,所有WebGL程序必须使用它。着色器不仅强大,而且更复杂,仅仅通过一条简单的绘图命令是不能操作它的。

//顶点着色器程序
var VSHADER_SOURCE = 
   'void main() {\n' + 
   '  gl_Position = vec4(0.0, 0.0, 0.0, 1.0); \n' + //设置坐标
   '  gl_PointSize = 10.0; \n' + //设置尺寸
   '}\n';
//片元着色器程序
var FSHADER_SOURCE = 
   'void main() {\n' +
   '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + //设置颜色
   '}\n';
function main() {
	var canvas = document.getElementById('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 ;
	}
	//RGBA
	gl.clearColor(0.0, 0.0, 0.0, 1.0);
	//清空
	gl.clear(gl.COLOR_BUFFER_BIT);
	//绘制点
	gl.drawArrays(gl.POINTS, 0, 1);  //点的位置和大小
}

WebGL需要两种着色器。

  • 顶点着色器(Vertex shader):顶点着色器是用来描述顶点特性(如位置、颜色等)的程序。
  • 片元着色器(Fragment shader):进行逐片元处理过程如光照的程序。片元是一个WebGL术语,你可以将其理解为像素。




vec4(x, y, z, w);齐次坐标(x, y, z, w)等价于三维坐标(x/w, y/w, z/w),齐次坐标的存在,使得用矩阵乘法来描述顶点变换成为可能,三维图形系统在计算过程中,通常使用齐次坐标来表示顶点的三维坐标。

gl.drawArrays()可以用来绘制各种图形


1.3 WebGL坐标系统

    


   '  gl_Position = vec4(0.5, 0.5, 0.0, 1.0); \n' + //设置坐标

   '  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n' + //设置颜色

注:WebGL不需要交换颜色缓冲区

1.4 绘制一点实例

   将位置信息从JavaScript程序中传给顶点着色器。有两种方式可以做到:attribute变量和uniform变量。attribute变量传输的是那些与顶点相关的数据,而uniform变量传输的是那些对于所有顶点都相同(或与顶点无关)的数据。


//顶点着色器程序
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 = 
   'void main() {\n' +
   '  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n' + //设置颜色
   '}\n';
   

function main() {
	var canvas = document.getElementById('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 ;
	}
	//获取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;
	}
	gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
	//RGBA
	gl.clearColor(0.0, 0.0, 0.0, 1.0);
	//清空
	gl.clear(gl.COLOR_BUFFER_BIT);
	//绘制点
	gl.drawArrays(gl.POINTS, 0, 1);  //点的位置和大小
}



//顶点着色器程序
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' + //uniform变量
   'void main() {\n' +
   '  gl_FragColor = u_FragColor;\n' + //设置颜色
   '}\n';
  
function main() {
	var canvas = document.getElementById('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 ;
	}
	//获取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;
	}
	var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
	if (u_FragColor < 0) {
		console.log("failed to get the storage location of u_FragColor");
		return;
	}
	//注册鼠标
	canvas.onmousedown = function(ev) { click(ev, gl, canvas, a_Position, u_FragColor)};
	gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
	//RGBA
	gl.clearColor(0.0, 0.0, 0.0, 1.0);
	//清空
	gl.clear(gl.COLOR_BUFFER_BIT);
	//绘制点
	//gl.drawArrays(gl.POINTS, 0, 1);  //点的位置和大小
}

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]);
	//将点的颜色存储到g_colors数组中
	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++) {
		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);
	}
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值