1、1、 提供了 3 个示例程序,都是导入的同一个 obj 文件(带法向、材质和纹理贴图,分别为obj 文件、mtl 文件和 jpg 文件) ,但 3 个示例程序采用不同的 shader:(1) 无光照无贴图:没有使用光照和纹理映射,只是利用了 obj 文件中的顶点坐标信息,绘制时使用白色,没有 3D 感;(2) 有光照无贴图:使用了光照计算(在片元 shader 中计算光照) ,有 3D 感了;(3) 有光照有贴图:进一步使用了纹理映射,最终的片元颜色根据光照计算的颜色以及纹理图像颜色计算得到,真实感更强了2、 如果用 Chrome 运行示例程序,需要在 Chrome 的快捷方式上添加运行参数:
2、意思是允许访问文件,注意需要通过此快捷方式运行 Chrome 后,再打开示例程序html 文件运行,如果直接右键点 html 文件选用 Chrome 打开,不会用到此快捷方式。不同的浏览器设置不同,自行百度,有的浏览器(如 ie)无需任何设置。3、 在自己的程序中导入 Obj 文件的方法(请对照 3 个示例程序,查看以下步骤内容):(1) 在 Common 中新增 js 文件: ObjModel.js (示例程序中已提供)(2) 在 html 文件中加载 ObjModel.js:(3) 下载 obj 模型,或是自己用 3dsMax 或 Maya 之类的建模软件建模后导出为 obj 模型(注意纹
3、理坐标设为 UV 展开形式 ),用记事本打开 obj 文件和 mtl 文件,注意里面的文件路径是否正确,建议将 obj、mtl 连通纹理图像放在同一个文件夹下,然后 obj 和 mtl 中的文件路径只保留文件名即可:Mtl 文件目前的库只使用了 map_Kd 即漫反射贴图(但实际上在使用时不只影响到漫反射分量的颜色,计算方式可参见示例程序,原理会在后续课程中讲解)(4) 在 js 程序中定义全局变量,同时加载模型:loadOBJ 是 ObjModel.js 中提供的函数,注意参数中的相对路径是相对于 js 文件路径而言的(是转义字符,实际就是 ) ,在此函数中会请求加载该 obj 文件及所有相
4、关文件(mtl 和纹理图像文件),并读取所有文件内容,注意读取方式是异步方式,即 js 程序不会等文件读完,而是继续往下执行;(5) 定义全局 AttribIndex 对象:该对象主要用于存放 shader 中 attribute 变量索引,有 3 个分量,分别存放顶点坐标、顶点法向和纹理坐标的索引(AttribIndex 是在 ObjModel.js 中定义的,下面是ObjModel.js 中的定义代码):(6) 在 shader 中获取相关 shader 变量的索引后,在 main 函数中对 attribIndex 进行初始化:如果有的变量 shader 中没有,则调用 init 时传-1
5、,例如“无光照无贴图”示例中是这样调用的:(7) 如果有用到光照计算,则同样定义存放相关 uniform shader 变量索引的对象:MTLIndex 同样是在 ObjModel.js 中定义的:(8) 同样在 main 函数中获取相关变量索引,并对 mtlIndex 进行初始化:(9) 在绘制函数 render 开始,检查 obj 对象是否一切就绪(含义是相关文件信息是否已全部读取完毕,且为绘制做的准备工作也做完了,例如 buffer 的初始化、纹理对象的初始化等等) ,如果读取完毕,则进一步处理,如果没有一切就绪,则请求重绘并返回,不进行后续绘制工作。(如果场景中包含很多对象,也可以先只
6、绘制其他对象,而 obj 对象在读取完毕后再绘制 ) (10) 调用 obj 对象的 draw 函数进行绘制(注意 draw 之前的代码和 obj 导入无关,根据自己的需求编写,通常需要给 shader 中相关矩阵变量传值 ):draw 函数也是在 ObjModel.js 中定义的,最后一个参数为 shader 中纹理采样器变量的索引,如果没有用光照计算,则第 3 个参数给 null,如果没有用纹理贴图,则最后一个参数给 0。在绘制 obj 模型时,自己不用管纹理相关变量的传值,也不用管材质变量和顶点属性变量的传值,全部封装好了,最主要的工作就是给矩阵传值,用来对模型进行实例化以及设置视角,注
7、意下载的模型有的会很大或很小,需要缩放后才能看到。4、 以上即是导入 Obj 模型的步骤,因为做了很多的封装,使用起来比较方便,感兴趣的同学可以看 ObjModel.js 来了解内部原理,此部分不要求掌握。5、 下载的模型有的很大(一个几十 M 甚至上百 M) ,这种模型不建议在实践作品中使用,因为在导入时需要太久。6、 当导入的 Obj 模型比较多或是文件比较大时,可以尝试在导入 Obj 模型时绘制一个进度条,这次时间不足,昆哥计划在明年再加上了。今年就作为同学们的选作吧,给大家一个思路:(1) 在 render 中未一切就绪时,绘制进度条(两个矩形而已,一个不变,一个另外一种填充颜色的长度不断变化,另外使用不同的视域体(ortho2D 即可))(2) 进度可根据两个方面:一是加载的 Obj 文件数量(根据数量将进度条划分成 n 等份) ,二是在调用 obj 对象的 isAllReady 时查询已解析的文本行数及完成读取的文件数量等信息,返回一个当前 Obj 相关文件的加载进度( 此部分需要修改ObjModel.js 了)