本篇文章我们通过介绍3D影院的视觉原理,并介绍了three.js事件处理过程,全面分析了实现3D影院的基础知识。
1.创建一个3d的空间
可以想象一下我们在房间内,房间是一个立方体,如果你有生活品味,可能会在房间内贴上壁纸,three.js可以很方便的创建一个立方体,并且给它的周围贴上纹理,让照相机在立方体之中,照相机可以360旋转,就模拟了一个真实的场景。
转换为代码:
const path = 'assets/image/' const format = '.jpg' const urls = [ `${path}px${format}`, `${path}nx${format}`, `${path}py${format}`, `${path}ny${format}`, `${path}pz${format}`, `${path}nz${format}` ] const materials = [] urls.forEach(url => { const textureLoader = new TextureLoader() textureLoader.setCrossOrigin(this.crossOrigin) const texture = textureLoader.load(url) materials.push(new MeshBasicMaterial({ map: texture, overdraw: true, side: BackSide })) }) const cube = new Mesh(new CubeGeometry(9000, 9000, 9000), new MeshFaceMaterial(materials)) this.scene.add(cube)
CubeGeometry创建一个超大的立方体 MeshFaceMaterial给立方体贴上文理,由于视角是在立方体内部,所以side:BackSide 2.粒子效果
一个3d模型是由点,线,面组成的,可以遍历模型的每一个点,把每一个点转换为几何模型,并且给它贴上文理,拷贝每一个点的位置,用这些几何模型重新构成一个只有点的模型,这就是粒子效果的基本原理。
this.points = new Group() const vertices = [] let point const texture = new TextureLoader().load('assets/image/dot.png') geometry.vertices.forEach((o, i) => { // 记录每个点的位置 vertices.push(o.clone()) const _geometry = new Geometry() // 拿到当前点的位置 const pos = vertices[i] _geometry.vertices.push(new Vector3()) const color = new Color() color.r = Math.abs(Math.random() * 10) color.g = Math.abs(Math.random() * 10) color.b = Math.abs(Math.random() * 10) const material = new PointsMaterial({ color, size: Math.random() * 4 + 2, map: texture, blending: AddEquation, depthTest: false, transparent: true }) point = new Points(_geometry, material) point.position.copy(pos) this.points.add(point) }) return this.points
new Group创建一个群,可以说是粒子的集合通过point.position.copy(pos)设置粒子和位置,坐标和模型中对应点的位置相同 3.点击事件的处理
three.js的点击事件需要借助光线投射器(Raycaster),为了方便理解,请先看一张图:
Raycaster发射一个射线,intersectObject监测射线命中的物体
this.raycaster = new Raycaster() // 把你要监听点击事件的物体用数组储存起来 this.seats.push(seat) onTouchStart(event) { event.preventDefault() event.clientX = event.touches[0].clientX; event.clientY = event.touches[0].clientY; this.onClick(event) } onClick(event) { const mouse = new Vector2() mouse.x = ( event.clientX / this.renderer.domElement.clientWidth ) * 2 - 1 mouse.y = - ( event.clientY / this.renderer.domElement.clientHeight ) * 2 + 1; this.raycaster.setFromCamera(mouse, this.camera) // 检测命中的座位 const intersects = this.raycaster.intersectObjects(this.seats) if (intersects.length > 0) { intersects[0].object.material = new MeshLambertMaterial({ color: 0xff0000 }) } }
intersects.length > 0 表示射线命中了某个几何体偷懒只实现了移动端的点击实现,如果想看pc怎么实现,请看thee.js官网
4.着色器的初步使用
着色器分为顶点着色器和片元着色器,用GLSL语言编写,是一种和GPU沟通的的语言,这里只讲如何使用
const vertext = ` void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } ` const fragment = ` uniform vec2 resolution; uniform float time; vec2 rand(vec2 pos) { return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0)); } vec2 rand2(vec2 pos) { return rand(rand(pos)); } float softnoise(vec2 pos, float scale) { vec2 smplpos = pos * scale; float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x; float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x; float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x; float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x; vec2 a = fract(smplpos); return mix( mix(c0, c1, smoothstep(0.0, 1.0, a.x)), mix(c2, c3, smoothstep(0.0, 1.0, a.x)), smoothstep(0.0, 1.0, a.y)); } void main(void) { vec2 pos = gl_FragCoord.xy / resolution.y; pos.x += time * 0.1; float color = 0.0; float s = 1.0; for(int i = 0; i < 8; i++) { color += softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0; s *= 2.0; } gl_FragColor = vec4(color); } ` // 设置物体的质材为着色器质材 let material = new ShaderMaterial({ uniforms: uniforms, vertexShader: vertext, fragmentShader: fragment, transparent: true, })
5.光晕效果
由于是模拟电影院,我想做一个投影仪,模拟投影仪射出的光线。
// 光晕效果必须设置alpha = true const renderer = this.renderer = new WebGLRenderer({alpha: true, antialias: true}) let textureFlare = new TextureLoader().load('assets/image/lensflare0.png') let textureFlare3 = new TextureLoader().load('assets/image/lensflare3.png') let flareColor = new Color(0xffffff) let lensFlare = new LensFlare(textureFlare, 150, 0.0 , AdditiveBlending, flareColor) lensFlare.add(textureFlare3, 60, 0.6, AdditiveBlending); lensFlare.add(textureFlare3, 70, 0.7, AdditiveBlending); lensFlare.add(textureFlare3, 120, 0.9, AdditiveBlending); lensFlare.add(textureFlare3, 70, 1.0, AdditiveBlending); lensFlare.position.set(0, 150, -85)
主要的光线还是靠lensflare0.png模拟 textureFlare3设置光晕的范围
本文向大家介绍three.js中3D视野的缩放实现代码,包括了three.js中3D视野的缩放实现代码的使用技巧和注意事项,需要的朋友参考一下 通过Threejs基础学习——修改版知道创建一个相机的相关知识点 视野角:fov 这里视野角(有的地方叫拍摄距离)越大,场景中的物体越小,视野角越小,场景中的物体越大 纵横比:aspect (3d物体的宽/高比例) 相机离视体积最近的距离:near 相
本文向大家介绍three.js实现3D模型展示的示例代码,包括了three.js实现3D模型展示的示例代码的使用技巧和注意事项,需要的朋友参考一下 由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 先看看效果: three.js整体来说 不是很难 只要你静下心来研究研究 很快就会上手的 首先我们在页面上需要创建一个能够放置3D模型的画布 也可以说是初始化 Thre
本文向大家介绍Three.js实现3D机房效果,包括了Three.js实现3D机房效果的使用技巧和注意事项,需要的朋友参考一下 3D机房系统是最近用户的需求,通过相关了解最后使用Three.js,也发现最近有东西可以写出来分享: webGL可以让我们在canvas上实现3D效果。而three.js是一款webGL框架,由于其易用性被广泛应用 Three.js是通过对WebGL接口的封装与简化而形成
本文向大家介绍Spring HandlerInterceptor实现原理代码解析,包括了Spring HandlerInterceptor实现原理代码解析的使用技巧和注意事项,需要的朋友参考一下 HandlerInterceptor 在这里看到这个HandlerExecutionChain对interceptor的调用,在这里深入看一下。 HandlerExecutionChain 就是一个类,绑
本文向大家介绍three.js实现3D视野缩放效果,包括了three.js实现3D视野缩放效果的使用技巧和注意事项,需要的朋友参考一下 首先,不再废话了,什么是three.js,是干什么的,知道的就是知道,不知道的就百度吧。 小编为大家推荐一篇:Three.js快速入门教程 昨儿发现three.js中的3D视野的缩小和放大效果可以用照相机的远近焦来实现。 缩小后: 这里采用的是透视照相机: 在这里
本文向大家介绍Three.js实现简单3D房间布局,包括了Three.js实现简单3D房间布局的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Three.js实现简单3D房间布局的具体代码,供大家参考,具体内容如下 废话不说了,直接上成果图。 代码如下 通过Enter键可控制开门和关门动作。门的旋转是通过,把门克隆一份,把克隆的那个设置为不可见,然后把两个门打个组 ,这个时候中旋转