three.js伪入门教程之旋转的九尾妖狐

WebGL是一项利用JavaScript API呈现3D计算机图形的技术,其原生API灵活且高性能,但是这些优点的代价就是入门困难,在后续文章我会慢慢和大家分享我学习WebGL的感悟和心得。three.js是一个封装了WebGL API的轻量级库,官方称是其为傻瓜而生的(难道我连傻瓜都不如么……,学习起来略吃力丫)。本文将通过介绍使用three.js在浏览器里渲染一只旋转的九尾妖狐模型引导大家入门three.js。

目标读者

熟悉javascript,无图形编程经验的开发人员。

示例下载

示例的源代码,模型,纹理都可以在这里下载(访问密码58a5)。

效果预览

gif录制设置为10帧/s,实际效果更流畅。


获取模型和纹理文件

本小节可跳过,如果你的电脑上没有安装英雄联盟,maya,photoshop的话……
如果你天生爱折腾,那么我们一步一步来获取英雄联盟游戏里英雄的模型和纹理吧。
  1. 打开英雄联盟安装目录,比如C:/Program Files/腾讯游戏/英雄联盟体验服,打开目录下的Game文件夹,里面你会发现很多压缩包,所有英雄的模型和纹理就在这些压缩包里。比如本文使用的是九尾妖狐模型是CharacterSkins.zip解压后的DATA/Characters/Ahri/Skins/Skin04/Ahri_Skin04.skn文件,而纹理是CharacterTextures.zip解压后的DATA/Characters/ahri/skins/skin04/Ahri_Skin04_TX_CM.dds。如果你想提取其他英雄的,可以到其他相似的路径里寻找。好,现在你已经找到了skn和dds文件,把它们拷贝到你喜欢的文件夹里去。
  2. 点击这个链接下载maya插件riotfiletranslator。这个插件允许你将skn格式文件导入到maya中去。如果你安装的是maya2014,或许你应该使用这个链接来下载插件。
  3. 如果你安装的是maya2011~2013,解压压缩包,将MayaFolder里的icons和scripts文件夹复制到maya安装目录下。将plugin文件夹里和你版本相符的mll文件复制到maya安装目录下的bin/plug-ins里。打开maya,点击菜单栏里的窗口——设置/首选项——插件管理器,将riotfiletranslator.mll和objExport.mll的已加载和自动加载勾选起来。
  4. maya菜单栏点击文件——导入,导入你喜欢英雄的skn文件。将状态栏上的模块选择器修改为多边形模块。选中你的模型,菜单栏点击法线——反向。OK,现在可以导出你的模型了。选中你的模型,菜单栏点击文件——导出当前选择,文件名随意,文件格式改为OBJexport,可以保存了。
  5. 点击这个链接(32位)或这个链接(64位)下载并安装photoshop插件NVIDIA Texture Tools。这个插件允许你将dds格式文件导入到ps中去。用ps打开你喜欢英雄的dds文件,将图像大小修改为2048px*2048px。最后将图像导出为jpg格式。
如果你坚持完成了以上步骤,恭喜你,你获得了你喜欢英雄的obj模型文件和jpg图像纹理。如果你懒的动手,示例下载里已经包含了九尾妖狐的模型和纹理。

three.js伪入门

为了能显示出物体,three.js需要三种东西:场景(scene),摄像机(camera)和渲染器(renderer)(或许这就是three.js名称的由来,谁知道呢)。创建了场景后你就可以往场景里添加物品,比如在场景里放一个白炽灯(点光源),放一个箱子(由六面网格构成),然后由摄像机实时记录,最后渲染器渲染出摄像机拍下的画面。
下面我们来看看怎么让九尾妖狐显现在我们的浏览器里。
        //在形成完整的DOM树后触发函数
        addEventListener("DOMContentLoaded", function () {
            //创建场景
            var scene = new THREE.Scene(),
                //创建透视摄像机,参数分别代表视场角,屏幕宽高比,视锥近截面,视锥远截面
                camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 2000),
                //创建渲染器
                renderer = new THREE.WebGLRenderer(),
                //创建纹理
                texture = new THREE.Texture(),
                //创建环境光,参数为十六进制的颜色
                ambientLight = new THREE.AmbientLight(0xaaaaaa),
                //创建定向光源,参数为十六进制的颜色
                directionalLight = new THREE.DirectionalLight(0xffeedd),
                imgURL = "ahri.jpg",
                objURL = "ahri.obj",
                obj = null;
            //将摄像机向z轴(屏幕外)移动260
            camera.position.z = 260;
            //设置视口大小
            renderer.setSize(innerWidth, innerHeight);
            //指定定向光源由z正半轴射向原点(平行光从屏幕外射向屏幕中心)
            directionalLight.position.set(0, 0, 1);
            //承诺在图片纹理和模型加载完后调用函数,values[0]为图片对象,values[1]为模型对象
            Promise.all([loadImage(), loadObject()]).then(function (values) {
                //指定纹理使用的图片
                texture.image = values[0];
                //纹理在创建后发生了改变(由上一语句引发),必须设置needsUpdate属性为true
                texture.needsUpdate = true;
                obj = values[1];
                //遍历模型对象的属性,指定纹理
                obj.traverse(function (child) {
                    if (child instanceof THREE.Mesh) {
                        child.material.map = texture;
                    }
                });
                //将模型下移一些,使其能居中
                obj.position.y = -70;
                //将模型,环境光,定向光源添加入场景
                scene.add(obj);
                scene.add(ambientLight);
                scene.add(directionalLight);
                document.body.appendChild(renderer.domElement);
                //开始渲染
                render();
                function render() {
                    //高性能循环渲染
                    requestAnimationFrame(render);
                    //每次渲染前将模型沿Y轴旋转0.05
                    obj.rotation.y += 0.05;
                    //渲染
                    renderer.render(scene, camera);
                }
            });
            //图片加载函数
            function loadImage() {
                //承诺加载完成后返回图片对象
                return new Promise(function (resolve) {
                    new THREE.ImageLoader().load(imgURL, resolve);
                });
            }
            //模型加载函数
            function loadObject() {
                //承诺加载完成后返回模型对象
                return new Promise(function (resolve) {
                    new THREE.OBJLoader().load(objURL, resolve);
                });
            }
        });


或许你可以这么想象,在一个漆黑的夜里,阿狸在山上冷得在不停的转圈,月亮刚爬上山头,月光从正前方照亮阿狸……
好吧,以上都是我无聊的想象。你可以下载示例然后在chrome浏览器里观看。如果你有任何疑问或发现错误请在下面留言评论。如果你从中受益请期待博主的webgl系列,下个webgl系列文章将不使用three.js,从webgl基础说起……

你可能感兴趣的:(WebGL)