随着时间的推移技术的进步,前端愈来愈杂了,可是也愈来愈精彩了。只是会用一点ThreeJs,对于WebGl的原理并没了解过,这并不影响咱们利用ThreeJs去作出一个很是炫酷的项目。javascript
开始
新世界的大门打开啦!css
写在前面
不要由于不了解就被这种3D展现的项目给吓到 其实实现起来很简单 很简单 很简单
城市模型一份 最好是gltf模型,obj模型也没问题,我会介绍如何转化与压缩 PS:为何只有这俩,由于我写这个项目只用到了这俩,处理的经验也是针对这俩的,我项目中所用的模型是公司全部暂不能提供。
有必定ThreeJs的基础 俗话说得好 万丈高楼平地起嘛 若是没有这方面基础的同窗也不要急 推荐一本书《THREE.JS开发指南》,有基础也有提升 很棒
本文所示代码大部分只是思路 我也是第一次上手用ThreeJs处理模型并应用到项目中,可能有少量不足之处,还望各路大神指正教导
项目进行一半的时候,由于没经验,我发现让建模看着地图建模的思路是不对的,应该让他们利用geoJson做为地理数据,去建模,建造出来的更精确,并且能够利用地理坐标和世界坐标去关联(猜测),利于项目开发,毕竟第一次,这个锅我背了
Threejs的文档是不全的,不少控制器,loader,后期处理都没有文档,要本身多看看Threejs的examples,不少效果均可以基于Demo去实现
单页面应用必定要清除ThreeJs 的建立的对象,避免内存泄露,能dispose的dispose,多个children的要遍历remove掉 并且里面的 material 和geometry也要删掉,最近刚知道一个取消占用的妙招,WEBGL_lose_context
后期处理对显卡有必定要求
最好一次渲染,不要屡次渲染
HTML部分
Threejs-city-model-showname="viewport"
content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
/>
color: #fff;
margin: 0px;
overflow: hidden;
}
建立场景
首先,咱们要祭出ThreeJs的最重要的几大组件——scene(场景)、camera(相机)、renderer(渲染器) 、light(灯光),以及渲染的目标——container(就是DOM结构),老生常谈,很少说html
打个比方,scene就是舞台,camera就是拍摄舞台的摄像机,它能决定观众看到什么,而一个舞台没有灯光的话它就是黑乎乎的,因此light就是舞台上的各类灯光,因此舞台上表演什么,就是舞台中有什么,因此要加入到scene中 scene.add(“演员们(模型)”)前端
var camera, scene, renderer;
var container;
var ambientLight, pointLight;
// 初始化
init()
// 循环渲染每一帧 一帧一帧的 就是你打游戏时的FPS
animate()
function init(){
// 初始化相机
// 这里使用的是透视相机来模拟人眼看到的效果 近大远小
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.z = 70;
camera.position.x = 50;
camera.position.y = 10;
// 初始化场景
scene = new THREE.Scene();
// 初始化灯光
// 环境光 能保持总体都是亮点
ambientLight = new THREE.AmbientLight(0x404040)
// 点光源 就像灯泡同样的效果 白色灯光 亮度0.6
pointLight = new THREE.PointLight(0xffffff, 0.6);
// 将灯光加入到场景中
scene.add(ambientLight)
// 将灯光加到摄像机中 点光源跟随摄像机移动
// 为何这样作 由于这样可让后期处理时的辉光效果更漂亮
camera.add(pointLight);
// 咱们将摄像机加入到场景中
scene.add(camera);
// 初始化渲染器
renderer = new THREE.WebGLRenderer({
// 开启抗锯齿
antialias: true,
// 开启背景透明
alpha: true
});
// 把自动清除颜色缓存关闭 这个若是不关闭 后期处理这块会不能有效显示
// 书上的描述是 若是不这样作,每次调用效果组合器的render()函数时,以前渲染的场景会被清理掉。经过这种方法,咱们只会在render循环开始时,把全部东西清理一遍。
renderer.autoClear = false;
// 背景透明 配合 alpha
renderer.setClearColor(0xffffff, 0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// 伽马值启动 更像人眼观察的场景
renderer.gammaInput = true;
renderer.gammaOutput = true;
// 渲染到DOM中去
container = document.createElement("div");
container.appendChild(renderer.domElement);
document.body.appendChild(container);
}
// 这样一来,基础场景建立就完成了,接下来咱们来让它循环渲染起来
function animate() {
// 这个方法低版本浏览器兼容很差 能够从github上找些兼容库 若是要兼容低版本浏览器
requestAnimationFrame(animate);
// 渲染咱们的场景 摄像机啪啪啪的拍和录
// 因为把renderer autoClear 关闭了 因此咱们要在渲染函数中手动清除
renderer.clear();
renderer.render(scene, camera);
}
// ok 基础部分完成 接下来咱们来加载模型
加载城市模型
限于经验和技术等各类外力因素影响,项目最开始时编写demo使用的是Obj模型和Mtl贴图文件(不太肯定贴图文件的叫法是否准确),使用起来也很简单(ThreeJs仓库里的webgl_loader_obj_mtl.html拿来改下就好了)vue
Threejs-city-model-showname="viewport"
content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
/>
color: #fff;
margin: 0px;
overflow: hidden;
}
// 加载的过程
var onProgress = function(xhr) {
if (xhr.lengthComputable) {
var percentComplete = (xhr.loaded / xhr.total) * 100;
console.log(Math.round(percentComplete, 2) + "% downloaded");
}
};
var onError = function() {
// 载入出错时候
};
// 加载Mtl贴图文件
new THREE.MTLLoader()
// 贴图文件的路径
.setPath("models/obj/male02/")
.load("male02_dds.mtl", function(materials) {
// 看代码意思是预加载
materials.preload();
// 加载OBJ模型
new THREE.OBJLoader()
// 设置OBJ模型的材质贴图
.setMaterials(materials)
.setPath("models/obj/male02/")
.load(
"male02.obj",
function(object) {
object.position.y = -95;
scene.add(object);
},
onProgress,
onError
);
});
这一步通常会出现的问题有以下java
模型加载后,不显示也不报错?
检查场景是否正常渲染了,若是正常渲染模型的位置在哪里,摄像机在哪里,摄像机是否对着模型,灯光是否配置,模型是否太大或者过小了,超出了摄像机的摄影范围……
模型能够正常加载,可是贴图不显示?
首先检查network是否报404错误,若是报错,通常都是mtl贴图文件(看起来像是雪碧图那种)没给你,或者路径配置的不是相对路径,若是贴图没错误,模型是黑色的,在mtl文件中能够更改ka或kd的三个值(对应rgb),或者打印出模型属性,在material.color中更改点色值或别的属性。黑色的时候,看不到贴图。通常这样一通操做以后,就能看到了模型了
模型文件太大了,浏览器在渲染的时候进程被彻底卡死!要等待几十秒之久!天呐!
这个问题看起来比较棘手,其实很好解决。ThreeJs官方推荐gltf格式的模型在浏览器中渲染,由于它是为浏览器而生的,性能好,体积小。咱们项目中使用的模型文件,一开始是Obj和Mtl的,