第四章 使用three.js加載以圖片為紋理的模型(上)
在前言中我們介紹過,我們一般不用three.js自帶的三維模型創建函數去拼湊我們想要的三維模型,而是使用類似Blender一樣的三維建模工具去定制三維模型,然后導出為three.js可以識別的jason格式,加載顯示。通過這種方式,我們可以構建較為原始的三維模型在瀏覽器端顯示,比如我們前面看到的馬克杯模型。如果單純依靠三維建模去逼近現實世界中的形體外觀是很難的,細節的修繕將給3D建模帶來巨大的工作量,同時也會導致模型的加載器計算量巨大,不僅對人還是機器都是巨大的挑戰。
好在我們可以另辟蹊徑,不去追求模型的精細度,而在模型的紋理上做文章,尤其當我們用真實物體的照片作為模型紋理的時候,3D模型的效果立刻就得到了極大的提高,比如這個箱體模型:
如果不考慮外表圖片紋理,它只是一個簡單的立方體模型。加上紋理之后,幾乎和我們在一些制作精良的3D游戲中見到的箱體所差無幾了。下面我們來分析它的代碼:
1 //兼容各種瀏覽器的animation函數 2 window.requestAnimFrame = (function(callback){ 3 return window.requestAnimationFrame || 4 window.webkitRequestAnimationFrame || 5 window.mozRequestAnimationFrame || 6 window.oRequestAnimationFrame || 7 window.msRequestAnimationFrame || 8 function(callback){ 9 window.setTimeout(callback, 1000 / 60); 10 }; 11 })(); 12 13 // 實現旋轉的動畫函數 14 function animate(lastTime, angularSpeed, three){ 15 // 動畫更新時以時間為基准 16 var date = new Date(); 17 var time = date.getTime(); 18 var timeDiff = time - lastTime; 19 // 角度以弧度為單位 20 var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000; 21 three.cube.rotation.y += angleChange; 22 lastTime = time; 23 24 // 重新渲染 25 three.renderer.render(three.scene, three.camera); 26 27 // 角度參數在第一次調用時設定 28 requestAnimFrame(function(){ 29 animate(lastTime, angularSpeed, three); 30 }); 31 } 32 33 window.onload = function(){ 34 var angularSpeed = 0.2; 35 var lastTime = 0; 36 37 // 渲染器 38 var renderer = new THREE.WebGLRenderer(); 39 renderer.setSize(window.innerWidth, window.innerHeight); 40 document.body.appendChild(renderer.domElement); 41 42 // 攝像機 43 var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000); 44 camera.position.z = 700; 45 46 // 場景 47 var scene = new THREE.Scene(); 48 49 // 以圖片為紋理的材質,這是關鍵點 50 var material = new THREE.MeshLambertMaterial({ 51 map: THREE.ImageUtils.loadTexture("crate.jpg") 52 }); 53 54 // 立方體模型 55 var cube = new THREE.Mesh(new THREE.CubeGeometry(300, 300, 300), material); 56 cube.overdraw = true; 57 scene.add(cube); 58 59 // 加入環境光 60 var ambientLight = new THREE.AmbientLight(0x555555); 61 scene.add(ambientLight); 62 63 // 加入方向光 64 var directionalLight = new THREE.DirectionalLight(0xffffff); 65 directionalLight.position.set(1, 1, 1).normalize(); 66 scene.add(directionalLight); 67 68 // 把以上創建3D模型的要素都包裝成一個對象 69 var three = { 70 renderer: renderer, 71 camera: camera, 72 scene: scene, 73 cube: cube 74 }; 75 76 // 使用onload回調函數啟動動畫,這樣能保證圖片被完全加載后才開始旋轉 77 var textureImg = new Image(); 78 textureImg.onload = function(){ 79 animate(lastTime, angularSpeed, three, this); 80 }; 81 textureImg.src = "crate.jpg"; 82 };
與之對應的html代碼如下:
1 <!DOCTYPE HTML> 2 <html lang="en"> 3 <head> 4 <style> 5 body { 6 margin: 0px; 7 overflow: hidden; 8 } 9 </style> 10 </head> 11 <body> 12 <script src="http://mrdoob.github.com/three.js/build/three.min.js"></script> 13 <script src="LoadCrate.js"></script> 14 </body> 15 </html>
這個紋理圖片可以在這里下載:http://www.html5canvastutorials.com/demos/webgl/html5_canvas_webgl_texture/crate.jpg
這篇文章也參考自:http://www.html5canvastutorials.com/webgl/html5-canvas-webgl-texture-with-three-js/
作為一個系列中的一篇,相信這篇文章能夠讓初學者有效的向前推進一步,邁向three.js自由應用的大門!
在下一篇里,我們將分析如何給一個用Blender制作的,較為復雜的模型貼圖顯示在瀏覽器端。
另外,實踐中我們發現,可以使用Chrome瀏覽器加載本地的WebGL模型中的素材,只需要在啟動Chrome的時候加上一下參數:--allow-file-access-from-files --disable-web-security
或許只加--allow-file-access-from-files就足夠了。方法如下圖所示:
這樣以來我們就可以隨意選擇自己偏愛的瀏覽器去調試three.js程序了。