1. 程式人生 > >67 - three.js 筆記 - 使用 bumpMap 凹凸貼圖建立皺紋

67 - three.js 筆記 - 使用 bumpMap 凹凸貼圖建立皺紋

凹凸貼圖用於為材質增加厚度,在三維環境中使表面產生凹凸不平的視覺效果。
它主要的原理是通過改變表面光照的法線。凹凸貼圖是一種灰度影象素的密集程度定義的是凹凸的程度。凹凸貼圖只包含畫素的相對高度,不包含傾斜方向的資訊,凹凸貼圖不會改變物體的形狀。

1、示例

示例
http://ithanmang.com/threeJs/home/201809/20180905/04-bump-texture.html
效果
這裡寫圖片描述
可以看左邊添加了凹凸貼圖的立方體明顯和右邊的不一樣,左邊的牆體看上去多了一些細節。
但是這種細節只是針對於正面,並不包含傾斜效果
這裡寫圖片描述
傾斜之後二者的效果是一樣的。

2、實現步驟

2.1、bumpMapbumpScale 屬性

bumpMap:建立凹凸貼圖的紋理,黑色和白色的值對映到與燈光相關的感知深度。bump並不會影響物體的幾何形狀,只有照明。如果定義了正常的對映,則將忽略它。
bumpScale: 凹凸的高度,預設為1,範圍在1 - 0之間

2.2、建立例項並設定材質的bumpMap屬性
let loader = new THREE.TextureLoader();
let bump = loader.load('../../textures/general/' + bumpUrl);
material.bumpMap = bump;

3、示例程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="icon" href="../../../three.png">
    <title>使用 凹凸 貼圖載入皺紋</title>
    <style>
        body {
            margin: 0;
            overflow: hidden; /* 溢位隱藏 */
        }

        #loading
{ position: fixed; top: 50%; left: 50%; color: #FFFFFF; font-size: 20px; margin-top: -30px; margin-left: -40px; }
</style> <script src="../../libs/build/three-r93.js"></script> <script src="../../libs/examples/js/Detector.js"></script> <script src="../../libs/examples/js/libs/dat.gui.min.js"></script> <script src="../../libs/examples/js/libs/stats.min.js"></script> <script src="../../libs/examples/js/controls/OrbitControls.js"></script> </head> <body> <p id="loading">loading......</p> <script> let scene, camera, renderer, controls, guiControls; let stats = initStats(); /* 場景 */ function initScene() { scene = new THREE.Scene(); scene.background = new THREE.Color(0x050505); } /* 相機 */ function initCamera() { camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000); camera.position.set(0, 0, -50); camera.lookAt(new THREE.Vector3(0, 0, 0)); } /* 渲染器 */ function initRender() { renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); } /* 燈光 */ function initLight() { scene.add(new THREE.AmbientLight(0x0c0c0c)); let spotLight1 = new THREE.SpotLight(0xffffff); spotLight1.position.set(-400, -400, -400); let spotLight2 = new THREE.SpotLight(0xffffff); spotLight2.position.set(400, 400, 400); scene.add(spotLight1); scene.add(spotLight2); } /* 控制器 */ function initControls() { /* 地圖控制元件 */ controls = new THREE.OrbitControls(camera, renderer.domElement); /* 屬性引數 */ } /* 除錯外掛 */ function initGui() { guiControls = new function () { this.bumpScale = box1.material.bumpScale; }; let gui = new dat.GUI(); gui.add(guiControls, 'bumpScale', -10, 1).onChange(function (e) { box1.material.bumpScale = e; }); } /* 場景中的內容 */ let box1; let box2; function initContent() { box1 = createMesh(new THREE.BoxGeometry(10, 10, 10), 'stone.jpg', 'stone-bump.jpg'); box2 = createMesh(new THREE.BoxGeometry(10, 10, 10), 'stone.jpg'); box1.translateX(7); box2.translateX(-7); scene.add(box1); scene.add(box2); removeLoading(); } /* 移除載入元素 */ function removeLoading() { document.getElementById('loading').style.display = 'none'; } /* 建立帶有紋理的網格 */ function createMesh(geometry, imageUrl, bumpUrl) { let loader = new THREE.TextureLoader(); let texture = loader.load('../../textures/general/' + imageUrl); let material = new THREE.MeshPhongMaterial(); material.map = texture; if (bumpUrl !== undefined) { let bump = loader.load('../../textures/general/' + bumpUrl); material.bumpMap = bump; } let mesh = new THREE.Mesh(geometry, material); return mesh; } /* 效能外掛 */ function initStats() { let stats = new Stats(); document.body.appendChild(stats.domElement); return stats; } /* 視窗變動觸發 */ function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } /* 資料更新 */ function update() { stats.update(); controls.update(); } /* 初始化 */ function init() { if (!Detector.webgl) Detector.addGetWebGLMessage(); initScene(); initCamera(); initRender(); initLight(); initControls(); initContent(); initGui(); /* 監聽事件 */ window.addEventListener('resize', onWindowResize, false); } /* 迴圈渲染 */ function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); update(); } /* 初始載入 */ (function () { console.log("three init start..."); init(); animate(); console.log("three init end..."); })(); </script> </body> </html>