《WebGL入门指南》——第1章,第1.2节3D图形学——入门

1.2 3D图形学——入门
WebGL入门指南
“数学太难了啦!”

——芭比娃娃

也许有点不太好听,但是我必须得说,当我写3D图形的代码的时候,我会和芭比一样,有强烈的欲望想要用疯狂购物来放纵一下自己。因为3D图形编程通常很难,而且需要大量的数学知识。幸运的是,你不需要先成为数学大师再来写WebGL应用;我们会使用各种框架来代替我们去做其中大部分的复杂工作。尽管如此,理解底层的工作原理依然是非常重要的,因此下面我尝试在几页的篇幅内总结出整个3D图形学的基础知识。

1.2.1 3D坐标系
毫无疑问,3D绘制是建立在3D坐标系中的。任何一个熟悉2D笛卡儿坐标系(即绘图纸上的和HTML页面中的窗口坐标)的人,都会知道x坐标和y坐标。这种2D坐标可以用于定义页面中

标签的位置,或者指定在Canvas元素上进行2D绘制的位置。类似地,3D绘制是建立在3D坐标系统中的,除了x轴和y轴,新增加了一个坐标轴z,用于表示深度(即在离屏幕多深多远的地方绘制一个3D物体)。WebGL使用的坐标系可以查看图1-2,x轴方向是水平的从左到右,y轴的方向是垂直的从下到上,z轴的方向是从屏幕里面指向屏幕外面。

图1-2 一个3D坐标系统(https://commons.wikimedia.org/wiki/File: 3D_coordinate_system.svg; 根据Creative Commons Attribution–Shar eAlike 3.0 Unported协议授权使用)

如果你已经非常熟悉2D坐标系,那么我想3D坐标系应该也不是很难理解。不过,从现在开始,事情要变得复杂一些了。

1.2.2 网格、多边形和顶点
有很多种方法来绘制3D图形,最常用的一种方法就是使用网格(Mesh)。网格是由一个或多个多边形组成的物体,各个顶点的坐标(x, y, z)定义了多边形在3D空间中的位置。网格中的多边形通常都是三角形(包含三个顶点)和四边形(包含四个顶点)。3D网格通常也被叫做模型(model)。

图1-3举例说明了一个3D网格。由黑线描边的四边形组成了这个网格,形成了一个脸部的形状(当然在最终的渲染图片中你不会看到这些黑线,这里只是为了解释网格的概念)。网格中的各个顶点的x, y, z的坐标分量只是用于定义形状;而网格表面的其他特性,如颜色和着色,都是由其余的属性来定义的,我们稍后会介绍。

图1-3 一个3D网格 (http://upload.wikimedia.org/wikipedia/commons/8/88/Blender3D_UVTexTut1.png; 根据Creative Commons Attribution-Share Alike 3.0 Unported 协议授权使用)

1.2.3 材质、纹理和光源
网格表面的其他特性是由除了顶点位置(x, y, z)坐标之外的属性来定义的。网格表面可以简单到只有一种颜色,也可以复杂到是由多个不同的数据来共同决定的,比如说物体如何反射照射到表面上的光,物体的光泽度如何。网格表面同样也可以由一个或多个位图来决定,这就是我们通常所说的纹理映射(texture map),或者简称为纹理。纹理可以定义一个线性表面的外观(就好比把一张图片印在T恤衫上),另外,通过组合多张不同的纹理可以实现更加复杂的效果,例如凹凸效果和辉光效果。在大多数的图形系统中,网格表面的特性被统称为材质(material)。材质通常依赖于一个或多个光源(light)来呈现出外观效果,你也许已经猜到了,这就是我们如何让场景被照亮的。

图1-3中人的头部模型拥有一层紫色的材质,光源则是从模型的左侧照入(注意观察模型右侧脸颊的阴影)。

1.2.4 变换与矩阵
3D网格的形状是由顶点位置决定的。如果每次你想要移动模型都必须重新设定顶点位置,那将会是一件非常可怕和沉闷的事情,特别是当模型会持续穿过整个场景或做其他的动作的时候。因此,大部分的3D系统都支持变换(transform),这是一种不需要遍历每个顶点就可以移动模型的操作,不需要明确的逐个改变每个顶点的位置。变换包括对渲染模型的缩放、旋转、位移操作,而不必手动设定任何顶点的值。

变换通常是由矩阵来操作的,这是一个包含一组数值的数学模型,用于计算顶点的变换位置。如果你和我一样也是一个线性代数迷,那你应该很适应这个方法。如果不是,也别灰心。本书中使用的Three.js工具集可以让我们以黑箱模式操作矩阵:我们只需要告诉程序位移、旋转或者缩放,那么Three.js就会完成相应的操作。

1.2.5 相机、透视、视口和投影
每一个场景在渲染时都需要有一个视点,用户正是从视点的位置去观察场景。3D图形系统通常使用相机(camera)来定义用户与场景的相对位置和朝向,和我们真实世界中的相机一样,3D世界中的相机也具有类似于视野尺寸等属性。视野尺寸决定了透视关系(例如,远处的物体会看起来小一些)。相机的各个属性组合在一起将最终的3D场景渲染图像传送给2D视口(viewport),视口是由浏览器窗口或Canvas元素决定的。

相机永远是由两个矩阵来控制的。第一个矩阵定义了相机的位置和朝向,类似于用于进行变换操作的矩阵(见前文)。第二个矩阵比较特殊,它用于将相机空间的3D坐标转换为视口中的2D绘制空间中的坐标,这就是所谓的投影矩阵(projection matrix)。唉,我就知道讨厌的数学又来了!但大部分的WebGL框架都可以掩盖相机矩阵的底层细节,所以你要做的只是放置相机然后渲染即可。

图1-4很好地解释了相机、视口和投影的核心概念。在图的左下方,会看到一个眼睛的图标,代表相机的位置。红色的向量指向右侧(在图中被标记为x轴),代表相机的指向。蓝色的方块是3D场景中的物体。绿色和红色的矩形分别代表近裁剪面和远裁剪面。这两个平面决定了3D空间的子集的边界,也就是所谓的视锥体(view volume)或视平截头体(view frustum)。只有处于视平截头体内部的物体才可以被渲染到屏幕上。近裁剪面即视口,此平面就是我们最终在屏幕上看到的渲染的2D图像。

图1-4 相机、视口和投影(http://obviam.net/index.php/3d-programming-with-android-projections- perspective/),经授权使用

相机是一个非常强大的工具,它决定了观察者和3D场景之间的关系,造成一种仿真感。在动画兵工厂中相机还是一件威力无比的武器,通过移动相机,你可以创造出神奇的荧幕效果,掌控用户的视觉体验。

1.2.6 着色器
这是在总结我们的3D图形学探索旅程之前的最后一个话题:着色器(shader)。为了在最终的图像中渲染模型,开发者必须精确地定义顶点、变换、材质、光源和相机之间的关系和交互。这就是由着色器来完成的。着色器(或称为“可编程着色器”)是一小段程序代码,其中包含了将模型投射到屏幕上的像素算法。着色器通常是由高等级的类C语言编写的,编译并运行在图形处理单元(GPU)中。大部分的现代电脑都配备了GPU,它是一种独立于CPU而专门用于渲染3D图形的处理器。

如果你仔细阅读了我之前提到的WebGL的定义,你也许会注意到我忽略了一部分内容。在科纳斯组织的官方网站上有这么一段话:

它使用OpenGL渲染语言GLSL ES……

在其他许多图形系统中,着色器是一个可选的或比较高级的特性;但与之不同的是,WebGL必须配备着色器。当你编写WebGL程序的时候,必须定义着色器,否则图形是不会显示在屏幕上的。WebGL的实现假定客户端电脑上配备有GPU。GPU可以处理顶点、纹理和其他一点东西;但它对材质、光源和变换却一无所知。把后者这些较高级的信息传递给GPU并最终把它们绘制到屏幕上的转换过程是由着色器来完成的,着色器是由开发者创建的。

所以你现在应该可以理解为什么我不一开始就讨论这个话题:我不想吓到你!着色器编程看起来很吓人,要用类C的语言来写,短时间内看是这样的,而且似乎花这么大的代价来将3D场景转换成最终的2D图像有点得不偿失。但是,请别害怕:许多流行的WebGL框架都内置了着色器,你只需要在代码中嵌入它们即可,这些内置的着色器可以满足你大部分的需求。

我想我有必要声明一下,着色器带来的并不只是痛苦和煎熬。它的存在是很有必要的。着色器给予图形开发者完全的能力去操控每一个顶点和像素。这种能力可以创作出许多惊艳的视觉效果,从栩栩如生的CG效果(如图1-1所示的水母)到奇幻的卡通风格。但是强大的能力总是需要更强大的控制者。着色器是一个非常高端的话题,我不想让你在一开始就去攀登这座大山,直到我们已经充分理解了各种知识。这也正是为什么本书中所有的示例都使用了相当简单的着色器。

时间: 2024-08-30 08:34:11

《WebGL入门指南》——第1章,第1.2节3D图形学——入门的相关文章

《WebGL入门指南》——导读

目 录第1章 WebGL简介 1.1 WebGL--一个技术定义 1.2 3D图形学--入门 1.3 WebGL原生API 1.4 本章小结 第2章 你的第一个WebGL程序 2.1 Three.js--一个JavaScript 3D引擎 2.2 建立Three.js运行环境 2.3 一个简单的Three.js网页2.4 一个真实的3D示例 2.5 本章小结 第3章 图形 第4章 动画 第5章 交互 第6章 2D与3D的整合 第7章 实战WebGL 第8章 你的第一个WebGL游戏 后记 附录A

《WebGL入门指南》——第2章,第2.4节一个真实的3D示例

2.4 一个真实的3D示例 WebGL入门指南 到目前为止,你也许在想"真是个还不错的正方形",然后开始怀疑我们什么时候开始画一些真正的3D图形.好吧,那就现在吧!在示例2-2中我们将会用更有趣的物体来代替正方形,我们将会完成一个看起来还不错.并且展示了大部分WebGL主要特性.同时还保持代码简洁的页面. 图2-2就是页面的最终效果.其中我们设置了标题文字,添加了一个表面贴有图片的立方体,然后在页面底部也添加了文字.另外值得一提的是,这个页面是可以交互的:点击画布元素,立方体就会开始或

《WebGL入门指南》——第1章,第1.4节本章小结

1.4 本章小结 WebGL入门指南 这样我们就结束了WebGL基础知识之旅.噢!东西可真多啊!现在你也许在想,仅仅在屏幕上画一个正方形就如此兴师动众.而且,这还不是一个真正的3D物体!好吧,我部分同意你的意见.WebGL编程,在这个等级上的编程,是相当困难的.标准的设计者做出这样一个决定还是相当清醒的,他们用这样一个既小巧又简单的标准,换取了WebGL强大的能力,而付出的代价是开发者必须要在应用程序端编写大量的代码. 显然,在大部分情况下,我们不会使用WebGL来绘制2D物体.HTML5的2D

《WebGL入门指南》——第2章,第2.3节一个简单的Three.js网页

2.3 一个简单的Three.js网页 WebGL入门指南 好了,我想现在是时候来编写你的第一个 WebGL 程序了.在这一节中,你会看到上手Three.js是一件相当简单的事情.示例2-1实际上是第1章中的那个绘制正方形示例的翻版,但是将代码从150行精简到30行.由此可见,在使用Three.js之后对代码的压缩量之大. 示例2-1 一个简单的Three.js网页 <!DOCTYPE html> <html> <head> <title>A Simple

《WebGL入门指南》——第2章,第2.5节本章小结

2.5 本章小结 WebGL入门指南 本章介绍了第一个真实示例.我必须要说,这其实还是很轻松的.仅仅使用了很少的代码,我们就可以创建一个包含3D内容的HTML网页,装扮它,用动画赋予它生命,然后让它可以交互.你要意识到在过去这是根本不可能的.感谢WebGL,让这一切都变成了现实.而又有了Three.js,可以让你在开发前不必先去考取一个计算机图形学的学位. 我们已经构建和运行起来了WebGL,剩下的就都是细节了.

《WebGL入门指南》——第2章,第2.1节Three.js——一个JavaScript 3D引擎

2.1 Three.js--一个JavaScript 3D引擎 WebGL入门指南 需求是创新之母.每个开发者在项目之初都必须不厌其烦的使用WebGL原生API来编写代码,直到可以建立一个自己的代码库,以用于随后的通用3D编程.事实上,已经有很多人完成了这项工作.现在有很多不错的WebGL开源框架,例如GLGE(http://www.glge.org/).SceneJS(http://www.scenejs.org/).CubicVR(http://www.cubicvr.org/)等.每个框架

《WebGL入门指南》——第1章,第1.3节WebGL原生API

1.3 WebGL原生API WebGL入门指南 计算机图形学中的基本概念在过去的数年中从未发生过变化.但图形技术却不断进化,特别是最近几年,伴随着设备和操作系统的多样化.这些百花齐放的图形技术的根基则是诞生于20世纪80年代末期的OpenGL.OpenGL作为行业规范已经存在了非常长的时间,并且成功经受住了来自微软的DirectX的竞争考验,无可争辩的成为了3D图形编程的领衔者. 但是并非所有的OpenGL都是一样的.根据不同平台的不同特征,包括台式电脑.智能电视.手机和平板电脑等,人们开发了

《WebGL入门指南》——第1章,第1.1节WebGL——一个技术定义

1.1 WebGL--一个技术定义 WebGL入门指南 WebGL 标准是由科纳斯组织(Khronos Group)开发和维护的,该组织还是管理着 OpenGL.COLLADA等其他你也许早有耳闻的规范的标准组织.以下是科纳斯组织的网站上对WebGL的官方描述: WebGL是免授权费的,跨平台的应用程序接口API,它将OpenGL ES 2.0作为在HTML网页内的3D绘图环境,作为低级别文档对象模型接口开放.它使用OpenGL渲染语言GLSL ES,并可被整洁地与其他3D内容上层或下层的网页内

《WebGL入门指南》——第2章,第2.2节建立Three.js运行环境

2.2 建立Three.js运行环境 WebGL入门指南 你要做的第一件事情就是从GitHub上获取到最新版的Three.js包.Three.js在GitHub上的地址是https://github.com/mrdoob/three.js/.复制到本地之后,你可以在build/Three.js目录找到打包好的库文件.另外,Three.js的全部源代码都在src文件夹中.而API文档则是直接连接到GitHub网站,但这份文档相当简陋,你最好还是对照源代码来上手. Three.js使用了Google