欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WebGL编程指南(1)简介

程序员文章站 2022-05-23 14:18:42
...

   书本源代码 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程序的结构

   WebGL编程指南(1)简介

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 onload="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术语,你可以将其理解为像素。

WebGL编程指南(1)简介

WebGL编程指南(1)简介

WebGL编程指南(1)简介

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

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

WebGL编程指南(1)简介

1.3 WebGL坐标系统

WebGL编程指南(1)简介    

WebGL编程指南(1)简介

   '  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变量传输的是那些对于所有顶点都相同(或与顶点无关)的数据。

WebGL编程指南(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 = 
   '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);  //点的位置和大小
}
WebGL编程指南(1)简介

WebGL编程指南(1)简介

WebGL编程指南(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);
	}
}
WebGL编程指南(1)简介