欢迎光临
免费的PDF电子书下载网站

TypeScript图形渲染实战:基于WebGL的3D架构与实现 PDF下载

编辑推荐

资深图形编程专家15年开发经验的深度分享

详解TypeScript编程及基于WebGL3D架构与实现

深入:凝聚作者15年图形编程经验,带领读者深入探索图形编程的知识

系统:用TypeScript语言实现WebGLApplication框架和WebGLUtilLib渲染库

广泛:涵盖常用的数据结构、3D图形数学基础、多视口渲染、文字绘制、Quake3 BSP场景渲染、Doom3 PROC场景渲染、骨骼蒙皮动画原理及渲染等内容

独特:精讲8个完整的有较高价值的绘图案例,帮助读者理解3D图形编程的基础核心要点

实用:不局限于TypeScript和WebGL范畴,可以使用其他各种编程语言应用到3D图形编程的各个领域

7位重量级大咖力荐:

中国工业设计研究院西南中心院长 ; 覃霁

上海灵禅网络科技股份有限公司CEO ; 兰海文

上海凯英网络科技有限公司副总裁 ; 何鑫

成都手领科技有限公司创始人兼CTO、迷雾侦探/AI-LIMIT游戏技术负责人 ; 张锐

《全局光照技术》作者 ; 秦春林

《Go语言从入门到进阶实战》作者、慕课网讲师、资深全栈游戏开发者 ; 徐波

 ;跨平台开源UI引擎FairyGUI作者 ; 萧应棠

TypeScript图形渲染实战:基于WebGL3D架构与实现》核心内容:

SystemJS与webpack

TypeScript封装和实现常用容器

WebGLApplication框架

WebGL基础

WebGLUtilLib渲染框架

3D图形中的数学基础

多视口渲染基本几何体、坐标系及文字

解析与渲染Quake3 BSP场景

解析与渲染Doom3 PROC场景

解析与渲染Doom3 MD5骨骼蒙皮动画

超值赠送:

本书源代码文件(需要下载)

本书Demo(需要下载)

 ;

内容简介

为了让广大3D图形爱好者能够快速地学习WebGL图形编程,《TypeScript图形渲染实战:基于WebGL的3D架构与实现》按照循序渐进的方式,由浅入深地讲解了WebGL图形编程的相关知识点。《TypeScript图形渲染实战:基于WebGL的3D架构与实现》理论结合实践,可以让3D图形爱好者少走弯路,直击3D图形开发中的核心要点。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》共10章,分为3篇。第1、2章为数据结构基础篇,主要介绍如何构建TypeScript开发调试环境,并以范型编程方式实现和封装了动态类型数组、关联数组、双向链表、队列、栈和树等数据结构。第3~7章为WebGL图形编程基础篇,围绕着如何建立一个WebGLApplication框架应用体系和WebGLUtilLib渲染体系而展开,并且详细介绍了3D图形编程中的一些常用数学基础知识。第8~10章为开发实战篇,在使用WebGLApplication框架和WebGLUtilLib框架的基础上实现了对Id Software公司开源的Quake3 BSP及Doom3 PROC场景的解析和渲染,并且介绍了Doom3 MD5骨骼蒙皮动画原理、解析与渲染的相关知识点。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》特别适合对3D图形开发、WebGL图形编程、游戏开发等感兴趣的技术人员阅读,还适合JavaScript程序员及想从C、C 、Java、C#等强类型语言转HTML 5开发的程序员阅读。另外,编程爱好者、高校学生及培训机构的学员也可以将《TypeScript图形渲染实战:基于WebGL的3D架构与实现》作为兴趣读物。

作者简介

步磊峰 ; 计算机图形编程资深爱好者。有超过15年的程序开发经验。擅长C/C 、C#、Java、Objective-C、JavaScript和TypeScript等编程语言。在作者的程序人生中,曾经编写过3D程序、跨平台UI引擎、Java页游服务器和微信服务器,并为国内的多个大型国营金融机构开发过多款移动端App。个人最大的成就是通过内部培训,为公司培养了20多个C语言、C 及移动端的开发人才。

TypeScript图形渲染实战:基于WebGL的3D架构与实现 PDF下载

目录


 
第1篇  ;数据结构基础
第1章  ;SystemJS与Webpack 2
1.1  ;准备工作 3
1.1.1  ;安装Node.js 3
1.1.2  ;安装Viusal Studio Code 4
1.2  ;安装和配置SystemJS 5
1.2.1  ;安装SystemJS 5
1.2.2  ;使用SystemJS 7
1.2.3  ;第一个TypeScript程序 8
1.3  ;安装和配置Webpack 9
1.3.1  ;安装Webpack 9
1.3.2  ;配置Webpack 11
1.3.3  ;调用build命令 12
1.3.4  ;配置tsconfig.json文件 12
1.3.5  ;调用build和dev命令 13
1.3.6  ;使用watch命令 14
1.3.7  ;联合使用watch和dev命令 15
1.3.8  ;使用Webpack压缩打包源码 16
1.4  ;SysemJS VS. Webpack 16
1.5  ;编译(Compile)VS.转义(Transpile) 18
1.6  ;断点调试 19
1.6.1  ;安装及配置Debugger for Chrome扩展 19
1.6.2  ;断点调试TypeScript程序 20
1.6.3  ;VS Code Debug快捷键 21
1.7  ;本章总结 21
第2章  ;TypeScript封装和实现常用容器 22
2.1  ;ArrayBuffer、DataView及类型数组实现原理 23
2.1.1  ;C/C 模拟JS/TS中的ArrayBuffer对象 23
2.1.2  ;C/C 模拟JS/TS中的DataView对象 24
2.1.3  ;C/C 版CDataView VS. JS/TS版DataView 25
2.1.4  ;C/C 模拟JS/TS中的Float32Array对象 26
2.1.5  ;C/C 版CFloat32Array VS. JS/TS版Float32Array 28
2.1.6  ;JS/TS中的类型数组对象 30
2.2  ;封装动态类型数组 31
2.2.1  ;TypedArrayList的成员变量及构造函数 31
2.2.2  ;TypedArrayList的push方法 32
2.2.3  ;TypedArrayList的slice方法和subarray方法 33
2.2.4  ;TypedArrayList的其他方法和属性 35
2.2.5  ;capacityChangedCallback回调函数 36
2.3  ;封装关联数组 36
2.3.1  ;JS/TS中的关联数组 37
2.3.2  ;TypeScript索引签名 37
2.3.3  ;ES 6 Map对象 38
2.3.4  ;封装成Dictionary字典对象 39
2.3.5  ;测试Dictionary对象 42
2.3.6  ;红黑树还是哈希表 42
2.4  ;实现SGI STL风格双向循环链表 44
2.4.1  ;泛型的ListNode结构 45
2.4.2  ;List中的头节点 45
2.4.3  ;双向循环概念 46
2.4.4  ;List的查询与遍历操作 46
2.4.5  ;List的插入操作 48
2.4.6  ;List的删除操作 50
2.4.7  ;List的push / pop / push_front / pop_front操作 51
2.5  ;封装队列与栈 51
2.5.1  ;声明IAdapter<; T >;泛型接口 52
2.5.2  ;实现AdapterBase<; T >;抽象基类 52
2.5.3  ;实现Queue子类和Stack子类 53
2.6  ;实现通用树结构 54
2.6.1  ;树结构的内存表示 54
2.6.2  ;树节点添加时的要点 55
2.6.3  ;树节点isDescendantOf和remove方法的实现 56
2.6.4  ;实现addChild等方法 58
2.6.5  ;查询树结构的层次关系 59
2.6.6  ;广度/深度优先遍历算法 60
2.6.7  ;队列及栈在广度/深度优先遍历中的应用 62
2.6.8  ;广度/深度线性遍历枚举器 63
2.6.9  ;树结构枚举器的实现 63
2.6.10  ;测试树结构迭代器 67
2.6.11  ;深度优先的递归遍历 71
2.7  ;本章总结 73
第2篇  ;WebGL图形编程基础
第3章  ;WebGLApplication框架 76
3.1  ;Application体系结构概述 77
3.2  ;第一个WebGL Demo 78
3.2.1  ;技术要点描述 78
3.2.2  ;Demo的成员变量与构造函数 80
3.2.3  ;资源同步加载 82
3.2.4  ;立方体、坐标系、三角形及文字渲染 83
3.2.5  ;更新操作 85
3.2.6  ;键盘输入事件处理 86
3.2.7  ;总结Application框架的使用流程 87
3.3  ;Application框架实现 87
3.3.1  ;成员变量与构造函数 88
3.3.2  ;启动/查询/停止Application 89
3.3.3  ;不间断地更新操作 90
3.3.4  CanvasInputEvent及其子类 92
3.3.5  DOM中的getBoundingRect方法 93
3.3.6  实现viewportToCanvasCoordinate方法 94
3.3.7  将DOM Event事件转换为CanvasInputEvent事件 95
3.3.8  实现EventListenerObject接口进行事件分发 96
3.3.9  让事件起作用 97
3.3.10  定时器Timer系统 97
3.3.11  增删定时器对象 98
3.3.12  触发多个定时任务的操作 100
3.3.13  WebGLApplication子类 101
3.3.14  CameraApplication子类 102
3.4  HTML页面系统 103
3.4.1  HTML页面系统简介 103
3.4.2  HTML页面源码 104
3.4.3  入口文件main.ts 105
3.5  异步资源加载及同步操作 107
3.5.1  使用Promise封装HTTP异步请求 107
3.5.2  实现AsyncLoadTestApplication类 109
3.5.3  异步run函数的覆写(override)与测试 110
3.5.4  Promise.all异步并发加载及同步操作 111
3.5.5  本书后续的资源加载及同步策略 114
3.6  本章总结 114
第4章  WebGL基础 116
4.1  WebGL中的类 116
4.2  准备工作 117
4.2.1  创建WebGLRenderingContext对象 117
4.2.2  WebGLContextAttributes对象与帧缓冲区 118
4.2.3  渲染状态 120
4.2.4  WebGLContextEvent事件 121
4.3  基本几何图元绘制Demo 122
4.3.1  视矩阵、投影矩阵、裁剪和视口 122
4.3.2  GLSL ES着色语言 123
4.3.3  WebGLShader对象 126
4.3.4  GLSL ES精度限定符与WebGLShaderPrecisionFormat对象 128
4.3.5  WebGLProgram对象 130
4.3.6  WebGLActiveInfo对象 132
4.3.7  WebGLUniformLocation对象 134
4.3.8  WebGLBuffer对象 137
4.3.9  渲染数据存储思考 140
4.3.10  Interleaved数组的存储、寻址及绘制 141
4.3.11  drawArrays绘制基本几何图元 144
4.3.12  详解基本几何图元 146
4.3.13  drawElements绘制方法 149
4.4  本章总结 152
第5章  WebGLUtilLib渲染框架 153
5.1  WebGLUtilLib框架类结构体系 153
5.2  GLAttribState类的实现 155
5.2.1  预定义顶点属性常量值 156
5.2.2  GLAttribState类的bit位操作 157
5.2.3  getInterleavedLayoutAttribOffsetMap方法 158
5.2.4  getSequencedLayoutAttribOffsetMap方法 160
5.2.5  getSepratedLayoutAttribOffsetMap方法 161
5.2.6  getVertexByteStride方法 162
5.2.7  setAttribVertexArrayPointer方法 163
5.2.8  setAttribVertexArrayState方法 164
5.3  GLProgram相关类的实现 166
5.3.1  常用的VS和FS uniform变量 166
5.3.2  GLProgram的成员变量和构造函数 167
5.3.3  loadShaders方法 168
5.3.4  绑定和解绑GLProgram 169
5.3.5  载入uniform变量 170
5.3.6  GLProgramCache类 171
5.3.7  GLShaderSource对象 172
5.3.8  初始化常用的着色器 173
5.4  GLMesh相关类的实现 174
5.4.1  VAO对象与GLMeshBase类 174
5.4.2  GLStaticMesh类实现细节 175
5.4.3  GLMeshBuilder类成员变量 178
5.4.4  GLMeshBuilder类构造方法 179
5.4.5  GLMeshBuilder类的color、texcoord、normal和vertex方法 181
5.4.6  GLMeshBuilder类的begin和end方法 184
5.5  GLTexture类的实现 187
5.5.1  GLTexture的成员变量和构造函数 187
5.5.2  GLTexture类的upload方法 188
5.5.3  mipmap相关的静态方法 189
5.5.4  GLTexture的bind / unbind、wrap和filter方法 190
5.5.5  GLTexture的createDefaultTexture静态方法 191
5.6  本章总结 192
第6章  3D图形中的数学基础 193
6.1  坐标系 193
6.1.1  OpenGL / WebGL中的坐标系 193
6.1.2  左手坐标系与右手坐标系 194
6.2  TSM数学库 196
6.3  向量 197
6.3.1  向量的概念 197
6.3.2  向量的大小(或长度) 198
6.3.3  两个向量之间的距离 199
6.3.4  单位向量 199
6.3.5  向量的加法 199
6.3.6  向量的减法 200
6.3.7  向量的缩放 201
6.3.8  负向量 202
6.3.9  向量的点乘 202
6.3.10  向量的叉乘 203
6.4  矩阵 204
6.4.1  矩阵的定义 205
6.4.2  矩阵的乘法 205
6.4.3  单位矩阵 206
6.4.4  矩阵的转置 207
6.4.5  矩阵的行列式与求逆 207
6.5  仿射变换 208
6.5.1  平移矩阵 209
6.5.2  缩放矩阵 209
6.5.3  绕任意轴旋转矩阵 210
6.6  视图矩阵与投影矩阵 211
6.6.1  视图(摄像机)矩阵 212
6.6.2  投影矩阵 213
6.7  四元数 214
6.8  平面 215
6.8.1  构造平面 216
6.8.2  平面的单位化 217
6.8.3  点与平面的距离与关系 217
6.9  矩阵堆栈 218
6.9.1  构造函数与worldMatrix属性 219
6.9.2  矩阵的入栈、出栈及load方法 219
6.9.3  仿射变换操作 220
6.10  摄像机 220
6.10.1  成员变量和构造函数 221
6.10.2  摄像机的移动和旋转 222
6.10.3  摄像机的更新 224
6.10.4  摄像机的相关属性 225
6.11  WebGLCoordSystem类 227
6.12  本章总结 228
第7章  多视口渲染基本几何体、坐标系及文字 230
7.1  使用GLMeshBuilder多视口渲染基本几何体 230
7.1.1  Demo的需求描述 230
7.1.2  Demo的成员变量和构造函数 231
7.1.3  drawByMatrixWithColorShader方法绘制流程 233
7.1.4  使用INTERLEAVED顶点存储格式绘制三角形 234
7.1.5  使用SEQUENCED顶点存储格式绘制四边形 235
7.1.6  使用SEPARATED顶点存储格式绘制立方体 236
7.1.7  创建多视口的方法 239
7.1.8  WebGL中的纹理坐标系 240
7.1.9  drawByMultiViewportsWithTextureShader方法绘制流程 240
7.1.10  绘制纹理立方体 242
7.1.11  实现Atlas纹理贴图效果 243
7.1.12  收尾工作 245
7.2  坐标系、文字渲染及空间变换Demo 246
7.2.1  Demo的需求描述 246
7.2.2  Demo的成员变量和构造函数 247
7.2.3  生成单视口或多视口坐标系数组 248
7.2.4  覆写(override)更新和渲染虚方法 249
7.2.5  覆写(override)键盘事件处理虚方法 250
7.2.6  drawFullCoordSystem方法 250
7.2.7  drawFullCoordSystemWithRotatedCube方法 252
7.2.8  DrawHelper类的drawFullCoordSystem方法 254
7.2.9  深度测试对坐标系绘制的影响 255
7.2.10  drawText方法 256
7.2.11  MathHelper类的obj2GLViewportSpace方法 258
7.2.12  3D图形中的数学变换流水线 258
7.3  本章总结 259
第3篇  开发实战
第8章  解析与渲染Quake3 BSP场景 262
8.1  Q3BspApplication入口类 262
8.2  解析Quake3 BSP二进制文件 264
8.2.1  Quake3BspParser类的常量定义 264
8.2.2  Q3BSPLump结构定义 265
8.2.3  解析BSP文件头 266
8.2.4  解析实体字符串数据 267
8.2.5  解析材质数据 269
8.2.6  解析顶点数据 270
8.2.7  解析顶点索引数据 273
8.2.8  解析渲染表面数据 273
8.2.9  Quake3与WebGL坐标系转换 276
8.3  渲染Quake3 BSP场景 277
8.3.1  Quake3BspScene的初始化 278
8.3.2  DrawSurface对象 278
8.3.3  封装Promise加载所有纹理 279
8.3.4  生成GLStaticMesh对象 280
8.3.5  绘制整个BSP场景 282
8.4  本章总结 283
第9章  解析和渲染Doom3 PROC场景 285
9.1  Doom3Application入口类 285
9.2  解析Doom3 PROC场景 286
9.2.1  Doom3词法解析规则 287
9.2.2  IDoom3Tokenizer词法解析器 287
9.2.3  Doom3 PROC文件格式总览 288
9.2.4  Doom3ProcParser的parse方法 289
9.2.5  Doom3Area、Doom3Surface及Doom3Vertex类 290
9.2.6  Doom3ProcParser的_readArea方法 292
9.2.7  Doom3ProcParser的_readSurface方法 293
9.2.8  Doom3ProcParser的_readPortals方法 295
9.2.9  Doom3ProcParser的_readNodes方法 297
9.3  使用Doom3ProcScene加载和渲染PROC场景 298
9.3.1  RenderSurface对象 299
9.3.2  Doom3ProcScene的draw方法 299
9.3.3  Doom3ProcScene类的loadTextures方法 300
9.3.4  Doom3ProcScene的parseDoom3Map方法 301
9.4  AABB包围盒 303
9.4.1  AABB包围盒与OBB包围盒的特点 304
9.4.2  构建AABB包围盒 304
9.4.3  计算AABB包围盒的9个顶点坐标值 306
9.4.4  计算变换后的AABB包围盒 307
9.4.5  AABB包围盒的两个常用碰检算法 307
9.5  摄像机视截体 308
9.5.1  摄像机视截体的概念 308
9.5.2  Frustum类的成员变量和构造函数 309
9.5.3  buildFromCamera方法的实现 310
9.5.4  让Camera类支持Frustum 312
9.5.5  Frustum与包围盒及三角形的可见行测试 313
9.5.6  让GLStaticMesh支持包围盒 314
9.5.7  更新Doom3ProcScene的draw方法 314
9.5.8  将Frustum绘制出来 315
9.5.9  Doom3ProcScene类增加包围盒绘制方法 316
9.6  本章总结 316
第10章  解析和渲染Doom3 MD5骨骼蒙皮动画 318
10.1  骨骼蒙皮动画原理 318
10.1.1  骨骼蒙皮动画效果演示 319
10.1.2  骨骼蒙皮动画中的各种坐标系 320
10.1.3  骨骼蒙皮动画数学关键点的问答 321
10.2  解析和渲染.md5mesh文件格式 322
10.2.1  .md5mesh文件解析流程 323
10.2.2  .md5mesh中的绑定姿态 324
10.2.3  解析绑定姿态 325
10.2.4  .md5mesh中的蒙皮数据 326
10.2.5  解析蒙皮数据 329
10.2.6  计算顶点最终位置 330
10.2.7  加载和生成纹理 331
10.2.8  绘制绑定姿态(BindPose) 332
10.3  解析和渲染.md5anim文件格式 333
10.3.1  .md5anim的解析流程 333
10.3.2  解析.md5anim中的关节层次信息 334
10.3.3  解析.md5anim中的包围盒数据 336
10.3.4  解析.md5anim中的baseframe数据 337
10.3.5  解析.md5anim中的frame数据 338
10.3.6  帧动作姿态结构 339
10.3.7  MD5Anim类的buildLocalSkeleton方法 340
10.3.8  MD5Anim类的updateToModelSpaceSkeleton方法 342
10.3.9  MD5SkinedMesh类的playAnim方法 342
10.3.10  MD5SkinedMesh的drawAnimPose方法 343
10.4  实现MD5SkinedMeshApplication Demo 344
10.5  本章总结 346
第1章  SystemJS与Webpack 2

媒体评论

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》从图形基础算法原理出发,用非常浅显易懂的语言讲解相关知识点,然后深入浅出地分析经典案例,一步步带带领读者领略3D图形算法及架构的精彩世界。

——中国工业设计研究院西南中心院长  覃霁

作者通过通俗易懂的讲解,将他十几年图形编程经验的精华浓缩至《TypeScript图形渲染实战:基于WebGL的3D架构与实现》中。书中对TypeScript编程语言、3D图形及其数学基础都有较为全面的剖析,能够让广大读者较为系统地掌握HTML 5 WebGL图形开发的核心技术。

——上海灵禅网络科技股份有限公司CEO  兰海文                                      

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》涉猎广泛,内容深刻,讲解深入浅出,囊括了TypeScript基本语法、图形渲染机制、图形学、数据结构、设计模式等内容,是一本不可多得的HTML 5图形开发书籍。

——上海凯英网络科技有限公司副总裁  何鑫

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》带给读者多个WebGL绘图API开发案例。对于热衷于图形学或游戏开发的相关读者而言,《TypeScript图形渲染实战:基于WebGL的3D架构与实现》不仅是一本通俗易懂的TypeScript入门书,更是一本优秀的3D图形学工具书。

——成都手领科技有限公司创始人兼CTO、迷雾侦探/AI-LIMIT游戏技术负责人  张锐

一本优秀的计算机图书,能够让读者从其文字中感受到作者的态度。相信读者也能够从《TypeScript图形渲染实战:基于WebGL的3D架构与实现》中体会到作者多年来所坚持的技术钻研精神。

——《全局光照技术》作者  秦春林

传统图形编程都是基于DirectX/OpenGL。而Web时代,HTML 5 Canvas2D/WebGL TypeScript的组合才是*的图形编程方案。作者基于多年的实战经验编写了《TypeScript图形渲染实战:基于WebGL的3D架构与实现》,让读者能够较为轻松地理解图形编程的奥秘和编写技巧。阅读完《TypeScript图形渲染实战:基于WebGL的3D架构与实现》后,不但能让萌新程序员一览大佬庖丁解牛的风姿,从而获得巨大的提升,而且也能让老的图形程序员巩固提升,收获满满。

——《Go语言从入门到进阶实战》作者、慕课网讲师、资深全栈游戏开发者  徐波

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》介绍的TypeScript与WebGL相关技术可以构建你梦想中的3D WebApplication。全书通过8个完整的图形编程案例,可以让你了解并掌握3D图形编程的数学基础与核心技术。

—— 跨平台开源UI引擎FairyGUI作者  萧应棠

前沿

笔者在《TypeScript图形渲染实战:基于WebGL的3D架构与实现》的姊妹篇《TypeScript图形渲染实战:2D架构设计与实现》一书中使用了微软最新的TypeScript语言,以面向接口及泛型的编程方式,采用HTML 5中的Canvas2D绘图API,实现了一个2D动画精灵系统,并在该精灵系统上演示了精心设计的与图形数学变换相关的Demo。《TypeScript图形渲染实战:基于WebGL的3D架构与实现》中,笔者将继续带领读者学习TypeScript图形渲染的相关知识。《TypeScript图形渲染实战:基于WebGL的3D架构与实现》主要解决的是基于WebGL的3D图形架构与实现。

3D图形编程是一个庞大的主题,从宏观角度,笔者将整个3D图形编程分为三个层次,即画出来、画得美和画得快。《TypeScript图形渲染实战:基于WebGL的3D架构与实现》定位于画出来,目的是让读者使用TypeScript语言及WebGL 3D API编写一个WebGLApplication应用程序框架及WebGLUtilLib封装库,来渲染id Software公司的Quake3及Doom3这两个引擎的场景和骨骼动画格式。通过《TypeScript图形渲染实战:基于WebGL的3D架构与实现》,可以让各位读者了解3D图形渲染底层最原始的运行流程。

读者能学到什么

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》最大的特点是专注于使用TypeScript语言和WebGL API(应用程序接口),来渲染id Software公司最经典的Quake3和Doom3引擎的场景和骨骼蒙皮动画文件格式。全书通过8个完整的Demo来探索和演示3D图形渲染的基础知识。

通过阅读《TypeScript图形渲染实战:基于WebGL的3D架构与实现》,读者能掌握以下知识:

?    构建TypeScript的开发、编译及调试环境;

?    使用TypeScript封装或实现常用的容器对象;

?    实现一个支持刷新、重绘、事件分发与响应、定时回调及异步/同步资源加载的WebGLApplication框架体系;

?    使用WebGL 1.x版中内置的各个常用对象;

?    将WebGL 1.x中的一些常用操作封装成可重复使用的类库(WebGLUtilLib);

?    使用开源的TSM(TypeScript Vector And Matrix Math Library)数学库;

?    用单视口和多视口自由切换来渲染基本的几何体、坐标系,并在WebGL环境中正确地使用Canvas2D进行文本绘制;

?    进行远程加载、解析和渲染Quake3 BSP二进制场景文件;

?    进行远程加载、解析Doom3 PROC场景文件,并实现基于视锥体与AABB级别的可见性测试场景渲染功能;

?    深入理解骨骼蒙皮动画的数学原理,并成功地解析和渲染Doom3中的MD5骨骼动画格式。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》有何特色

?    深入:凝聚作者15年3D图形编程经验,带领读者探索3D图形编程的知识;

?    系统:使用TypeScript构建Application应用程序框架及WebGL渲染框架;

?    广泛:涉及数据结构、WebGL渲染API用法、3D数学、二进制文件读取、骨骼动画及场景渲染等内容;

?    独特:使用TypeScript和WebGL渲染API来演示Quake3、Doom3引擎的场景和骨骼动画渲染;

?    实用:详细讲解8个完整的3D图形Demo,帮助读者理解3D图形渲染最本质的运行流程。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》内容

第1篇  数据结构基础(第1、2章)

第1章SystemJS与webpack,以循序渐进的方式介绍了如何构建基于SystemJS和webpack的TypeScript语言开发、编译和调试环境,最终形成一个支持源码自动编译、模块自动载入、服务器端热部署、具有强大断点调试功能、能自动打包的TypeScript开发环境。

第2章TypeScript封装和实现常用容器,主要涉及与数据结构相关的知识点。首先讲解了JS/TS中新增的ArrayBuffer、DataView及与类型数组相关的知识点,然后封装和实现了动态类型数组、字典、双向循环列表、队列、栈及通用树结构。

第2篇  WebGL图形编程基础(第3~7章)

第3章WebGLApplication框架,通过本书第一个WebGL Demo来演示一个支持不停刷新、重绘、事件分发与响应、具有定时效果的WebGLApplication框架体系的使用流程。该框架支持使用ES 6.0标准中的async/await机制进行资源加载。

第4章WebGL基础,通过一个WebGL基本几何图元绘制的Demo,详细介绍了WebGLContextEvent、WebGLContextAttribut、WebGLRenderingContext、WebGLShader、WebGLProgram、WebGLShaderPrecisionFormat、WebGLActiveInfo、WebGLUniformLocation和WebGLBuffer这9个类的作用和常用方法。读者可以重点关注WebGLBuffer的3种不同渲染数据存储模式。

第5章WebGLUtilLib渲染框架,介绍了多个与WebGL相关的类。其中,GLProgram类用来编译、链接GLSL ES GPU Shader源码,并提供载入uniform变量的相关操作;GLStaticMesh对象用于绘制静态物体;GLMeshBuilder对象可以用于绘制动态物体;GLTexuture类可以在GLStaticMesh或GLMeshBuilder生成的网格对象上进行纹理贴图操作。

第6章3D图形中的数学基础,通过介绍开源TSM(TypeScript Vector And Matrix Math Library)数学库,让读者掌握向量、矩阵、四元数等相关的3D数学知识,并在TSM库的基础上实现了平面、摄像机、矩阵堆栈及GLCoordSystem等后续Demo要用到的类。

第7章多视口渲染基本几何体、坐标系及文字,使用WebGLApplication框架及WebGLUtilLib库实现了两个Demo。其中,第一个Demo使用GLMeshBuilder类在多视口中渲染基本几何体;第二个Demo则用来演示3D图形中坐标系的各种变换效果,并通过使用Canvas2D来绘制文字,从而解决WebGL中文字绘制的短板问题。

第3篇  开发实战(第8~10章)

第8章解析与渲染Quake3 BSP场景,首先在Quake3BspParser类的实现中介绍了如何使用DataView对象进行Quake3 BSP二进制文件解析,然后实现Quake3BspScene类。Quake3BspScene类可以将需要渲染的数据编译成GLStaticMesh对象支持的格式,从而正确地显示Quake3 BSP场景。

第9章解析和渲染Doom3 PROC场景,主要介绍了如何解析和渲染Doom3 PROC场景文件。首先实现了用Doom3SceneParser类进行场景文件的解析;然后实现了用Doom3ProcScene类进行场景文件的渲染;最后对场景的渲染增加视截体的可见性测试,从而提升WebGL的绘制效率。

第10章解析和渲染Doom3 MD5骨骼蒙皮动画,主要介绍了如何解析和渲染Doom3引擎中的MD5骨骼蒙皮动画。首先通过问答的方式介绍了骨骼动画中4个与坐标系相关的问题;然后解析并绘制.md5mesh文件;最后介绍.md5anim动画文件格式,并实现动画序列的显示播放。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》配套资源获取方式

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》涉及的源代码文件和Demo需要读者自行下载。请登录华章公司网站www.hzbook.com,在该网站上搜索到本书,然后单击“资料下载”按钮,即可在页面上找到“配书资源”下载链接。

运行书中的源代码需要进行以下操作:

(1)按照本书第1章中的介绍下载并安装Node.js和VS Code。

(2)在VS Code的终端对话框中输入npm install命令,自动下载运行依赖包。

(3)下载好依赖包后继续输入npm run watch。

(4)在VS Code中新建一个终端面板,输入npm run dev。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》读者对象

?    对3D图形编程、WebGL图形开发、游戏开发感兴趣的技术人员;

?    想转行做图形开发和WebGL开发的技术人员;

?    需要全面学习3D图形开发的技术人员;

?    想从其他强类型语言(C、C 、Java、C#、Objective-C等)转HTML 5开发的技术人员;

?    JavaScript程序员;

?    想了解TypeScript的程序员;

?    想提高编程水平的人员;

?    在校大学生及喜欢计算机编程的自学者;

?    专业培训机构的学员。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》阅读建议

?    没有3D图形框架开发基础的读者,建议从第1章顺次阅读并演练每一个实例;

?    有一定3D图形开发基础的读者,可以根据实际情况有重点地选择阅读各个模块和项目案例;

?    对于每一个模块和项目案例,先思考一下实现思路,然后再阅读,学习效果更好;

?    可以先对书中的模块和Demo阅读一遍,然后结合《TypeScript图形渲染实战:基于WebGL的3D架构与实现》提供的源码再进行理解,并亲自运行和调试,这样理解起来就更加容易,也会更加深刻。

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》作者

《TypeScript图形渲染实战:基于WebGL的3D架构与实现》由步磊峰编写。感谢在《TypeScript图形渲染实战:基于WebGL的3D架构与实现》编写和出版过程中给予了笔者大量帮助的各位编辑!

由于作者水平所限,加之写作时间较为仓促,书中可能还存在一些疏漏和不足之处,敬请各位读者批评指正。

……

免费在线读

第3章  WebGLApplication框架
对于一个HTML 5图形应用程序来说,不管是Canvas2D或是WebGL,都需要一个Application框架体系结构。在该体系结构中,最重要的功能是进行动画更新(动画更新包含基于时间的状态更新,以及更新状态后的重绘显示)。除此之外,还需要一些其他功能。为了更好地说明,先提供Application的功能体系结构图,如图3.1所示,以及用于代码实现的类结构图,如图3.2所示。
(无法传图)
图3.1  Application体系结构
(无法传图)
图3.2  Application体系类结构图
3.1  Application体系结构概述
参考图3.1,对于WebGL图形渲染来说,需要一个可控的、不断更新的动画运行机制。在该运行机制中可以:
? 控制动画系统的启动,查询动画是否运行,以及可以停止运行中的动画。
? 在动画系统运行期间,可以进行例如帧率计算(Frame Per Second,FPS)、基于时间差的更新、重绘及每帧触发一次frameCallback回调事件(让第三方实现者有机会做一些他想做的事情)。
? 将系统输入事件(鼠标事件和键盘事件)转换成自己定义的事件系统,并进行分发和响应。
将上述功能全部封装到一个名为Application的类中。接下来从程序实现的角度来看一下Application的类体系结构。如图3.2所示,Application是一个抽象基类,封装了上面所述的3个功能。
这3个功能是通用的,不管是Canvas2DApplication(由于本书关注WebGL,因此并没将Canvas2DApplication类在图3.2中绘制出来)还是WebGLApplication应用程序,都需要用到。
WebGLApplication类在Application类的基础上增加了用于渲染3D图形的WebGLRenderContext的成员变量(gl),以及同时可以用于2D渲染的CanvasRendering Context2D(ctx2D)成员变量。在本书中,ctx2D存在的主要价值是进行2D文字绘制,将会在后续章节中详解。
?注意:WebGL中渲染文字是一个比较艰巨的任务,感谢CanvasRenderingContext2D的存在,让我们可以用一种方便的方式解决WebGL中文字绘制的问题。
在OpenGL 1.1固定管线渲染时代,有两个笔者认为很棒的功能,即矩阵堆栈和立即渲染模式(经典的glBegin/glEnd渲染模式)。然而进入到OpenGL 2.0时代(或OpenGLES 2.0),由于固定管线被GPU可编程管线(后面会介绍可编程管线的相关内容)替代,所以将矩阵堆栈及立即渲染模式都取消了。
?注意:WebGL规范是基于OpenGLES规范的,因此也取消了矩阵堆栈和立即渲染模式。
矩阵堆栈和立即渲染模式这两个功能可以非常快速地进行原型开发、Debug显示,以及从视觉方面验证程序的正确性,因此我们在后续章节中会自行实现GLWorldMatrixStack类和GLMeshBuilder类来分别模拟OpenGL 1.1中的矩阵堆栈和立即渲染模式,并将这两个类作为WebGLApplication的成员变量,这样能在WebGLApplication中直接进行相关操作。
最后一个类是CameraApplication。该类继承自WebGLApplication,因此获得了基类的所有功能,并且增加了摄像机漫游的功能。在CameraApplication中,覆写了基类的onKeyPress事件,可以使用键盘控制摄像机的各种移动及朝向。本书的大部分Demo都是继承自CameraApplication这个类。
3.2  第一个WebGL Demo
在实现Application体系结构之前,我们先通过一个简单的Demo来体验一下Application及其子类的一些关键的功能,从而有一个感性的认识。
3.2.1  技术要点描述
结合如图3.1、图3.2和图3.3所示的内容,来描述一下第一个WebGL Demo要演示的与Application框架系统相关的技术点。
(1)我们的Demo继承自CameraApplication,CameraApplication则继承自WebGL Application,而WebGLApplication又继承自Application。
(2)参考图3.3中的立方体(Cube),该立方体贴着纹理贴图(Texture)。而纹理贴图中的像素(Pixel)数据来自于服务器端存储的图像(PNG或JPG格式)。在HTML中,图像从服务器加载是一个异步过程,而我们的WebGL渲染器需要在图像(Image)文件加载完成后才能进行绘制,因此会在源码中使用TS/JS的Promise/async/await相关技术来进行异步资源加载及同步操作。
(无法传图)
图3.3  第一个WebGL Demo效果图
(3)图3.3左上角显示了FPS:60的字样,目的是为了演示图3.1不停刷新step->fps帧率计算/不停刷新step->回调frameCallback这两个功能。
(4)图3.3中不停刷新step->更新update中分为两种不同的刷新方式,其中:
第一种是基于屏幕刷新频率的更新,我们在Demo中主要通过覆写Application的update虚方法,让图3.3中的立方体不停地绕绿色的Y轴旋转。
第二种是基于自行实现的定时器的回调更新,在Demo中通过两处进行演示:
? 图3.3右侧旋转的立方体具有三套纹理,每隔2秒钟进行周而复始的换肤操作,其效果如图3.4所示。
? 图3.3左侧显示的三角形,当我们按Q键时,会新增加一个定时器,每隔0.25秒让三角形绕着Z轴旋转1°。当我们按E键时,将删除掉定时器,此时三角形不再继续绕着Z轴进行旋转。
通过上述内容,可以了解基于屏幕刷新频率的固定更新操作与基于多个定时器,以不同时间间隔进行更新的操作。
(5)显然,所有的可显示对象(文字,立方体,X、Y、Z坐标轴及三角形)的绘制都是在render方法中,该方法覆写(override)了Application中的同名虚方法(不停刷新step->重绘render)。
(6)图3.3中文字的显示,使用了基类WebGLApplication中提供的ctx2D成员变量来进行文字的显示。
(7)图3.3中的三角形(Triangle)的显示使用了我们自己封装的类似OpenGL1.1中glBegin/glEnd那种立即绘制模式的类GLMeshBuilder。三角形及立方体的平移和旋转操作使用了矩阵堆栈。
(8)我们的Demo的基类是CameraApplication。在CameraApplication中封装了一个摄像机类Camera,并且重载了基类的onKeyPress虚方法,按W、S、A、D、Z、X键可以前后左右上下移动摄像机;按Y、P、R键则分别进行摄像机的Yaw(绕Y轴)/Pitch(绕X轴)/Roll(绕Z轴)旋转,这是键盘事件的应用。
(无法传图)
图3.4  立方体换肤效果
3.2.2  Demo的成员变量与构造函数
Demo名为RotatingCubeApplication,该Demo继承自CameraApplication。关于该Demo的成员变量以及构造函数参考代码如下:
 
export class RotatingCubeApplication extends CameraApplication
{
    // GPU可编程管线对象,后面章节详解,本书中带GL开头的类都是自行对WebGL进行的二
       次封装
    colorProgram: GLProgram;   // 使用纹理GPU Program对象
    textureProgram: GLProgram; // 使用颜色GPU Program对象
    // 纹理对象
    currTexIdx: number; // 由于cube会进行周而复始的换纹理操作,因此需要
      记录当前纹理的索引号
    textures: GLTexture2D[]; // 需要一个数组保存多个纹理
    cube: Cube;   // 几何体的数据表达式
    cubeVAO: GLStaticMesh; // 几何体的渲染数据源
    // 立方体的角运动相关变量
    cubeAngle: number;   // cube的角位移
    cubeSpeed: number;   // cube的角速度
    cubeMatrix: mat4;   // 合成的cube的世界矩阵
    // 三角形
    triAngle: number;   // 三角形的角位移
    triSpeed: number;   // 三角形的角速度
    triTimerId: number; // 由于三角形使用键盘来控制更新方式,需要添
      加和删除操作,需要定时器id
    triMatrix: mat4; // 合成的三角形的世界矩阵
    private _hitAxis: EAxisType; // 为了支持鼠标点选,记录选中的坐标轴的
      enum值
 
    public constructor ( canvas: HTMLCanvasElement )
    {
        // 调用基类构造函数,最后一个参数为true,意味着我们要创建一个Canvas2D上下
           文渲染对象
        // 这样我们才能使用该上下文对象进行2D文字渲染
        super( canvas, { premultipliedAlpha: false }, true ); 
        // 初始化角位移和角速度
        this.cubeAngle = 0;
        this.triAngle = 0;
        this.cubeSpeed = 100;
        this.triSpeed = 1;
        this.triTimerId = -1;
        this.currTexIdx = 0;
        this.textures = [ ];
        // 我们在WebGLApplication基类中内置了default的纹理贴图
        this.textures.push( GLTextureCache.instance.getMust( "default" ) );
        // 创建封装后的GLProgram类
        // 我们在WebGLApplication基类中内置texture/color的GLProgram对象
        this.textureProgram = GLProgramCache.instance.getMust( "texture" );
        this.colorProgram = GLProgramCache.instance.getMust( "color" );
        // 创建cube的渲染数据
        // 对于三角形的渲染数据,我们使用GLMeshBuilder中立即模式绘制方式
        this.cube = new Cube( 0.5, 0.5, 0.5 );
        let data: GeometryData = this.cube.makeGeometryData();
        this.cubeVAO = data.makeStaticVAO( this.gl );
        this._hitAxis = EAxisType.NONE; // 初始化时没选中任何一条坐标轴
        // 初始化时,世界矩阵都为归一化矩阵
        this.cubeMatrix = new mat4();
        this.triMatrix = new mat4();
        // 调整摄像机的位置
        this.camera.z = 8;
    }
}
 
注释比较详细,请读者自行阅读理解。
3.2.3  资源同步加载
接下来看在Application框架体系中如何从服务器同步加载图像数据。
在Application基类中,我们声明了一个带async关键字的方法,该方法的内容代码如下:
 
// 虚函数,子类覆写(overide),用于同步各种资源后启动Application
public async run (): Promise
{
    // 调用start方法,该方法会启动requestAnimationFrame
    // 然后不停地进行回调
    this.start();
}
 
该方法是使用async关键字来声明的,因此它肯定是个异步方法,会返回一个Promise对象(这里返回Promise
)。设计该方法的目的是为了让子类进行覆写(override),然后在函数体内进行各种异步资源的同步操作,在全部异步资源加载完成后,才启动Apllication进行更新与渲染。下面来看一下RotatingCubeApplication是如何使用该方法来同步的,代码如下:
 
// 覆写(override)基类同名方法,进行资源同步
public async run (): Promise
{
    // await必须要用于async声明的函数中
    let img: HTMLImageElement = await HttpRequest.loadImageAsync
( "./data/blocks15.jpg" );
    let tex: GLTexture2D = new GLTexture2D( this.gl );
    tex.upload( img );
    this.textures.push( tex );
    console.log( "1、第一个纹理载入成功!" );
    // await必须要用于async声明的函数中
    img = await HttpRequest.loadImageAsync( "./data/p1.jpg" );
    tex = new GLTexture2D( this.gl );
    tex.upload( img );
    this.textures.push( tex );
    console.log( "2、第二个纹理载入成功!" );
    // 在资源同步加载完成后,直接启动换肤的定时器,每隔2秒,将立方体的皮肤进行周而复
       始的替换
    this.addTimer( this.cubeTimeCallback.bind( this ), 2, false );
    console.log( "3、启动Application程序" );
    super.run(); // 调用基类的run方法,基类run方法内部调用了start方法
}
 
运行上述方法,就能获得如图3.5所示的结果,并且整个WebGL的渲染都是在纹理加载后进行的,这符合我们的需求。
(无法传图)
图3.5  资源同步加载输出结果
在3.5节中将会更加深入地介绍Promise、async和await的相关知识点。
3.2.4  立方体、坐标系、三角形及文字渲染
当启动Application的run方法后,就会进入不停地更新和渲染流程。先来看一下如何显示本节Demo中的4个形体。
(1)立方体和坐标轴的显示源码如下:
 
private _renderCube (): void
{
    // 绑定要绘制的texutre和program
    this.textures[ this.currTexIdx ].bind();
    this.textureProgram.bind();
    this.textureProgram.loadSampler();
    // 绘制立方体
    this.matStack.loadIdentity();
    // 第一个渲染堆栈操作
    {
        this.matStack.pushMatrix(); // 矩阵进栈
        this.matStack.rotate( this.cubeAngle, vec3.up, false );
  // 以角度(非弧度)为单位,每帧旋转
        // 合成modelViewProjection矩阵
        mat4.product( this.camera.viewProjectionMatrix, this.matStack.
worldMatrix, this.cubeMatrix );
        // 将合成的矩阵给GLProgram对象
        this.textureProgram.setMatrix4( GLProgram.MVPMatrix, this.cubeMatrix );
        this.cubeVAO.draw(); // 使用当前绑定的texture和program
          绘制cubeVao对象
        // 使用辅助方法绘制坐标系
        DrawHelper.drawCoordSystem( this.builder, this.cubeMatrix, this._
hitAxis, 1 );
        this.matStack.popMatrix(); // 矩阵出栈
    }
    // 解除绑定的texture和program
    this.textureProgram.unbind();
    this.textures[ this.currTexIdx ].unbind();
}
 
上述代码中,使用基类WebGLApplication内置的matStack矩阵堆栈对象进行局部坐标系的变换操作,从而最终合成要显示物体的世界坐标系,然后将世界坐标系与摄像机坐标系及投影坐标系合成为MVPMatrix(模型视图投影矩阵,关于这些知识点,后面会详解),然后将合成的MVPMatrix及当前使用的纹理对象投入到GPU可编程管线对象中进行渲染。
对立方体的渲染是通过二次封装的VAO(Vertex Array Object)对象进行的,关于这些二次封装过的WebGL对象,会在后续章节中详解。
当渲染好立方体后,调用DrawHelper.drawCoordSystem(后续章节详解)这个自行实现的绘图辅助方法进行坐标轴的绘制显示。
(2)使用GLMeshBuilder进行三角形绘制,代码如下:
 
private _renderTriangle (): void
    {
        // 禁止渲染三角形时启用背面剔除功能
        this.gl.disable( this.gl.CULL_FACE );
        // 由于三角形使用颜色 位置信息进行绘制,因此要绑定当前的GPU Program为
           colorProgram
        this.colorProgram.bind();
        {
            this.matStack.pushMatrix(); // 新产生一个矩阵
            // 立方体绘制在Canvas的中心
            // 而三角形则绘制在向左(负号)平移两个单位处的位置
            this.matStack.translate( new vec3( [ -2, 0, 0 ] ) );
            // 使用弧度,绕Z轴进行Roll旋转
            this.matStack.rotate( this.triAngle, vec3.forward, true );
            // 使用类似OpenGL1.1的立即绘制模式
            this.builder.begin(); // 开始绘制,defatul使用gl.TRIANGLES
              方式绘制
            this.builder.color( 1, 0, 0 ).vertex( -0.5, 0, 0 );
  // 三角形第一个点的颜色与坐标
            this.builder.color( 0, 1, 0 ).vertex( 0.5, 0, 0 );
  // 三角形第二个点的颜色与坐标
            this.builder.color( 0, 0, 1 ).vertex( 0, 0.5, 0 );
  // 三角形第三个点的颜色与坐标
            // 合成model-view-projection matrix
            mat4.product( this.camera.viewProjectionMatrix, this.matStack.
worldMatrix, this.triMatrix );
            // 将mvpMatrix传递给GLMeshBuilder的end方法,该方法会正确地显示图形
            this.builder.end( this.triMatrix );
            this.matStack.popMatrix(); // 删除一个矩阵
        }
        this.colorProgram.unbind();
        // 恢复背面剔除功能
        this.gl.enable( this.gl.CULL_FACE );
}
 
注释比较详细,请读者自行理解。
(3)使用Canvas2D绘制文字,代码如下:
 
// 关于Canvas2D的详细应用,可以参考本书的姐妹篇
//  TypeScript图形渲染实战:2D架构设计与实现
    private _renderText ( text: string, x: number = this.canvas.width * 0.5,
y: number = 150 ): void
    {
        if ( this.ctx2D !== null )
        {
            this.ctx2D.clearRect( 0, 0, this.canvas.width, this.canvas.
height );
            this.ctx2D.save(); // 渲染状态进栈
            this.ctx2D.fillStyle = "red";   // 红色
            this.ctx2D.textAlign = "center";   // X轴居中对齐
            this.ctx2D.textBaseline = op; // Y轴为top对齐
            this.ctx2D.font = "30px Arial"; // 使用大一点的Arial字体对象
            this.ctx2D.fillText( text, x, y ); // 进行文字绘制
            this.ctx2D.restore(); // 恢复原来的渲染状态
        }
    }
 
(4)覆写(override)render方法,并调用上述实现的3个方法进行显示,具体代码如下:
 
public render (): void
{
    // 切记,一定要先清屏(清除掉颜色缓冲区和深度缓冲区)
    this.gl.clear( this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT );
    this._renderCube();
    this._renderTriangle();
    this._renderText( "第一个WebGL Demo" );
}
 
至此完成了整个渲染操作流程。运行上述代码,就能显示静态的立方体、坐标系、三角形及文字,接下来我们让整个程序按需求运动起来。
3.2.5  更新操作
动画就是基于时间的状态更新,以及使用更新后的状态进行重回的过程,前面完成了渲染重绘的操作,现在来实现更新相关的操作。
在3.2.1节技术要点描述的第4点中,Demo需要进行两种类型的更新操作,其中第一种类型的更新是基于固定的屏幕刷新频率的更新。对于这种刷新方式,可以直接覆写(override)基类的update方法就可以,代码如下:
 
public update ( elapsedMsec: number, intervalSec: number ): void
{
    // s = v * t,根据两帧间隔更新角速度和角位移
    this.cubeAngle = this.cubeSpeed * intervalSec;
    // 我们在CameraApplication中也覆写(override)的update方法
    // CameraApplication的update方法用来计算摄像机的投影矩阵及视图矩阵
    // 所以我们必须要调用基类方法,用于控制摄像机更新
    // 否则你将什么都看不到,切记
    super.update( elapsedMsec, intervalSec );
}
 
第二种更新是基于不同帧率的多个定时器回调更新,用来定时置换纹理贴图及键盘控制启动或禁止三角形旋转,代码如下:
 
// cubeTimeCallback回调函数的调用是在3.2.3节的run函数中,请参考该部分代码
public cubeTimeCallback ( id: number, data: any ): void
{
    this.currTexIdx ; // 定时让计数器 1
    // 取模操作,让currTexIdx的取值范围为[ 0, 2 ]之间(当前有3个纹理)
    this.currTexIdx %= this.textures.length;
}
// 接下来看一下使用键盘启动或禁止三角形旋转的源码
public triTimeCallback ( id: number, data: any ): void
{
    this.triAngle = this.triSpeed;
}
 
当运行上面的代码时,会发现立方体自转的同时,每2秒钟会换一张纹理贴图,但是三角形仍旧处于静止状态,这是因为我们还没有实现键盘事件处理函数,接下来就来处理键盘和鼠标输入事件。
3.2.6  键盘输入事件处理
先来看一下键盘事件的处理。根据3.2.1节技术要点描述中第4条的需求描述,我们需要按Q键时启动三角形的旋转,而按E键时停止三角形的旋转。下面来看一下如何实现该效果,代码如下:
 
// 覆写(override)基类的同名方法
// 我们在onKeyDown方法中处理Q/E键盘事件
public onKeyDown ( evt: CanvasKeyBoardEvent ): void
{
    if ( evt.key === "q" )
    {
        // 为防止多次重复增删
        if ( this.triTimerId === -1 )
        {
           // 添加定时器,以每0.25秒的速度回调一次triTimeCallback函数
            this.triTimerId = this.addTimer( this.triTimeCallback.bind
( this ), 0.25, false );
        }
    } else if ( evt.key === "e" )
    {
        // 为防止多次重复增删
        if ( this.triTimerId !== -1 )
        {
            if ( this.removeTimer( this.triTimerId ) )
            {
                // 为防止多次重复增删
                this.triTimerId = -1;
            }
        }
    }
}
 
运行上述代码后,就能按照需求运行。这里需要强调一点的是,之所以使用定时器,是因为三角形的旋转并不是按照每秒60帧(基于屏幕刷新频率的更新速度)速度进行的,而是自定义的每秒4帧(每0.25秒回调一次,因此为每秒4帧)。当然你可以自行在update方法中处理,但是由于该功能足够通用,就直接将其封装成定时器对象。
3.2.7  总结Application框架的使用流程
前面的代码演示了Application框架的使用流程,再来总结一下:
(1)自己实现的Demo或项目必须要继承自Application或其子类(Canvas2DApplication / WebGLApplicaiton / CameraApplication)。
(2)如果你不需要资源同步载入后启动Application的不间断动画刷新功能,则可以直接使用start方法,否则就请覆写(override)基类的异步run虚方法,在run方法体内的最后一句代码请使用super.run()进行调用,这样就能启动Application。
(3)可以使用isRunning方法查询Application处于不间断刷新过程中,也可以使用stop方法停止刷新过程。
(4)可以覆写(override)基类的update虚方法,实现基于屏幕刷新频率的更新。如果要以不同的刷新频率进行更新,则请使用定时器回调。
(5)你需要覆写(override)基类的render虚方法,将所有的绘制代码实现在render虚方法中。
(6)输入事件(包括键盘和鼠标事件)处理与分发,请覆写(override)基类以on开头的键盘和鼠标事件虚方法。
综上所述,Application框架系统主要做三件事情:更新、重绘及事件的分发或处理。


对于一个HTML 5图形应用程序来说,不管是Canvas2D或是WebGL,都需要一个Application框架体系结构。在该体系结构中,最重要的功能是进行动画更新(动画更新包含基于时间的状态更新,以及更新状态后的重绘显示)。除此之外,还需要一些其他功能。为了更好地说明,先提供Application的功能体系结构图,如图3.1所示,以及用于代码实现的类结构图,如图3.2所示。

TypeScript图形渲染实战:基于WebGL的3D架构与实现 pdf下载声明

本pdf资料下载仅供个人学习和研究使用,不能用于商业用途,请在下载后24小时内删除。如果喜欢,请购买正版

pdf下载地址

版权归出版社和作者所有,下载链接已删除。如果喜欢,请购买正版!

链接地址:TypeScript图形渲染实战:基于WebGL的3D架构与实现