您的位置:首页 > 编程语言

【笔记】《WebGL编程指南》学习-第2章WebGL入门(3-画一个点-版本1))

2017-09-19 23:10 501 查看
目标:绘制一个最简单的图形-点(位于原点(0.0,0.0,0.0)处,大小10像素)!

成果展示:其实这个这点是用矩形画的,而不是圆。



开始学习!

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

HelloPoint1.html

HelloPoint1.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Draw a point 1</title>
</head>

<body onload="main()">
<canvas id="webgl" width="400" height="400">
Please use a browser that supports "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="HelloPoint1.js"></script>
</body>
</html>


html文件与之前的 HelloCanvas 基本一致,就不多说了。

HelloPoint1.js

先看代码(有个印象)

HelloPoint1.js

//顶点着色器程序
var VSHADER_SOURCE =
'void main(){' +
'gl_Position = vec4(0.0, 0.0, 0.0, 1.0);'+
' gl_PointSize = 10.0;'+
'}';

//片元着色器程序
var FSHADER_SOURCE=
'void main(){'+
'gl_FragColor = vect4(1.0, 0.0, 0.0, 1.0);'+
'}';

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

//获取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;
}

//指定清空<canvas>颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);

//清空<canvas>
gl.clear(gl.COLOR_BUFFER_BIT);

//绘制一个点
gl.drawArrays(gl.POINTS, 0, 1);
}


其实和上一篇文章的HelloCanvas.js相比,有很多都是一样的,但多了一个着色器的概念和画点的函数。

着色器是什么?

要使用 WebGL进行绘图就必须使用着色器。在代码中,着色器程序是以字符串的形式“嵌入”在JS文件中,在程序真正开始运行前它就已经设置好了。

WebGL需要两种着色器:

顶点着色器(Vertec shader):定点着色器是用来描述顶点特性(如位置、颜色等)的程序。顶点(Vertex)是指二维或三维空间中的一个点,比如二维或三维图形的端点或焦点。

片元着色器(Fragment shader):进行逐元处理过程如光照(以后的篇章会讲)的程序。片元(fragment)是一个WebGL术语,你可以将其理解为像素(图像的单元)。

着色器后面会详细去学,这里就不多说了。简单来说,在三维场景中,仅仅靠线条和颜色把图形画出来是不够的,比如光线照上去,观察者的视觉发生变化,对场景的影响等等。着色器可以高度灵活地完成这些工作,提供各种渲染效果。

JS读取了着色器的相关信息,然后存在WebGL系统中使用着色器在浏览器上绘制图形,下图是从执行JS程序到在浏览器中显示结果的过程:



图的左侧是两个浏览器窗口。它们是同一个窗口,上面一个是执行JS程序之前的窗口,下面一个执行之后的。

程序执行的流程大概是:

运行JS程序,调用了WebGL的相关方法。

顶点着色器和片元着色器会执行,在颜色缓冲区内进行绘制,这时就清空了绘图区。

颜色缓冲区中的内容会自动在浏览器的 <canvas>上显示出来。

在以后的学习中,上面这个图会经常用到,所以我们会有一个简化版本,注意程序流程是从左到右的,最右边是颜色缓冲区而不是浏览器,因为颜色缓冲区的内容会自动显示在浏览器上。



本节示例程序的任务是,在屏幕上绘制一个10像素大小的点,它用到两个着色器:

顶点着色器指定了点的位置和尺寸。本例中,点的位置是(0.0, 0.0, 0.0),尺寸是10像素。

片元着色器指定了点的颜色。本例中,点的颜色是红色(1.0, 0.0, 0.0, 1.0);

使用着色器的WebGL程序的结构

//顶点着色器程序
var VSHADER_SOURCE =
'void main(){' +
'gl_Position = vec4(0.0, 0.0, 0.0, 1.0);'+
' gl_PointSize = 10.0;'+
'}';

//片元着色器程序
var FSHADER_SOURCE=
'void main(){'+
'gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);'+
'}';


这一段代码分别是顶点着色器程序和片元着色器程序,着色器程序代码作为字符串存储在变量 VSHADER_SOURCEFSHADER_SOURCE 中。就像前面提到的它们是以JS字符串形式编写的着色器语言程序,这样主程序可以将他们传给W
bcf9
ebGL系统。

因为着色器程序代码必须预先处理成单个字符串的形式,所以我们用 + 号将多行字符串连成一个长字符串,可以在+号后面加上换行符 “\n” 。这样当着色器内部出错时,可以获得出错的行号,当然也可以不写。

初始化着色器

在研究着色器的内部细节之前,先看一下 main()函数的执行流程,大部分 WebGL 程序都会遵循这样的流程。



与上一篇的流程相比,新增“初始化着色器”和 “绘制”。

初始化着色器,我们调用辅助函数 initShaders()(被定义在要下载的文件里)对字符串形式的着色器进行了初始化,这个函数的内部细节,在后面的篇章会讲。

initShaders()点的行为



如图所示, WebGL系统由两部分在组成,即顶点着色器和片元着色器。在初始化着色器之前,顶点着色器和片元着色器都是空白的,我们需要将字符串形式的着色器代码从JS传给WebGL系统,并建立着色器,这就是 initShaders() 所做的事情。注意,着色器运行在WebGL系统中,而不是JS程序中。

WebGL程序包括运行在浏览器中的JS和运行在WebGL系统的着色器程序这两个部分。

顶点着色器

//顶点着色器程序
var VSHADER_SOURCE =
'void main(){' +
'gl_Position = vec4(0.0, 0.0, 0.0, 1.0);'+
' gl_PointSize = 10.0;'+
'}';


就像JS一样,着色器程序使用 = 操作符为变量赋值。首先将点的位置赋值给 gl_Position 变量,然后将点的尺寸赋值给 gl_PointSize 变量,这两个变量是内置在顶点着色器中,而且有特殊含义;gl_Position 表示顶点的位置,gl_PointSize 表示点的尺寸。

在看代码的时候你可能会有疑问,好像在定义顶点着色器时的类型和JS不一样。那是因为GLSL ES是一种强类型的编程语言,也就是说,开发者必须明确指出某个变量是某种“类型”的。

下面是这一节出现在GLSL ES代码中的几种类型:



注意:如果向某类型的变量赋一个不同类型的值。就会出错,例如,gl_PointSize 是浮点型的变量,你就必须向其赋浮点型的值。

在赋值给 gl_Position 时,我们添加了1.0作为第4个分量。由4个分量组成的矢量被称为齐次坐标。因为它能够提高处理三维数据的效率,所以在三维图形中被大量使用。虽然齐次坐标是四维的,但如果其最后一个分量是 1.0,那么这个齐次坐标就可以表示“前三个分量为坐标值”的那各个点。所以,当你需要用齐次坐标表示顶点坐标的时候,只要将最后一个分量赋为 1.0 就可以了。

齐次坐标

齐次坐标使用如下的符号描述:(x, y, z, w),齐次坐标(x, y, z, w)等价于三维坐标(x/w, y/w, z/w)。所以如果齐次坐标的第4个分量是1,你就可以将它当成三维坐标来使用。w 的值必须是大于等于0的。如果w 趋近于0,那么它所表示的点是趋近无穷远,所以齐次坐标系中可以有无穷的概念。齐次坐标的存在,使得用矩阵乘法来描述顶点变换成可能,三维图形系统在计算过程中,通常使用齐次坐标来表示顶点的三维坐标。

片元着色器

//片元着色器程序
var FSHADER_SOURCE=
'void main(){'+
'gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);'+
'}';


顶点着色器控制点的位置、大小,片元着色器控制点的颜色。如前所述,偏远就是显示在屏幕上的一个像素。

片元着色器的作用是处理片元,使其显示在屏幕上。

片元着色器将点的颜色赋给 gl_FragColor 变量,该变量是片元着色器唯一的内置变量,它控制着像素在屏幕上的最终颜色,对这个内置变量赋值后,相应的像素就会以这个颜色值显示,颜色值也是 vec4 类型。

绘制操作

首先我们清空绘制区域,然后我们使用 gl.drawArrays()来进行绘制。

gl.drawArrays(gl.POINTS, 0, 1);


gl.drawArrays()是一个强大的函数,它可以用来绘制各种图形:



示例函数调用该函数时,因为我么绘制的是单独的点,所以设置第1个参数为 gl.POINTS, 设置第2个参数为0,表示从第1个顶点(虽然只有1个顶点)开始画,第3个参数 count 为1,表示在这个简单的程序中仅绘制了1个点。

WebGL的坐标系统



如图所示,WebGL 坐标系和 <canvas>绘图区的坐标系不同,需要将前者映射到后者。默认情况下,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)

好,运行成果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  webgl 图形
相关文章推荐