记录一下用three.js加载并渲染上海外滩的BIM模型的小demo

<!DOCTYPE html>
<html lang="en"><head><style>body {margin: 0;}p {position: fixed;top: 0;}
</style><script src="lib/three.js"></script><script src="lib/OrbitControls.js"></script><script src="lib/GLTFLoader.js"></script><script src="lib/Water.js"></script></head><body><script src="index.js"></script><p>天空:<input type="checkbox" onchange="skyToggle()" /></p></body>
</html>

用到的three官方库:

  • three.min.js:THREE.js WebGL引擎

  • OrbitControls.js:轨道控制,鼠标控制视角变幻

  • GLTFLoader.js:gltf加载库

  • Water.js:水面效果,纯glsl实现

天空的实现:

天空的实现有多种方式,最常见的是一个包围全部的天空球,通常是UV球,也叫经纬球,其UV很方便映射到一张天空图片,比如:

天空球的所有面的法线必须朝向圆心(默认是朝外),或者渲染的时候采用背面渲染。

第二种方式是天空盒,即将上述的天空球变成一个正方体盒子,好处是减少了许多三角面片,只剩12个面,但通常要准备上下左右前后6张图片来贴合天空盒。比如这样:

与这2种方法相比,性能最好的方案是静态天空球(盒),即理想情况下的宇宙背景,天空球的半径无限大,导致渲染的时候,天空不会因为相机的移动而变化,只随旋转而变化,这样减少了许多计算量。

静态天空球就是360度全景摄像机的原理,它和墨卡托投影有点类似,但是正轴等距圆柱投影,想象一个经纬球,它的经纬线自然展开,UV坐标如下:

可以看到,图中每个矩形的宽高比是1:2,应该把它们都拉伸成正方形,因为赤道:经线=2:1,这样UV贴图的宽高比就是2:1,比如:

图中红线是赤道(圆周),每条竖线是经线(一半圆周),每条纬线都被拉伸至赤道长度。可以看到两极地区被拉伸严重,靠近赤道地区比例正常。

然后将它通过圆柱投影到球面上,或者转换成6张图作为正方体,作为静态天空,代码如下:

async function skyToggle() {if (scene.bgURL === "light.png") {scene.bgURL = "dark.png";} else {scene.bgURL = "light.png";}const texture = await new THREE.TextureLoader().loadAsync(scene.bgURL);const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);rt.fromEquirectangularTexture(renderer, texture);scene.background = rt.texture;
}

然后是加载gltf模型:

const loader = new THREE.GLTFLoader();
const modelLoaded = loader.loadAsync("shanghai.glb", function (xhr) {console.log((xhr.loaded / xhr.total) * 100 + "% loaded");}).then(function (gltf) {console.log("shanghai model:", gltf);const { min, max } = new THREE.Box3().setFromObject(gltf.scene);gltf.scene.position.sub(new THREE.Vector3((min.x + max.x) / 2, min.y, (min.z + max.z) / 2));scene.add(gltf.scene);gltf.scene.getObjectByName("castShadow").traverse((x) => x.isMesh && (x.castShadow = true));gltf.scene.getObjectByName("ground").traverse((x) => x.isMesh && (x.receiveShadow = true));}).catch(function (error) {console.error(error);});

其中让所有的大厦投影,让地面接收投影,实现真实的效果,又避免了所有物体都投影。

其中增加了一个视频plane,作为震旦大厦的大屏动画,plane的4个顶点的UV就是图片的4个角:

const video = document.createElement("video");video.src = "test2.mp4";video.loop = true;video.muted = true;video.playbackRate = 0.6;video.play();const videoPlane = gltf.scene.getObjectByName("video");videoPlane.material = new THREE.MeshBasicMaterial({map: new THREE.VideoTexture(video),});videoPlane.geometry.attributes.uv = new THREE.BufferAttribute(new Uint8Array([0, 0, 1, 0, 0, 1, 1, 1]),2);

视频:

增加海水:

new THREE.TextureLoader().loadAsync("waternormals.jpg").then((waterNormals) => {waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;const water = new THREE.Water(new THREE.PlaneGeometry(1000, 1000), {textureWidth: 512,textureHeight: 512,waterNormals,sunDirection: new THREE.Vector3(),sunColor: 0xffffff,waterColor: 0x001e0f,distortionScale: 3.7,fog: !!scene.fog,});water.material.uniforms.size.value = 10;water.rotation.x = -Math.PI / 2;scene.add(water);tasks.push(() => {water.material.uniforms.time.value += 0.005;});
});

海水法线贴图:

最后再加1个环境光,开启环境光遮蔽,再加一个平行光就好了:

视频来源:https://blog.csdn.net/goodriver1

用three.js渲染上海外滩模型相关推荐

  1. 解决three.js渲染gltf 模型与gltfViewer网站效果不一致问题 krpano发黑问题 three.js gltf模型渲染发黑问题

    解决使用three.js渲染gltf模型与gltfViewer网站上预览不一致的问题: 原因 灯光和环境贴图 直接上代码 function init(e) { //声明初始化函数$("#pr ...

  2. WebGL笔记(六)_Three.js渲染obj模型并同时渲染全景图

    基本思路简述:一个模型的渲染的流程是,创建一个场景,并将模型和相机放到场景中合适的位置:然后就会呈现出一个3D模型在屏幕上.全景图的呈现其实就是在创建一个场景.相机.几何球.模型和全景同时被呈现在屏幕 ...

  3. three.js实现3D模型展示

    开头说明下  文章是转载我同事一个 哥们的.怕自己 以后会用 拿过来  方便以后使用 three.js实现3D模型展示 由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 ...

  4. three.js使用外部模型创建动画,使用GLTF格式文件动画创建动画(vue中使用three.js71)

    使用GLTF格式文件动画创建动画 1.demo效果 2. 实现要点 2.1 加载GLTF文件 2.2 创建AnimationMixer动画 2.3 render中更新动画 3. demo代码 1.de ...

  5. three.js渲染带动画的glb文件(内附源码,保姆级)

    今日份的下午格外的懒惰,本来不想写辣么长长的一串文字了和解释说明的, 但是发文助手提醒我篇幅较短,曝光比较少,该说不说,这有点过分了. 那就一步步来吧哎 最底下附带了案例源文件 1.准备好three. ...

  6. 【Three.js】解决使用Three.js导入obj模型不可见问题详细记录

    问题描述: 近期在做三维重建项目,需要把最终生成的obj文件导入到web端浏览,这里使用的是three.js(另一个是babylon.js),但博主发现导入meshlab生成的obj时无法显示模型,但 ...

  7. Three.js 点击模型,高亮发光模型外轮廓

    最近在开发一个功能,在三维场景里有很多模型,需要点击模型,高亮对应的模型,代表选中了该模型.做起来还是稍微麻烦一些的. 具体效果 实现流程 主要的流程还是, Created with Raphaël ...

  8. Three.js学习六——模型动画

    目录 Three.js动画系统(Animation system) 实现流程 基本流程 工程文件 场景搭建 添加模型 模型动画 动画实现的基本流程 相关对象方法和代码 完整代码和实现效果 Three. ...

  9. 【问题探讨】H5 UI渲染心智模型

    目标 探讨H5 UI渲染心智模型,即阐述数据是依据什么样的逻辑渲染到界面上的. 本文思路 先通过一个示例讲述不同的数据渲染逻辑,然后讲两个延伸DEMO来着重说明CLASS和FUNCTION的特点: 示 ...

  10. QT实现Qt Quick和three.js渲染和实现QML3D控件

    QT实现Qt Quick和three.js渲染和实现QML3D控件 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 结合Qt Quick和three.js渲染. 演示 ...

最新文章

  1. Linux之获取管理员权限的相关命令
  2. spring bean作用域_Srping中Bean的三种装配方式:大魏Java记10
  3. CodeForces - 817D Imbalanced Array(单调栈)
  4. 廖雪峰 练习 把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字...
  5. DNS解析原理与Bind部署DNS服务
  6. 使用php自动将文章标题或内容进行分词,添加和删除标签功能实例!
  7. python 测试开发请关注这个新框架
  8. Oracle 10g升级之--PSU 升级(续)
  9. iOS应用开发模板 iOS Boilerplate
  10. 8)Thymeleaf 基本对象表达式
  11. java小球碰撞界面设计_JavaScript实现小球碰撞特效
  12. 计算机网络冲突窗口,计算机网络基础试题及答案
  13. UML类图画法全程解析
  14. VB编程:SelectCase多分支选择结构实例测试生肖运势-13
  15. .net写加密的com组件给ASP,VB,VC等其他语言调用
  16. 用HTML和CSS3做个鱼,如何使用CSS和D3实现小鱼游动的交互动画(附代码)
  17. 天球坐标系和地球坐标系
  18. 机电信息杂志机电信息杂志社机电信息编辑部2022年第13期目录
  19. 计算机可爱的企鹅教案,北师大版数学一年级上册可爱的企鹅教案
  20. 职业规划与发展部_3D成像原理

热门文章

  1. 项目总结报告(小米商城)
  2. 【修真院“善良”系列之二】产品经理应该懂哪些术语?
  3. 对比Ruby和Python的垃圾回收
  4. python编写程序实现货币转换_使用Tkinter的Python实时货币转换器
  5. 人生若梦,神马都是浮云,,,,,,,
  6. 【NOI2017模拟3.30】原谅
  7. 5G核心网技术基础自学系列 | 与EPC互通
  8. WIN10下 搭建golang+vscode开发环境(图文并茂,傻瓜式教程)
  9. 大数据-Flume(二)
  10. Google Analytics SEO 实时 网站 访问量 统计