這篇文章主要為大家Threejs 的快速入門,具有一定的參考價值,有興趣的小伙伴們可以參考一下
現在什麼都是3D,看電影3D,打遊戲3D,估計3D搭計程車,很快就會面世。那麼身為前端開發的標準語言,JS和3D能不能也搞出點大新聞呢?剛好最近在做活動時,就遇到了需要播放3D全景影片的需求,順便就研究了一下Threejs,一個用於在瀏覽器中繪製3D圖像的JS庫(https://github.com/mrdoob/three.js),這篇文章算是做個筆記,也希望能幫助那些想快速入門的同學。
首先,在正式學習Threejs之前,有幾個概念需要說明的。 Threejs在底層其實還是呼叫html5中的canvas api來實作繪圖的。但和我們一般繪製2D影像不同,Threejs在底層使用的是canvas的webgl context來實作3D繪圖。 webgl context本身更多是直接對gpu的操作,用起來相當不直觀,為此Threejs在頂層對3D繪圖所需的各種元素(例如場景,攝影機,燈光,幾何圖像,材質等)進行了封裝,如果我們需要使用Threejs來繪圖,只需要創建一個最小繪圖環境 #即可,這個最小繪圖環境包含了三個要素:
1.場景--包含所有需要顯示的3D物件以及其他相關元素的容器
#2.攝影機--決定3D場景如何投影到2D畫布之上
3.渲染器- -用於最後繪製的畫筆
具體的程式碼如下:
<p class="km_insert_code"> import { Scene, PerspectiveCamera, WebGLRenderer } from ‘three’; var scene = new Scene(); // 创建场景 var camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000); // 创建摄影机 camera.position.z = 8; var renderer = new WebGLRenderer(); // 创建渲染器 renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小 renderer.setPixelRatio(window.devicePixelRatio); // 设置像素比,针对高清屏 renderer.setClearColor(0x000000, 1); // 设置默认背景色 document.body.appendChild(renderer.domElement); // 把画笔插入到dom中</p>
簡單的幾句程式碼,就可以建立起一個最小繪圖環境,之後只要我們放入需要顯示的3D對象,這些對象就會被繪製在畫布中,顯示在螢幕上。
3D**物件**
#有了環境,我們還需要告訴Threejs,到底需要顯示什麼物件。為此,我們首先需要定義這個用於顯示的物體,然後把他加入場景中即可。
<p class="km_insert_code"> import { Mesh, MeshBasicMaterial, BoxGeometry } from ‘three’; var geometry = new BoxGeometry(1, 1, 1); // 创建一个长方体,用来定义物体的形状 var material = new MeshBasicMaterial({ color: 0xff0000 }); // 创建一个材质,用来定义物体的颜色 var mesh = new Mesh(geometry, material); // 使用形状和素材,来定义物体 scene.add(mesh); renderer.render(scene, camera);</p>
先看看效果
怎麼感覺好無聊,哈哈哈,但不管怎麼樣,我們已經可以畫出東西來了。
猜大家看了上面的程式碼,一定會有一些疑問,那個texture#是什麼鬼,geometry和material又是用來幹嘛的。其實Threejs在定義一個3D物體時,需要提供兩個信息,第一是形狀信息,也就是這個物體上每一個點,每一個面的坐標信息,第二是材質資訊,用來告訴Threejs物件的顏色,紋理,反光等資訊。有了這些訊息,Threejs才知道要如何渲染這個物件。而上面的new BoxGeometry(1, 1, 1),就是告訴Threejs,我要顯示一個長寬高各為1的長方形。而new MeshBasicMaterial({ color: 0xff0000}),就是要告訴Threejs,這個長方體是紅色的。最後根據形狀和素材,new Mesh(geometry, material),產生需要顯示的物體。
上面提到在Threejs中如果要產生一個長方體,則需要定義一個BoxGeometry,那除了長方體,Threejs還可以產生形狀呢:
#1.BoxGeometry --長方體
2.CircleGeometry--圆形平面
3.CylinderGeometry--圆柱体
4.PlaneGeometry--方形平面
5.RingGeometry--环形平面
6.SphereGeometry--球形
7.TextGeometry--文字
8.TorusGeometry--圆环
9.TubeGeometry--圆管
另外上面写到的MeshBasicMaterial,其实是指一个直接就能显示颜色的材质。什么叫直接显示颜色呢?这里要涉及到Threejs里的灯光设置。物体的材质由于确定物体的颜色,纹理,以及反光等属性。要反光,首先需要有一个光源:
<p class="km_insert_code"> import { SpotLight } from ‘three’; var light = new SpotLight(0xffffff); light.position.z = 5; light.position.x = 5; light.position.y = 5; scene.add(light);</p>
这里我们定义了一个白光源,具体的效果如下:
为了可以看清楚效果,我在场景中加入了一个绿色平面,可以看到,这个绿色平面上的反光是从下到上减弱,可见,这个光源是在画面的下方。
如果我把光源的强度减弱,那么平面上的反光也会跟着减弱:
但不知大家有木有发现,绿色平面上的反光是减弱了,但红色的那个长方体,还是一样的红,完全没有变化。其实这就体现出不同材质的区别了,在红色长方体上,我采用的是MeshBasicMaterial这种材质,而在绿色平面上,我采用的是另一种称为MeshLambertMaterial的材质,这种材质的特点是漫反射强烈,主要用来模拟真实环境下的物体,例如木材,石料等物质的反光情况。另外Threejs还有另外一种材质叫MeshPhongMaterial,这种材质主要是镜面反射强烈,用来模拟镜子,金属等拥有高光的物体就比较合适。
MeshLambertMaterial和MeshPhongMaterial两种材质,都是需要光照才能看到的,如果场景中没有光源,你将会什么都看不到。相反我们在红色长方体上采用的材质是MeshBasicMaterial,这种材质即使没有光,也可以看到,你可以想象为它自己发光吧,如果用技术一点的话来说,就是MeshLambertMaterial和MeshPhongMaterial两种材质需要根据场景光线的数值来计算显示在屏幕上的颜色,而MeshBasicMaterial则忽略光线的作用,是什么颜色,就直接显示什么颜色,但也由于这种材质忽略了光照的作用,那么它也不会有任何阴影的效果。所以这种材质就叫Basic,用来做演示就十分合适。一下就是Threejs提供给我们用到的其他材质
1.MeshBasicMaterial
2.MeshLambertMaterial--漫反射材质
3.MeshPhongMaterial--镜面反射材质
4.MeshDepthMaterial--根据物体上每一点到摄像机的远近来显示颜色,远的显示黑色,近的显示白色
5.MeshNormalMaterial--根据物体上每一面的法向量方向来显示颜色
如果绘制3D物体时,只能使用纯色,那也未免太单调了,没关系,Threejs提供了接口来帮忙解决这个问题。Threejs的材质,除了可以设置颜色,还支持纹理贴图,我们可以把一个图片,覆盖在3D物体上作为他的纹理,这样就可以利用这些贴图来模拟更真实的场景
<p class="km_insert_code"> import { TextureLoader, MeshLambertMaterial } from ‘three’; var texture = new TextureLoader().load(‘./assets/texture/crate.gif’); var material = new MeshLambertMaterial({ map: texture });</p>
上面的代码中,我们通过TextureLoader来加载一个gif图作为纹理,并且把这个纹理通过map属性映射到了材质上,加上材质后,整个物体就更加真实了
3D动画
能绘图了,但如何加入动画呢?其实很简单,在之前的代码中已经讲解过,Threejs是通过渲染器来绘图的,你可以想象成拍照。我们在场景中摆好灯光,摆好道具,渲染器咔嚓一下,就把当前的画面绘制下来了。那如果要做成动画,只需要在渲染器来个定时连拍就可以拉。具体如下。
<p class="km_insert_code"> function render() { requestAnimationFrame(render); update(); renderer.render(scene, camera); } function update() { // update your view } </p>
这里我们通过requestAnimationFrame接口,来做定时刷新,每次进入render方法,都会先去执行update方法(用于更新场景),然后让渲染器拍照(renderer.render(scene, camera)),最后等待下一次render。在update方法中,我们可以修改场景中所有物体的参数,例如,我们可以试着让盒子在屏幕中转动:
<p class="km_insert_code"> function update() { box.rotation.x += 0.005; box.rotation.y += 0.01; } </p>
最后的最后,其实Threejs还有很多额外的能力,例如刚刚我们使用图片作为纹理,那么我们也可以使用视频作为纹理,把这个纹理贴到一个盒子上,通过陀螺仪来控制摄像机的拍摄方向,就可以作出一个全景视频啦。Threejs也支持粒子系统,模型数据导入,自定义着色器等一系列高级功能,大家也赶快掌握起来吧。
以上是Threejs 的快速入門的詳細內容。更多資訊請關注PHP中文網其他相關文章!